Installation

Reverse Proxy

FediSuite lauscht auf Port 3000 und ist ohne Reverse Proxy nur direkt über diesen Port erreichbar, ohne HTTPS und ohne Domainzuordnung. Ein Reverse Proxy nimmt Anfragen auf Port 80 und 443 entgegen, übernimmt TLS und leitet den Verkehr an FediSuite weiter. Diese Seite zeigt Traefik mit Let's Encrypt und zusätzlich Caddy und Nginx.

Was ist ein Reverse Proxy?

Ein Reverse Proxy sitzt zwischen dem Internet und deiner Anwendung. Ruft jemand https://deine-domain.de auf, nimmt er die Anfrage entgegen, übernimmt die HTTPS-Verschlüsselung und leitet sie unverschlüsselt an FediSuite auf Port 3000 weiter, innerhalb des Docker-Netzwerks oder des Hosts.

Traefik ist ein Reverse Proxy, der für Docker-Umgebungen gebaut ist. Er erkennt laufende Container, liest deren Konfiguration aus Labels und richtet Routing und TLS-Zertifikate selbst ein.

Genau ein Proxy davor: FediSuite vertraut genau einem vorgeschalteten Proxy (trust proxy = 1) und liest die Client-IP aus dessen X-Forwarded-For-Header. Das braucht die IP-basierte Begrenzung von Anmeldeversuchen. Sitzt ein zweiter Proxy oder ein CDN davor, sieht FediSuite die Adresse des ersten Proxys statt der der Besucher*innen.

Wie der Datenfluss aussieht

Browser

https://deine-domain.de

Port 443 (HTTPS)

Traefik

TLS-Terminierung

Port 3000 (intern)

FediSuite app

Docker-Netzwerk

Wichtig: ports: 3000 entfernen

Mit Reverse Proxy sollte Port 3000 nicht mehr auf allen Schnittstellen des Hosts veröffentlicht werden. Das Mapping 3000:3000 im app-Service macht die App direkt am Server erreichbar, ohne HTTPS und am Proxy vorbei. Docker umgeht dabei außerdem Firewall-Regeln wie ufw. Traefik erreicht die App über das Docker-Netzwerk und braucht das Mapping nicht.

Ohne Reverse Proxy (mit Port-Mapping)

  app:
    ...
    ports:
      - "3000:3000"  # mit Proxy entfernen
    ...

Mit Traefik (kein Port-Mapping)

  app:
    ...
    # ports: komplett entfernt
    labels:
      - "traefik.enable=true"
    ...
Merke: Port 3000 bleibt im Container aktiv, Traefik kennt ihn über das Label loadbalancer.server.port=3000. Läuft dein Reverse Proxy direkt auf dem Host (Caddy, Nginx), setze statt des Entfernens "127.0.0.1:3000:3000". Dann erreicht nur der Proxy den Port.

Szenario 1: Externer Traefik

Das ist der typische Fall, wenn auf dem Server schon andere Dienste hinter Traefik laufen. Traefik hat seinen eigenen Stack, und FediSuite tritt dem vorhandenen externen Docker-Netzwerk bei, in der Regel proxy.

1

Voraussetzungen prüfen

Dein externer Traefik muss Folgendes erfüllen:

Der Docker-Provider ist aktiviert (--providers.docker=true).
Es gibt einen Cert-Resolver für Let's Encrypt. Merke dir seinen Namen, du brauchst ihn im Label tls.certresolver. Im Beispiel heißt er letsEncrypt.
Es gibt ein externes Docker-Netzwerk, über das Traefik die Container erreicht. Im Beispiel heißt es proxy.
2

Externes Netzwerk anlegen (falls noch nicht vorhanden)

Das Netzwerk proxy muss einmalig angelegt werden, falls es noch nicht existiert:

bash
docker network create proxy
3

docker-compose.yml anpassen

Die docker-compose.yml enthält die Labels und die Netzwerk-Einträge bereits als Kommentar. Nimm im app-Service diese Änderungen vor (der Rest des Service bleibt unverändert):

① ports: im app-Service entfernen, Labels und Networks einkommentieren und Domain und Resolver anpassen:

docker-compose.yml: app Service
  app:
    ...
    # ports: entfernt, Traefik übernimmt
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.fedisuite.rule=Host(`deine-domain.de`)"
      - "traefik.http.services.fedisuite.loadbalancer.server.port=3000"
      - "traefik.http.routers.fedisuite.service=fedisuite"
      - "traefik.http.routers.fedisuite.tls.certresolver=letsEncrypt"
      - "traefik.docker.network=proxy"
    networks:
      - default
      - proxy

② Am Ende der Datei den networks:-Block einkommentieren:

docker-compose.yml: Ende der Datei
networks:
  proxy:
    external: true

external: true teilt Docker Compose mit, dass das Netzwerk bereits existiert und nicht neu angelegt wird.

Alternative ohne Änderung der mitgelieferten Datei: Lege dieselben Einträge in eine docker-compose.override.yml (steht in der .gitignore). Compose hängt Listen wie labels und networks an, das ports-Mapping entfernst du dort ab Docker Compose 2.24 mit ports: !reset []. Die Datei docker-compose.traefik.example.yml im Repository zeigt die Labels und Netzwerke als Vorlage.
4

Stack neu starten

bash
docker compose up -d

Traefik erkennt den neuen Container, liest die Labels und stellt ein Let's-Encrypt-Zertifikat für deine Domain aus. Traefik leitet erst an Container weiter, deren Healthcheck besteht. Bis die App bereit ist (bei langen Datenbankmigrationen bis zu zehn Minuten), kann deshalb ein 404 erscheinen.

Szenario 2: Traefik in der docker-compose.yml

Ist FediSuite der einzige Dienst auf dem Server, lässt sich Traefik direkt in die docker-compose.yml einbauen. Traefik läuft dann als fünfter Container im selben Stack, ohne externes Netzwerk.

1

Traefik-Service hinzufügen

Füge den traefik-Service am Anfang der docker-compose.yml unter services: ein. Ersetze die E-Mail-Adresse durch deine echte, Let's Encrypt nutzt sie für Hinweise zu Zertifikaten.

docker-compose.yml: traefik Service
services:

  traefik:
    image: traefik:v3
    restart: unless-stopped
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--certificatesresolvers.letsEncrypt.acme.tlschallenge=true"
      - "--certificatesresolvers.letsEncrypt.acme.email=deine@email.de"
      - "--certificatesresolvers.letsEncrypt.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./letsencrypt:/letsencrypt"
    networks:
      - proxy

  db:
    # ... unverändert ...

  app:
    # ... siehe Schritt 2 ...
Hinweis: Der Zugriff auf den Docker-Socket gibt Traefik weitreichende Rechte auf dem Host, auch mit :ro. Wer das vermeiden will, schaltet einen Socket-Proxy davor. Die TLS-Challenge von Let's Encrypt läuft über Port 443, Port 80 dient der Weiterleitung auf HTTPS.
2

app-Service anpassen

Entferne ports:, setze die Labels und das proxy-Netzwerk. Der Rest des app-Service bleibt wie in der mitgelieferten Datei:

docker-compose.yml: app Service
  app:
    ...
    # ports: entfernt, Traefik übernimmt
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.fedisuite.rule=Host(`deine-domain.de`)"
      - "traefik.http.services.fedisuite.loadbalancer.server.port=3000"
      - "traefik.http.routers.fedisuite.service=fedisuite"
      - "traefik.http.routers.fedisuite.tls.certresolver=letsEncrypt"
      - "traefik.docker.network=proxy"
    networks:
      - default
      - proxy
3

Netzwerk am Ende der Datei definieren

Da Traefik und FediSuite im selben Stack laufen, ist das Netzwerk nicht extern. Docker Compose legt es selbst an:

docker-compose.yml: Ende der Datei
networks:
  proxy:

Kein external: true, das Netzwerk gehört zu diesem Stack.

4

Stack starten

bash
docker compose up -d

Traefik startet, erkennt den app-Container über den Docker-Provider und stellt ein TLS-Zertifikat für deine Domain aus. Das Zertifikat liegt dauerhaft in ./letsencrypt/acme.json und wird vor Ablauf erneuert. Sichere diesen Ordner mit, wenn du den Stack wiederherstellen willst.

Szenario 3: Caddy oder Nginx auf dem Host

Jeder Reverse Proxy, der HTTP an Port 3000 weiterleiten kann, funktioniert. Beschränke das Port-Mapping dafür auf die lokale Schnittstelle (127.0.0.1:3000:3000) und sorge dafür, dass der Proxy HTTPS beendet. Beachte, dass die Dateien bis zu 50 MB groß sein können, die FediSuite beim Upload annimmt, ein Proxy mit kleinem Body-Limit (bei Nginx standardmäßig 1 MB) lehnt größere Anhänge ab.

