Files
d4rk_media/docker-compose.yml
D4rkst3randClaude Opus 5 ab93e0ae4e feat: die Archive lassen sich aus dem Panel holen
Einstellungen -> "Sicherungen holen": die fertigen Archive mit Datum, Groesse
und einem Knopf. Der erste Schritt, der eine Kopie VON DIESEM RECHNER HERUNTER
bringt -- bisher haette man sich dafuer per Fernwartung auf den Server klicken
muessen, und genau daran hat es gelegen. Nicht Unwille, sondern
Umstaendlichkeit.

Der Ordner haengt NUR LESEND in den Container. Ein Dienst, der seine eigenen
Sicherungen loeschen kann, ist genau das Werkzeug, das man einem uebernommenen
Dienst nicht in die Hand geben will. Nachgemessen im Container:

    touch /sicherungen/probe  ->  Read-only file system

Und es gibt NUR EINE FORM VON NAMEN -- nicht "alles ausser .. und /", sondern
ein Muster, das genau auf die eigenen Archive passt. Wer einen Pfad
hineinschmuggeln will, muesste ihn erst so benennen. Das ist der Unterschied
zwischen dicht gemacht und dicht gebaut:

    ../../etc/passwd                -> 404
    ..%2f..%2fdata%2fmedia.db       -> 400
    media.db                        -> 400
    <archiv>.tar.gz.evil            -> 400
    ohne Anmeldung                  -> 401

Der ganze Weg einmal wirklich gegangen, nicht nur die Kopfzeilen: 336 MB in
15,9 s durch den Proxy, sha256 auf der Platte gleich sha256 heruntergeladen,
tar tzf zeigt 4639 Eintraege. Gestroemt und nicht in den Speicher gelesen --
sonst haetten Dienst UND Proxy die 336 MB gleichzeitig im Arbeitsspeicher.

Jeder Griff steht im Verwaltungs-Verlauf. Geloggt wird der GRIFF und nicht der
Erfolg: ein abgebrochener Download taucht ebenfalls auf, und das ist gewollt --
wer spaeter fragt, wer sich den Bestand geholt hat, will die Anfrage sehen.

Die fuenf neuen Pruefungen sind in tools/rundgang.py mit drin; der steht jetzt
bei 29 in Ordnung, 0 nicht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 15:46:03 +02:00

112 lines
5.2 KiB
YAML

# d4rk_media — unser eigener Medien-Dienst. EIN Container.
#
# In Portainer: Stacks -> Add stack -> Repository
#
# Repository URL https://git.d4rkst3r.de/D4rkst3r/d4rk_media
# Compose path docker-compose.yml
#
# EINE Datei, und das ist wichtig: Portainer nimmt unter "Compose path" genau
# eine. Ergaenzungen werden stillschweigend uebergangen -- alle Container
# gesund, alles 502. Das hat beim Lite-Anlauf einen Nachmittag gekostet.
#
# Die Werte gehoeren in die STACK-VARIABLEN, nicht in eine Datei im Repo.
services:
media:
build:
context: ./server
image: d4rk-media:latest
container_name: d4rk-media
restart: unless-stopped
environment:
# Der Ursprung, unter dem der Dienst oeffentlich steht -- OHNE Pfad
# und ohne abschliessenden Schraegstrich:
# https://media.d4rkst3r.de
#
# Das /f/ haengt der Dienst selbst an. Wer es hier mitschreibt,
# bekommt Adressen mit /f/f/, und das faellt erst auf, wenn das
# erste Bild fehlt.
#
# Das :? ist Absicht: fehlt die Variable, bricht der Stack ab,
# statt mit einer Adresse hochzufahren, die niemand erreicht.
PUBLIC_URL: ${PUBLIC_URL:?PUBLIC_URL fehlt, z.B. https://media.d4rkst3r.de}
# Wird beim ERSTEN Start als Benutzer "admin" angelegt. Ein spaeter
# geaenderter Wert setzt das bestehende Passwort nicht zurueck.
ADMIN_PASSWORD: ${ADMIN_PASSWORD:?ADMIN_PASSWORD fehlt}
ADMIN_USERNAME: ${ADMIN_USERNAME:-admin}
# EIN NAME (leer, Standard): Dashboard und API an der Wurzel,
# Dateien unter /f/.
#
# ZWEI NAMEN: hier den Hostnamen eintragen, unter dem es dann
# ausschliesslich Dateien gibt -- kein Dashboard, keine API, nichts
# anzumelden. Die URLs kommen dann ohne /f/ aus, und PUBLIC_URL ist
# der Datei-Name. Beide Namen muessen im Proxy auf diesen Port
# zeigen. Welche Betriebsart laeuft, sagt der Dienst beim Start.
FILES_HOST: ${FILES_HOST:-}
MAX_UPLOAD_MB: ${MAX_UPLOAD_MB:-64}
SESSION_DAYS: ${SESSION_DAYS:-30}
# Wieviel der Papierkorb hoechstens halten darf, zusaetzlich zu den
# 30 Tagen. Wer 200 GB loescht, haelt sie sonst 30 Tage doppelt.
# Verstellbar vor allem, damit sich der Deckel PRUEFEN laesst, ohne
# 20 GB zu loeschen -- Nachkommastellen sind erlaubt.
PAPIERKORB_MAX_MB: ${PAPIERKORB_MAX_MB:-20480}
# NODE_ENV=production setzt das Sitzungs-Cookie auf "Secure". Hinter
# NPM mit TLS ist das richtig.
#
# WER OHNE HTTPS AUSPROBIERT, SPERRT SICH AUS -- und zwar auf die
# unangenehme Art. Nachgemessen im Browser gegen
# http://192.168.2.33:8096:
#
# POST /api/dash/auth/login -> 200, sieht nach Erfolg aus
# document.cookie -> leer, still verworfen
# GET /api/dash/auth/me -> 401 "nicht angemeldet"
#
# Die Anmeldung MELDET Erfolg und ist trotzdem keine. Genau die
# Sorte Rueckmeldung, wegen der wir hier neu bauen.
#
# Und die naheliegende Gegenprobe fuehrt in die Irre: ueber
# http://localhost geht es, weil Browser localhost als sicheren
# Kontext behandeln. Also entweder ueber den Proxy mit HTTPS
# testen -- oder zum Ausprobieren NODE_ENV weglassen.
NODE_ENV: production
volumes:
# Bilder UND media.db in einem Volume. Eine Sicherung ist damit
# genau ein Kopiervorgang.
- media-data:/data
# Die fertigen Archive, damit man sie sich aus dem Panel holen kann,
# ohne sich per Fernwartung auf den Server zu klicken. Genau das war
# der Grund, aus dem es lange keine Kopie ausserhalb dieser Maschine
# gab: nicht Unwillen, sondern Umstaendlichkeit.
#
# DAS :ro AM ENDE IST DER WICHTIGE TEIL. Ein Dienst, der seine
# eigenen Sicherungen loeschen kann, ist genau das Werkzeug, das man
# einem uebernommenen Dienst nicht in die Hand geben will.
# Herausgeben reicht.
- ${BACKUP_DIR:-C:/backup/d4rk_media}:/sicherungen:ro
ports:
# Links der Host-Port, rechts der im Container. Nur die LINKE Zahl
# muss auf diesem Server einmalig sein.
#
# Belegt sind 80, 81, 443, 2224, 3000, 3080, 3478, 8000, 8080,
# 8090, 9000, 9443, 11000 -- und 9100/9101, solange der Lite-Stack
# als Vergleichsmassstab weiterlaeuft. Deshalb 9102.
#
# Gebunden an ALLE Adressen, nicht an 127.0.0.1: NPM liegt im
# Standard-Bridge-Netz und kommt ueber die Docker-Bruecke herein,
# nicht ueber Loopback. Ein an 127.0.0.1 gebundener Port naehme die
# Anfrage nicht an. ZU MACHT IHN DIE FIREWALL, nicht die Bindung --
# 9102 gehoert von aussen dicht, oeffentlich ist nur NPM auf 80/443.
- '${BIND_ADDR:-0.0.0.0}:${HOST_PORT:-9102}:8080'
volumes:
media-data: