The running Traefik instance has no global entrypoint http->https redirection even though /srv/stack/docker-compose.yml declares one, so plain http://desfoto.de/ answered with Traefik's default 404 once the old desfoto-redirect-http router was removed. Route desfoto.de through its own http router (desfoto-http + desfoto-http-to-https, permanent redirect) via the proven live Docker provider instead of restarting the shared proxy. Document the live-config drift in docs/deployment.md.
6.7 KiB
Deployment — desfoto.de
Zielumgebung
| Baustein | Wert |
|---|---|
| Produktionshost | prod-main = opencode-prod@87.106.24.138 (NOPASSWD sudo) |
| Live-Verzeichnis | /home/denny/stacks/desfoto/ (Owner denny:denny) |
| Release-Snapshots | /home/denny/stacks/desfoto-releases/<stamp>-<sha>/ |
| Compose-Dateien | compose.yml + compose.vps.yml, Projektname desfoto |
| Container | desfoto-web-1 (nginx:1.28-alpine), gebunden an 127.0.0.1:18430 |
| Netzwerk | externes Docker-Netzwerk web (Traefik-Docker-Provider) |
| Reverse Proxy | Traefik v3 im Projekt stack (/srv/stack/docker-compose.yml) |
| Entrypoints | http und https, ACME-Resolver le, HTTP-01-Challenge |
| Zertifikate | /srv/traefik/acme.json |
| Domains | desfoto.de (kanonisch) und www.desfoto.de → 301 auf Apex |
Der Proxy wird niemals neu gestartet oder neu erzeugt. Die Anbindung erfolgt
ausschließlich über Labels in compose.vps.yml.
Ablauf einer Veröffentlichung
/home/king/bin/oc-release /home/king/projects/desfoto \
"feat: ..." <geänderte Dateien...>
oc-release committet und pusht die genannten Dateien und ruft danach die
getrackten Hooks auf:
-
.ocauto/deploy <sha>- prüft, dass
HEADdem Release entspricht undsite/,nginx.conf,compose.yml,compose.vps.ymlkeine uncommitteten Änderungen haben; - packt diese Pfade in ein Archiv und lädt es nach
prod-main:/tmp; - legt auf dem Server zuerst einen Snapshot der aktuell laufenden Version an
(
/home/denny/stacks/desfoto-releases/<stamp>-<sha>/, zusätzlich alspreviousverlinkt); - entpackt die neue Version nach
/home/denny/stacks/desfoto/, setzt den Owner aufdenny:dennyund schreibt die Release-Kennung nachRELEASE; docker compose -f compose.yml -f compose.vps.yml up -d --remove-orphansund wartet aufhealthy;- entfernt einmalig die veralteten
desfoto.de-Weiterleitungs-Labels aus/srv/stack/docker-compose.yml: Es werden ausschließlich Traefik-Label-Zeilen mitdesfoto-Bezug sowie der zugehörige Kommentar entfernt, das Ergebnis wird zuerst als Compose-Projekt validiert (config --quiet) und danach per atomaremmvan die Stelle der Live-Datei gesetzt. Eine Vorher-Fassung liegt im Snapshot (docker-compose.yml.stack-backup) und daneben alsdocker-compose.yml.bak.<stamp>. Danach wird ausschließlich derlanding-Container mit--no-depsneu erzeugt, damitdennyapp.deunddennyschulz.deunverändert weiterlaufen. Bleibt einedesfoto-Referenz übrig (z. B. ein eigener Service-Block), wird sie als WARNUNG ausgegeben.
- prüft, dass
-
.ocauto/verify <sha>- vergleicht den Dateibaum unter
/home/denny/stacks/desfoto/sitemit dem committetensite/(SHA-256 über alle Dateien außer den datiertensitemap.xml/security.txt); - prüft alle 13 Routen, die 404-Seite,
robots.txt,sitemap.xml,.well-known/security.txt, Bilder und Schriften; - prüft die Weiterleitungen
http → httpsundwww → Apex; - prüft die Sicherheits-Header, dass kein
Set-Cookiegesetzt wird und dass das Zertifikat noch mindestens sieben Tage gültig ist; - prüft, dass
www.dennyschulz.deunddennyapp.deweiterhin erreichbar sind.
- vergleicht den Dateibaum unter
Routing
desfoto.de wird vor dem Aufräumen bereits vom neuen Container bedient, weil die
Routers in compose.vps.yml eine explizite Traefik-Priorität 200 tragen und die
alten Weiterleitungsrouters keine Priorität setzen (damit gilt dort die
Regel-Länge). Der Container wird also zuerst gesund geprüft, und erst danach werden
die alten Labels entfernt — der Übergang hat damit kein Fenster ohne Antwort.
www.desfoto.de wird über die Middleware desfoto-canonical dauerhaft auf
https://desfoto.de/... umgeschrieben. Für http bringt die Anwendung einen
eigenen Router (desfoto-http + desfoto-http-to-https) mit, der dauerhaft
(301) auf https umleitet. Die ACME-HTTP-01-Challenge beantwortet Traefik über
den internen acme-http-Router mit maximaler Priorität, bevor dieser Redirect
greift.
Abweichung der laufenden Traefik-Konfiguration (Live-Drift)
/srv/stack/docker-compose.yml deklariert eine globale
Entrypoint-Weiterleitung http → https
(--entrypoints.http.http.redirections.entryPoint.to=https /
…scheme=https, Zeilen 10–11). Der laufende Container traefik führt diese
Flags nachweislich nicht (docker inspect traefik --format '{{json .Args}}'
enthält keine redirections-Flags; http://dennyapp.de/ leitet nur deshalb um,
weil landing einen eigenen landing-http-Router besitzt). Die Datei auf der
Platte und die laufende Konfiguration stimmen also nicht überein.
Der Proxy wird deswegen nicht aus der Datei neu erzeugt oder neu gestartet:
Das würde alle fremden Routen risikobehaftet anfassen. Stattdessen bringt jede
Anwendung ihr eigenes HTTP-Routing mit — desfoto.de über die Labels in
compose.vps.yml. Wird die globale Weiterleitung später bewusst aktiviert,
bleibt der eigene Router schlicht wirkungslos.
Nachzuprüfen mit:
curl -sS -o /dev/null -w '%{http_code} %{redirect_url}\n' http://desfoto.de/
# erwartet: 301 https://desfoto.de/
Rollback
ROLLBACK_TO=/home/denny/stacks/desfoto-releases/<stamp>-<sha> \
/home/king/projects/desfoto/.ocauto/deploy rollback
Der Befehl synchronisiert site/, nginx.conf und beide Compose-Dateien aus dem
Snapshot zurück nach /home/denny/stacks/desfoto/ und startet den Stack neu. Die
frühere Version bleibt so lange verfügbar, bis sie bewusst gelöscht wird.
Jeder Release legt den Snapshot an, auch der allererste. Enthält der Snapshot noch
kein site/ (weil vorher nichts ausgeliefert wurde), entfernt der Rollback den
desfoto-Stack wieder und stellt den Zustand vor der Veröffentlichung her.
Wurde /srv/stack/docker-compose.yml verändert, liegt die Vorher-Fassung sowohl im
Snapshot als docker-compose.yml.stack-backup als auch daneben unter
docker-compose.yml.bak.<stamp>. Beide werden vom Rollback automatisch
zurückgespielt, gefolgt von docker compose up -d --no-deps landing; das Backup
.bak.<stamp> bleibt zusätzlich für einen manuellen Eingriff liegen.
Betrieb
ssh prod-main
sudo docker compose -f /home/denny/stacks/desfoto/compose.yml \
-f /home/denny/stacks/desfoto/compose.vps.yml ps
sudo docker logs --tail 50 desfoto-web-1
sudo docker inspect --format '{{.State.Health.Status}}' desfoto-web-1
Access-Logs gibt es bewusst nicht (access_log off in nginx.conf). Auch Fehler
schreibt nginx nicht weg: error_log /dev/null crit; verwirft sie vollständig,
statt sie in eine Datei zu schreiben. Der JSON-Log-Treiber des Containers ist
zusätzlich auf 5 MB × 2 Dateien begrenzt. Das entspricht der Zusage in der
Datenschutzerklärung.