Files
d4rk_media/docker-compose.yml
T
D4rkst3randClaude Opus 5 bbb74138c8 feat: Verlauf als CSV, Meldung bei Upload mit Drossel, Deckel auf dem Papierkorb
Abschnitt 3 aus docs/ideen.md, bis auf die Sicherungsziele.

VERLAUF ALS CSV. Der Export konnte nur den Bestand; wer nachrechnen wollte,
was ueber einen Zeitraum passiert ist, sass vor einer Tabelle, die nach 500
Zeilen umblaettert. Der Knopf sitzt in der Reiterleiste und holt den Verlauf,
DER GERADE OFFEN IST -- zwei Knoepfe nebeneinander waeren die Frage "welchen
von beiden?" an einer Stelle, wo die Antwort schon auf dem Bildschirm steht.

Semikolon und CRLF wie beim Bestands-Export; das war dort nachgemessen worden.
Gemessen an der ausgelieferten Datei: 5371 Zeilen, kein einziges nacktes LF.
Ohne Anmeldung 401 -- die Route liegt hinter dem Waechter, was nach dem
Sitzungs-Fehler von vorgestern ausdruecklich nachgeprueft wurde.

MELDUNG BEI UPLOAD -- die Drossel ist der eigentliche Inhalt. Jeder Upload
schiebt eine Frist von zwei Minuten nach hinten; erst nach der Ruhe geht EINE
Nachricht raus. Ohne das waere die Funktion ein Schaden: 900 Fahrzeugbilder
ergaeben 900 Nachrichten, Discord drosselt Webhooks, und wer danach eine echte
Meldung bekommt, sieht sie nicht mehr.

Gemessen: drei Uploads mit zehn Sekunden Abstand -> eine Meldung ueber drei
Dateien. Ein einzelner Upload -> eine Meldung ueber eine Datei.

Nur Token-Uploads, absichtlich. Was ueber das Dashboard hereinkommt, hat gerade
jemand selbst hochgeladen und bestaetigt bekommen. Zurueckholen aus dem
Papierkorb meldet gar nichts: das ist kein Neues, das ist ein Wiedergefundenes.

Und derselbe Fehler wie bei 'platte' lauerte schon wieder: die Liste der
Anlaesse steht im Server UND in der Oberflaeche, und der Server verwirft beim
Speichern alles, was in seiner Liste fehlt -- ein Kreuzchen, das sich setzen
laesst und beim naechsten Laden weg ist. Diesmal beide angefasst, in beiden
steht jetzt ein Verweis auf die andere. Nachgemessen: vier geschickt, vier
gespeichert.

DECKEL AUF DEM PAPIERKORB. 30 Tage UND 20 GB, was zuerst greift. Wer 200 GB
loescht, haelt sie sonst 30 Tage doppelt und merkt es erst, wenn die Platte
voll ist. Geraeumt wird das AELTESTE zuerst -- dessen Versehen waere am
ehesten schon aufgefallen.

Ueber PAPIERKORB_MAX_MB verstellbar, und das nicht aus Bequemlichkeit: ein
Deckel von 20 GB laesst sich nicht pruefen, ohne 20 GB zu loeschen. Mit
0.0002 MB nachgemessen -- vier Eintraege zu 422 Bytes, drei entfernt, uebrig
blieb der NEUESTE. Danach zurueck auf 20 GB, gemessen 21474836480.

NEBENBEI, DREIMAL DIESELBE SORTE FEHLER: "0.0 MB" fuer 422 Bytes, "0 KB" fuer
106 Bytes, "0.0 MB von 0.0 MB" beim Deckel. Es gab drei Byte-Formatierer, jeder
mit anderer Untergrenze. Jetzt einer in meldung.ts, von Bytes bis GB, exportiert
und von dash.ts mitbenutzt. Nachgemessen ueber alle Stufen.

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

101 lines
4.6 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
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: