Webseite, Community-Forum und Adminbereich für den Zugsimulator Connected Rails.
| Bereich | Technologie |
|---|---|
| Backend | C# / .NET 10, ASP.NET Core, EF Core, MariaDB 11.8 |
| Frontend | React 19, TypeScript, Vite, Tailwind CSS 4, TipTap |
| Betrieb | Docker Compose, nginx |
Die vollständige Planung liegt in docs/; die Umsetzung folgt
docs/12-umsetzungsplan.md, der Fortschritt steht in
docs/CHANGELOG-IMPL.md.
Grundsätze: DSGVO-konform, keine Drittanbieter-Ressourcen zur Laufzeit, selbst gehostete Schriften, Forum nach dem Vorbild von WoltLab Suite Forum.
backend/ .NET-Solution (Api, Core, Infrastructure, Tests)
frontend/ React-SPA (Vite)
deploy/ Docker-Compose, Dockerfiles, nginx
docs/ Planungsdokumentation
- .NET SDK 10.0
- Node.js 22+ und pnpm 10+ (
npm i -g pnpmodercorepack enable pnpm) - Docker mit Compose-Plugin
# 1. Umgebungsdatei anlegen und Werte anpassen
cp deploy/.env.example deploy/.env
# 2. Infrastruktur starten (MariaDB auf :3306, Mailpit auf :8025)
docker compose -f deploy/docker-compose.dev.yml up -d
# 3. Backend starten (API auf http://localhost:5000, Swagger unter /api/docs)
cd backend && dotnet run --project src/ConnectedRails.Api
# 4. Frontend starten (http://localhost:5173, Proxy /api → :5000)
cd frontend && pnpm install && pnpm devcd backend && dotnet build && dotnet test
cd frontend && pnpm lint && pnpm typecheck && pnpm test && pnpm buildcd backend
dotnet ef migrations add <Name> -p src/ConnectedRails.Infrastructure -s src/ConnectedRails.Api
dotnet ef database update -p src/ConnectedRails.Infrastructure -s src/ConnectedRails.ApiBereits ausgelieferte Migrationen werden nie verändert.
Der Produktionsaufbau besteht aus mariadb, api (ASP.NET Core auf :8080, nur im internen
Netz) und web (nginx mit der gebauten SPA und der Weiterleitung von /api/), optional
backup (docs/13-devops-tests.md §1). Die Compose-Datei ist für Dokploy ausgelegt: kein
Dienst veröffentlicht einen Host-Port, Traefik von Dokploy beendet TLS und erreicht web über das
externe Netz dokploy-network.
- In Dokploy einen Dienst vom Typ Compose anlegen, Quelle: dieses Git-Repository, Zweig
main, Compose Pathdeploy/docker-compose.yml. - Reiter Environment: den Inhalt von
deploy/.env.exampleeinfügen und alle Platzhalter ersetzen. Pflicht:DB_PASSWORD,DB_ROOT_PASSWORD(und dasselbe Passwort inCR_ConnectionStrings__Default),CR_App__BaseUrlmit der echten Domain,CR_App__SecretKey(64 zufällige Bytes, base64),CR_Security__IpHashSalt, SMTP-Zugang,CR_Seed__Admin*. Dokploy schreibt die Werte als.envneben die Compose-Datei;apilädt sie überenv_file. - Reiter Domains: Domain eintragen, Dienst
web, Container-Port80, HTTPS mit Let's Encrypt. Dokploy ergänzt beim Deployment die Traefik-Labels selbst; eigene Labels sind nicht nötig. Diewww.-Variante als zweiten Eintrag auf denselben Dienst legen (eigenes Zertifikat); nginx leitet sie dauerhaft (301) auf die Domain ohnewwwweiter, Pfad und Query bleiben erhalten.CR_App__BaseUrlzeigt auf die Domain ohnewww. - Deploy. Beim ersten Start legt die API die Migrationen an (
CR_App__RunMigrations=true) und erzeugt ausCR_Seed__Admin*das erste Administratorkonto. Für spätere Versionen genügt ein erneutes Deploy (oder Auto-Deploy per Webhook); Migrationen laufen beim Start der API. - Reiter Backups: Datenbank-Backup auf Dienst
mariadb(Typ MariaDB, Zugangsdaten aus der Umgebung) und Volume Backups füruploads(und bei Bedarfdb-data) auf ein S3-Ziel in der EU einrichten; Details indocs/ops/backup-restore.md.
Das Administratorkonto kommt wegen security.require2faForStaff erst nach der Einrichtung der
Zwei-Faktor-Anmeldung (/settings/security) in den Adminbereich.
Hinweise: Keine container_name-Einträge ergänzen (stört Logs und Metriken in Dokploy). Daten
liegen ausschließlich in benannten Volumes (db-data, uploads, backups); Bind-Mounts in den
Repo-Klon würden bei jedem Deployment geleert.
Die Dateiablage kann statt im Volume uploads in einem S3-kompatiblen Objektspeicher liegen
(CR_Storage__Provider=S3 plus CR_Storage__S3__*, siehe deploy/.env.example). Der Bucket
bleibt privat, ausgeliefert wird weiterhin über die API; Sicherung dann über Versionierung oder
Replikation beim Anbieter (docs/13-devops-tests.md §1).
Mit deploy/docker-compose.standalone.yml veröffentlicht web einen Host-Port; davor gehört ein
TLS-Proxy des Hosts, der X-Forwarded-For und X-Forwarded-Proto setzt (auch für die
www.-Variante, die nginx auf die Domain ohne www umleitet). Den Port nur für den
Proxy öffnen (WEB_HTTP_PORT=127.0.0.1:8080): nginx vertraut dem letzten Eintrag in
X-Forwarded-For, sobald die Anfrage aus einem privaten Docker-Netz kommt.
cp deploy/.env.example deploy/.env # alle Platzhalter ersetzen
docker network create dokploy-network # einmalig; der Name kommt aus docker-compose.yml
docker compose -p connected-rails -f deploy/docker-compose.yml \
-f deploy/docker-compose.standalone.yml up -d --buildDie dateibasierte Sicherung (backup) ist ein Compose-Profil: --profile local-backup an die
Aufrufe anhängen.
docker compose -f deploy/docker-compose.yml ps # Healthchecks aller Dienste
docker compose -f deploy/docker-compose.yml exec web wget -qO- http://127.0.0.1/api/v1/health
docker compose -f deploy/docker-compose.yml logs -f api # Serilog als JSON auf stdoutUnter Dokploy stehen dieselben Angaben in den Reitern Logs und Monitoring; von außen ist
https://<domain>/api/v1/health erreichbar. Der Endpunkt prüft Datenbank, Schreibrechte auf der
Dateiablage und den Herzschlag des Job-Workers. Die Zugriffsprotokolle von nginx enthalten nur
gekürzte IP-Adressen (IPv4 ohne letztes Oktett, IPv6 auf /64); die Absenderadresse übernimmt
nginx aus dem letzten, vom Proxy angehängten Eintrag in X-Forwarded-For.
Unter Dokploy: Datenbank-Backup (Dienst mariadb) und Volume-Backup (uploads) nach S3, siehe
oben. Alternativ oder zusätzlich legt der Dienst backup (Profil local-backup) täglich um
BACKUP_HOUR_UTC einen Stand im Volume backups ab (database.sql.gz, uploads.tar.gz,
checksums.sha256) und hält ihn BACKUP_KEEP_DAYS Tage vor. Die Verschlüsselung und die
Auslagerung auf einen EU-Speicher übernimmt das Werkzeug des Betreibers.
# Sicherung sofort erzeugen
docker compose --profile local-backup -f deploy/docker-compose.yml exec backup /usr/local/bin/backup.sh
# Datenbank aus einem Stand wiederherstellen
docker compose --profile local-backup -f deploy/docker-compose.yml exec backup \
/usr/local/bin/backup.sh --restore 2026-01-31_030000
# Dateien mitspielen (die Ablage hängt im Backup-Dienst schreibgeschützt);
# <projekt> ist der Dokploy-App-Name bzw. `connected-rails`
docker compose --profile local-backup -f deploy/docker-compose.yml run --rm \
-v <projekt>_uploads:/data/uploads backup \
/usr/local/bin/backup.sh --restore 2026-01-31_030000- Wartungsmodus: Einstellung
site.maintenance.activeim Adminbereich; die API antwortet dann für alle außer der Administration mit503und der hinterlegten Nachricht. - Aktualisieren: Deploy in Dokploy (bzw.
up -d --buildohne Dokploy); Migrationen laufen beim Start der API. - Aufräumen (Aufbewahrungsfristen, Sperren, Ränge, geplante Artikel) erledigt der stündliche Wartungslauf der API selbst.
Siehe LICENSE (folgt). Schriftlizenzen liegen unter frontend/public/licenses/.