Caddyfile
deine-domain.de {
    reverse_proxy 127.0.0.1:3000
}
Nginx (Ausschnitt)
server {
    listen 443 ssl;
    server_name deine-domain.de;
    # ssl_certificate ... (Zertifikat nach eigener Einrichtung)
    client_max_body_size 64m;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Trage in der .env als APP_URL die öffentliche HTTPS-Adresse ein, nicht die lokale.

Traefik-Labels erklärt

Über Labels in der docker-compose.yml teilt FediSuite Traefik mit, wie geroutet werden soll. Jedes Label hat eine klare Bedeutung:

traefik.enable=true

Aktiviert Traefik für diesen Container. Mit exposedbydefault=false (Szenario 2, in externen Setups üblich) muss jeder Container, den Traefik verwalten soll, dieses Label tragen.

traefik.http.routers.fedisuite.rule=Host(`deine-domain.de`)

Legt fest, für welche Domain Traefik Anfragen an diesen Container weiterleitet. Ersetze deine-domain.de durch deine Domain. Der Name fedisuite im Label ist ein frei wählbarer interner Bezeichner des Routers und muss nur eindeutig sein.

traefik.http.services.fedisuite.loadbalancer.server.port=3000

Port, auf dem der Container intern lauscht. FediSuite nutzt 3000. Traefik leitet intern an diesen Port weiter, er muss nicht nach außen geöffnet sein.

traefik.http.routers.fedisuite.service=fedisuite

Verknüpft den Router mit dem Service darüber. Bei nur einem Container ist das meist implizit, explizit angegeben vermeidet es Mehrdeutigkeiten.

traefik.http.routers.fedisuite.tls.certresolver=letsEncrypt

Aktiviert TLS für diesen Router und nennt den Cert-Resolver, der das Zertifikat ausstellt. Der Name letsEncrypt muss exakt mit dem Namen des ACME-Resolvers in der Traefik-Konfiguration übereinstimmen.

traefik.docker.network=proxy

Sagt Traefik, über welches Docker-Netzwerk es den Container erreicht. Da app in zwei Netzwerken hängt (default und proxy), muss Traefik wissen, welches es nutzen soll.

Troubleshooting

Kein Zertifikat / Browser zeigt Zertifikatsfehler

  • Der DNS-Eintrag der Domain zeigt noch nicht auf die Server-IP. Warte, bis er gilt.
  • Port 443 ist in der Firewall geschlossen. Die TLS-Challenge von Let's Encrypt (tlschallenge) läuft über Port 443. Bei einer HTTP-Challenge wäre es Port 80.
  • Der Name des Cert-Resolvers im Label stimmt nicht mit dem in Traefik konfigurierten überein.
  • Das Rate-Limit von Let's Encrypt ist erreicht. Warte einige Stunden und versuche es erneut.

Traefik findet den Container nicht / 404

  • traefik.enable=true fehlt im app-Service.
  • Das Label traefik.docker.network=proxy fehlt oder nennt das falsche Netzwerk.
  • Der app-Container hängt nicht im proxy-Netzwerk (networks: im Service fehlt).
  • Der Healthcheck der app besteht noch nicht. Prüfe docker compose ps und warte, bis sie healthy ist.
  • docker compose up -d wurde nach der Änderung nicht ausgeführt.

FediSuite antwortet, aber über HTTP statt HTTPS

  • Die Weiterleitung von HTTP auf HTTPS ist in Traefik nicht konfiguriert. In Szenario 2 sind die redirections-Zeilen im Traefik-Command nötig.
  • Das Label tls.certresolver fehlt, ohne es richtet Traefik kein TLS ein.

Anmeldung oder Konto-Verbindung schlägt fehl

  • APP_URL in der .env stimmt nicht mit der öffentlichen HTTPS-Adresse überein. Die OAuth-Rückkehradresse wird daraus gebaut. Nach einer Änderung docker compose up -d ausführen.
  • Vor der App sitzt mehr als ein Proxy, dadurch stimmen die Client-IPs für die Begrenzung von Anmeldeversuchen nicht.

Port 3000 ist von außen erreichbar, obwohl Traefik läuft

  • Die Zeile ports: - "3000:3000" wurde nicht aus der docker-compose.yml entfernt. Entfernen und docker compose up -d ausführen.
Traefik-Logs prüfen
# Szenario 1: Traefik in eigenem Stack
docker logs traefik -f

# Szenario 2: Traefik im FediSuite-Stack
docker compose logs traefik -f