Demo-Video bereitstellen¶
Die öffentliche Seite /video spielt das LLARS-Demo-Video /videos/llars_demo.mp4
ab. Die Datei ist rund 88 MB groß und liegt bewusst weder im Repository noch im
Frontend-Image (git- und dockerignored). nginx liefert sie direkt aus einem
Verzeichnis auf dem Host aus. Auf einem neuen Host, und immer wenn
/videos/llars_demo.mp4 mit 404 antwortet, wird sie einmalig von Hand abgelegt.
Woran man das Problem erkennt
/video zeigt die Hinweiskarte „Das Video kann gerade nicht geladen werden"
mit dem YouTube-Backup, curl -I …/videos/llars_demo.mp4 liefert
404 Not Found (nginx-Fehlerseite, text/html, 146 Bytes), und der
Smoke-Test meldet WARNING: Demo-Video fehlt auf dem Host.
Wo die Datei liegt¶
| Was | Wert |
|---|---|
| Host-Pfad (Standard) | /var/llars-static/videos/llars_demo.mp4 |
| Variable | LLARS_STATIC_DIR in /var/llars/.env (Standard /var/llars-static) |
| Pfad im nginx-Container | /srv/llars-static/videos/ (read-only) |
| Mount | docker-compose.prod.yml (Production) und docker-compose.staging.yml (Staging :55080) |
| nginx | location /videos/ in nginx.prod.conf (Port 80 und 443) und nginx.prod-no-ssl.conf |
| Quelle | llars-frontend/public/videos/llars_demo.mp4 auf einem Entwicklerrechner |
Warum außerhalb des Checkouts¶
Bis zum 02.10.2026 mountete docker-compose.prod.yml das Video aus
./static/videos, also aus /var/llars/static/videos im Checkout. Jeder
Deploy räumt den Checkout mit git reset --hard und git clean -fd auf, und
git clean entfernt alles Unversionierte, das nicht ignoriert ist. Weil
deploy_bluegreen.sh bei jedem Deploy die versionierte
docker/nginx/active_upstream.conf umschreibt, lief das Aufräumen praktisch
immer. Auf Production war das Verzeichnis deshalb leer, mit dem Zeitstempel des
nächtlichen Deploys (02:22).
Seitdem liegt der Standard unter /var/llars-static, wo weder ein git clean
(auch nicht mit -x) noch ein frischer Checkout hinreicht. /static/ steht
zusätzlich in .gitignore, und die Skripte schließen static/ beim
git clean aus, damit auch der alte Pfad nicht mehr geleert wird.
Blue-Green¶
Blue und Green teilen sich einen Checkout unter /var/llars; die Farben
unterscheiden nur Container-Namen und Compose-Projekte. Der nginx-Container
(llars_nginx_service) gehört zu keiner Farbe. Es gibt daher genau ein
Video-Verzeichnis, und ein Farbwechsel ändert nichts daran.
Datei ablegen¶
/var/llars-static liegt unter /var und braucht beim ersten Anlegen
Root-Rechte. Ohne sudo geht das über einen kurzlebigen Container, wie ihn auch
deploy_bluegreen.sh für chown nutzt (Docker legt das fehlende
Host-Verzeichnis beim -v selbst an). Vom Entwicklerrechner aus (SSH-Alias
llars für Production, llars-dev für kia-dev; für beide ist VPN nötig):
scp llars-frontend/public/videos/llars_demo.mp4 llars:/tmp/llars_demo.mp4
ssh llars 'docker run --rm \
-v /tmp/llars_demo.mp4:/src/llars_demo.mp4:ro \
-v /var/llars-static:/dst \
alpine:3.19 sh -c "mkdir -p /dst/videos \
&& cp /src/llars_demo.mp4 /dst/videos/llars_demo.mp4 \
&& chmod 755 /dst /dst/videos && chmod 644 /dst/videos/llars_demo.mp4" \
&& rm -f /tmp/llars_demo.mp4'
Mit sudo auf dem Host geht es auch direkt:
sudo install -D -m 0644 /tmp/llars_demo.mp4 /var/llars-static/videos/llars_demo.mp4
sudo chmod 755 /var/llars-static /var/llars-static/videos
Die Rechte sind wichtig: Der nginx-Worker läuft im Container als Benutzer
nginx und braucht Leserechte auf Datei (644) und Verzeichnisse (755).
Einmalig nach der Umstellung vom 02.10.2026
Wer das Video vorher nach /var/llars/static/videos/ gelegt hat, muss es
einmal nach /var/llars-static/videos/ legen. Am besten geschieht das
schon vor dem Deploy, der die Umstellung bringt; dann gibt es keine
Lücke. Nach dem Deploy prüfen, ob nginx den neuen Pfad eingehängt hat:
docker inspect llars_nginx_service \
--format '{{range .Mounts}}{{.Source}} -> {{.Destination}}{{"\n"}}{{end}}' | grep videos
Zeigt das noch /var/llars/static/videos, den nginx-Container neu erstellen
(Befehl unten). Danach kann die alte Kopie unter /var/llars/static/ weg.
Optional: schneller Start im Browser
In der aktuellen Datei steht der moov-Block (Metadaten) am Ende. Browser
holen ihn per Range-Request nach, das funktioniert, kostet auf langsamen
Verbindungen aber Zeit. Mit ffmpeg -i llars_demo.mp4 -c copy -movflags +faststart llars_demo_fast.mp4
wandern die Metadaten nach vorn, ohne neu zu kodieren.
Prüfen¶
# Auf dem Host (emuliert das FH-Gateway, das per HTTP auf Port 80 weiterleitet)
curl -sI -H "X-Forwarded-Proto: https" http://localhost/videos/llars_demo.mp4
# Von außen
curl -sI https://llars.e-beratungsinstitut.de/videos/llars_demo.mp4
# Range-Streaming (Vorspulen, Safari/iOS): erwartet 206 Partial Content
curl -s -o /dev/null -r 0-0 -w '%{http_code} %{content_type}\n' \
https://llars.e-beratungsinstitut.de/videos/llars_demo.mp4
Erwartet werden 200 OK (bzw. 206 beim Range-Request),
Content-Type: video/mp4 und Accept-Ranges: bytes.
Derselbe Check läuft in jedem Smoke-Test (scripts/ci/smoke_test_demo_video.sh,
aufgerufen aus smoke_test.sh). Fehlt die Datei, meldet er eine Warnung mit
dem Ablagepfad und lässt den Job grün, denn ein Rollback brächte die Datei nicht
zurück. Mit SMOKE_STRICT_VIDEO=1 wird er zum harten Fehler:
Wenn die Datei auf dem Host liegt, nginx aber weiter 404 liefert¶
Zwei Ursachen sind möglich. Entweder hängt der laufende Container noch den alten Pfad ein (siehe Kasten oben), oder das Verzeichnis wurde gelöscht, während nginx lief; dann zeigt der Bind-Mount noch auf das gelöschte Verzeichnis. In beiden Fällen sieht der Container die Datei nicht:
Fehlt sie dort, wird der nginx-Container mit demselben Befehl neu erstellt, den
auch deploy_bluegreen.sh verwendet (er hängt dabei die aktuelle
active_upstream.conf ein, die aktive Farbe bleibt):
cd /var/llars
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --no-deps --force-recreate nginx-service
Staging (:55080) bekommt den Mount beim nächsten deploy_bluegreen.sh deploy.
Datei ersetzen¶
Eine neue Fassung wird unter demselben Namen abgelegt. nginx liefert das Video
mit expires 7d aus; Browser, die es schon geladen haben, können die alte
Fassung bis zu sieben Tage aus dem Cache zeigen.