Skip to content

Repository files navigation

Connected Rails – Website & Forum

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.

Repository-Struktur

backend/    .NET-Solution (Api, Core, Infrastructure, Tests)
frontend/   React-SPA (Vite)
deploy/     Docker-Compose, Dockerfiles, nginx
docs/       Planungsdokumentation

Voraussetzungen

  • .NET SDK 10.0
  • Node.js 22+ und pnpm 10+ (npm i -g pnpm oder corepack enable pnpm)
  • Docker mit Compose-Plugin

Erste Schritte

# 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 dev

Tests und Prüfungen

cd backend  && dotnet build && dotnet test
cd frontend && pnpm lint && pnpm typecheck && pnpm test && pnpm build

Datenbank-Migrationen

cd 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.Api

Bereits ausgelieferte Migrationen werden nie verändert.

Betrieb

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.

Deployment mit Dokploy

  1. In Dokploy einen Dienst vom Typ Compose anlegen, Quelle: dieses Git-Repository, Zweig main, Compose Path deploy/docker-compose.yml.
  2. Reiter Environment: den Inhalt von deploy/.env.example einfügen und alle Platzhalter ersetzen. Pflicht: DB_PASSWORD, DB_ROOT_PASSWORD (und dasselbe Passwort in CR_ConnectionStrings__Default), CR_App__BaseUrl mit der echten Domain, CR_App__SecretKey (64 zufällige Bytes, base64), CR_Security__IpHashSalt, SMTP-Zugang, CR_Seed__Admin*. Dokploy schreibt die Werte als .env neben die Compose-Datei; api lädt sie über env_file.
  3. Reiter Domains: Domain eintragen, Dienst web, Container-Port 80, HTTPS mit Let's Encrypt. Dokploy ergänzt beim Deployment die Traefik-Labels selbst; eigene Labels sind nicht nötig. Die www.-Variante als zweiten Eintrag auf denselben Dienst legen (eigenes Zertifikat); nginx leitet sie dauerhaft (301) auf die Domain ohne www weiter, Pfad und Query bleiben erhalten. CR_App__BaseUrl zeigt auf die Domain ohne www.
  4. Deploy. Beim ersten Start legt die API die Migrationen an (CR_App__RunMigrations=true) und erzeugt aus CR_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.
  5. Reiter Backups: Datenbank-Backup auf Dienst mariadb (Typ MariaDB, Zugangsdaten aus der Umgebung) und Volume Backups für uploads (und bei Bedarf db-data) auf ein S3-Ziel in der EU einrichten; Details in docs/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).

Betrieb ohne Dokploy

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 --build

Die dateibasierte Sicherung (backup) ist ein Compose-Profil: --profile local-backup an die Aufrufe anhängen.

Zustand prüfen

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 stdout

Unter 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.

Sicherungen

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

Wartung

  • Wartungsmodus: Einstellung site.maintenance.active im Adminbereich; die API antwortet dann für alle außer der Administration mit 503 und der hinterlegten Nachricht.
  • Aktualisieren: Deploy in Dokploy (bzw. up -d --build ohne Dokploy); Migrationen laufen beim Start der API.
  • Aufräumen (Aufbewahrungsfristen, Sperren, Ränge, geplante Artikel) erledigt der stündliche Wartungslauf der API selbst.

Lizenz

Siehe LICENSE (folgt). Schriftlizenzen liegen unter frontend/public/licenses/.

About

Connected Rails website code

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages