commit 72f61dbd079b102140d838603f23bdf66018edc0 Author: D4rkst3r Date: Tue Aug 11 14:06:21 2026 +0200 Medien-Stack: Fivemanage Lite mit MySQL und MinIO Ein Ablageort fuer alle Resourcen statt Nextcloud plus rclone von Hand. Der Unterschied ist nicht der Speicher — den gibt es schon — sondern ein Schreibweg ueber HTTP: sobald ein Script hochladen soll, fehlt er, und Lite bringt ihn mit, samt Token je Resource und einer Oberflaeche zum Nachsehen. Zusammengestellt aus fivemanage/lite: dessen README, der deployments/docker-compose.yml (Entwicklung, startet die App gar nicht) und der deployments/docker-compose.test.yml (zeigt die App-Verdrahtung und dass MySQL genuegt und ClickHouse nicht Pflicht ist). Zwei Fassungen, und der Unterschied ist Absicht: docker-compose.yml fuer den Betrieb ueber Portainer aus diesem Repo. Keine offenen Ports, nur der Reverse Proxy spricht mit der App. docker-compose.local.yml zum Ausprobieren auf Docker Desktop. Ports offen, kein Proxy. Eine beta.23 gehoert erst auf einen Rechner, an dem nichts haengt. Ohne ClickHouse und Jaeger: beides ist Logging und Tracing, fuer das Ablegen von Bildern nicht noetig, und ClickHouse ist eine schwere Abhaengigkeit. Ein Init-Container legt den Bucket an und stellt ihn auf oeffentlich lesbar. Ohne diesen Schritt schlaegt der erste Upload fehl, und die Meldung nennt den Grund nicht. Healthchecks mit depends_on/condition, sonst startet die App gegen eine Datenbank, die noch nicht antwortet, und beendet sich — beim ersten Hochfahren jedes Mal. NICHT laufen gelassen: Docker war von hier nicht erreichbar. Das YAML ist geprueft, das Compose-Schema nicht. Co-Authored-By: Claude Opus 5 diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..cce478c --- /dev/null +++ b/.env.example @@ -0,0 +1,24 @@ +# Fivemanage Lite — Geheimnisse und Adressen +# +# Diese Datei ist die VORLAGE. Kopiere sie nach .env und trag echte Werte ein. +# .env selbst gehoert nicht ins Repo (siehe .gitignore). +# +# In Portainer traegst du dieselben Werte stattdessen als Stack-Variablen ein; +# dann braucht es die Datei dort gar nicht. +# +# Erzeugen: +# openssl rand -hex 16 DB_PASSWORD, MINIO_ROOT_PASSWORD +# openssl rand -hex 32 API_TOKEN_HMAC_SECRET (muss 32 Byte sein) +# openssl rand -hex 12 ADMIN_PASSWORD + +DB_PASSWORD= +MINIO_ROOT_PASSWORD= +API_TOKEN_HMAC_SECRET= +ADMIN_PASSWORD= + +# Unter welcher Adresse die Dateien oeffentlich liegen. Ohne sie liefert MinIO +# Links auf den internen Containernamen aus — die gehen von aussen ins Leere. +PUBLIC_URL=https://fivecdn.d4rkst3r.de + +# Das Docker-Netz, in dem der bestehende Reverse Proxy haengt. +PROXY_NETWORK=proxy diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..24d9d01 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Die echten Geheimnisse. Nur .env.example gehoert ins Repo. +.env diff --git a/README.md b/README.md new file mode 100644 index 0000000..71fccbd --- /dev/null +++ b/README.md @@ -0,0 +1,84 @@ +# d4rk_media + +Der Medien-Stack: **Fivemanage Lite** mit MySQL und MinIO. Ein Ablageort für +alle Resourcen — Fahrzeugbilder aus `d4rk_photostudio`, Item-Icons, Marken, +was sonst noch anfällt. + +Bisher liegt das auf dem Nextcloud und wird per rclone von Hand hochgeladen. +Das trägt, solange ein Mensch hochlädt. Sobald ein Script es tun soll, fehlt +ein Schreibweg über HTTP — und genau den bringt Lite mit, samt Token je +Resource und einer Oberfläche zum Nachsehen. + +--- + +## Ausprobieren, bevor es auf den Server geht + +`0.1.0-beta.23` ist früh. Erst auf Docker Desktop: + +```bash +cp .env.example .env # und ausfüllen, siehe unten +docker compose -f docker-compose.local.yml up -d +``` + +- Oberfläche: — `admin` und dein `ADMIN_PASSWORD` +- MinIO: — `lite` und dein `MINIO_ROOT_PASSWORD` + +Wenn das trägt, dasselbe auf dem Server. + +--- + +## Auf dem Server, über Portainer + +Portainer kann einen Stack direkt aus diesem Repo ziehen: + +**Stacks → Add stack → Repository** + +| Feld | Wert | +|---|---| +| Repository URL | `https://git.d4rkst3r.de/D4rkst3r/d4rk_media` | +| Compose path | `docker-compose.yml` | +| Environment variables | die vier Geheimnisse plus `PUBLIC_URL` | + +Die Werte gehören **in die Stack-Variablen**, nicht in eine Datei im Repo. +`.env` steht deshalb in `.gitignore`. + +Davor brauchst du auf dem Reverse Proxy, der schon `cdn.d4rkst3r.de` bedient: + +- `fivecdn.d4rkst3r.de` → `minio:9000` (die Dateien) +- eine zweite Adresse → `lite:8080` (die Oberfläche), oder gar nicht öffentlich + +--- + +## Die vier Geheimnisse + +```bash +openssl rand -hex 16 # DB_PASSWORD +openssl rand -hex 16 # MINIO_ROOT_PASSWORD +openssl rand -hex 32 # API_TOKEN_HMAC_SECRET (muss 32 Byte sein) +openssl rand -hex 12 # ADMIN_PASSWORD +``` + +--- + +## Was hier bewusst fehlt + +**ClickHouse und Jaeger.** Beide stehen in der Entwicklungs-Compose des +Projekts und sind für strukturiertes Logging und Tracing da. Zum Ablegen von +Bildern braucht es sie nicht, und ClickHouse ist eine schwere Abhängigkeit. +Nachrüsten geht jederzeit — die App findet sie über `CLICKHOUSE_*`. + +**Offene Ports in der Betriebsfassung.** Nur der Reverse Proxy spricht mit der +App; Datenbank und MinIO bleiben im internen Netz. Die Entwicklungs-Compose des +Projekts macht 5432, 9000, 16686 und mehr auf — dort in Ordnung, hier nicht. + +--- + +## Herkunft + +Zusammengestellt aus [fivemanage/lite](https://github.com/fivemanage/lite): +dessen `README.md`, `deployments/docker-compose.yml` (Entwicklung, ohne die +App) und `deployments/docker-compose.test.yml` (zeigt die App-Verdrahtung und +dass MySQL genügt). + +**Nicht laufen gelassen.** Rechne mit ein, zwei Anläufen — vor allem beim +ersten Login und beim Bucket. diff --git a/docker-compose.local.yml b/docker-compose.local.yml new file mode 100644 index 0000000..f1a7778 --- /dev/null +++ b/docker-compose.local.yml @@ -0,0 +1,90 @@ +# Zum Ausprobieren auf Docker Desktop. +# +# Der Unterschied zur Betriebsfassung ist Absicht und in beide Richtungen: +# hier sind die Ports offen und es gibt keinen Reverse Proxy, dort ist es +# umgekehrt. Eine `beta.23` gehoert erst auf einen Rechner, an dem nichts +# haengt — und wenn sie dort traegt, auf den Server. +# +# docker compose -f docker-compose.local.yml up -d +# +# Danach: http://localhost:8080 (admin / ADMIN_PASSWORD aus .env) +# http://localhost:9001 (MinIO, lite / MINIO_ROOT_PASSWORD) + +services: + db: + image: mysql:8 + environment: + MYSQL_DATABASE: fivemanage_lite + MYSQL_USER: lite + MYSQL_PASSWORD: ${DB_PASSWORD:?bitte setzen} + MYSQL_RANDOM_ROOT_PASSWORD: "yes" + volumes: + - db:/var/lib/mysql + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 5s + timeout: 5s + retries: 20 + + minio: + image: minio/minio:latest + command: server /data --console-address ":9001" + environment: + MINIO_ROOT_USER: lite + MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?bitte setzen} + # Oertlich: die Dateien liegen unter derselben Adresse, unter der MinIO + # antwortet. Erst auf dem Server tritt fivecdn.d4rkst3r.de an die Stelle. + MINIO_SERVER_URL: http://localhost:9000 + ports: + - "9000:9000" + - "9001:9001" + volumes: + - minio:/data + healthcheck: + test: ["CMD", "mc", "ready", "local"] + interval: 5s + timeout: 5s + retries: 20 + + minio-init: + image: minio/mc:latest + depends_on: + minio: + condition: service_healthy + environment: + MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?bitte setzen} + entrypoint: > + /bin/sh -c " + mc alias set local http://minio:9000 lite $$MINIO_ROOT_PASSWORD && + mc mb --ignore-existing local/media && + mc anonymous set download local/media && + echo 'Bucket media ist bereit' + " + restart: "no" + + lite: + image: fivemanage/lite:0.1.0-beta.23 + depends_on: + db: + condition: service_healthy + minio: + condition: service_healthy + environment: + PORT: "8080" + ENV: dev + DB_DRIVER: mysql + DSN: lite:${DB_PASSWORD:?bitte setzen}@tcp(db:3306)/fivemanage_lite + ADMIN_PASSWORD: ${ADMIN_PASSWORD:?bitte setzen} + API_TOKEN_HMAC_SECRET: ${API_TOKEN_HMAC_SECRET:?bitte setzen} + S3_PROVIDER: minio + AWS_ENDPOINT: http://minio:9000 + AWS_ACCESS_KEY_ID: lite + AWS_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:?bitte setzen} + AWS_BUCKET: media + AWS_REGION: auto + ports: + - "8080:8080" + +volumes: + db: + minio: diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..8e8d81f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,113 @@ +# Fivemanage Lite — fuer den Betrieb, ueber Portainer aus diesem Repo. +# +# Abgeleitet aus den beiden Compose-Dateien im Projekt (fivemanage/lite) und +# dem README. Deren docker-compose.yml ist fuer die ENTWICKLUNG: sie startet +# Datenbank, ClickHouse, MinIO und Jaeger, aber nicht die Anwendung, und mit +# Standardpasswoertern. Die docker-compose.test.yml zeigt dafuer, wie der +# App-Container verdrahtet wird — und dass MySQL genuegt. +# +# Bewusst NICHT dabei: +# +# ClickHouse und Jaeger. Beides ist strukturiertes Logging und Tracing. Fuer +# das Ablegen von Bildern braucht es sie nicht, und ClickHouse ist eine +# schwere Abhaengigkeit. Nachruesten geht spaeter. +# +# Offene Ports. Nur der Reverse Proxy spricht mit der App; Datenbank und +# MinIO bleiben im internen Netz. Zum Ausprobieren gibt es +# docker-compose.local.yml — die macht es andersherum, und dort ist es +# richtig. + +services: + db: + image: mysql:8 + restart: unless-stopped + environment: + MYSQL_DATABASE: fivemanage_lite + MYSQL_USER: lite + MYSQL_PASSWORD: ${DB_PASSWORD:?bitte in .env oder als Stack-Variable setzen} + MYSQL_RANDOM_ROOT_PASSWORD: "yes" + volumes: + - db:/var/lib/mysql + networks: [internal] + healthcheck: + # Ohne das startet die App gegen eine Datenbank, die noch nicht + # antwortet, und beendet sich — beim ersten Hochfahren jedes Mal. + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 10s + timeout: 5s + retries: 12 + + minio: + image: minio/minio:latest + restart: unless-stopped + command: server /data --console-address ":9001" + environment: + MINIO_ROOT_USER: lite + MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?bitte setzen} + MINIO_SERVER_URL: ${PUBLIC_URL:?bitte setzen} + volumes: + - minio:/data + networks: [internal, proxy] + healthcheck: + test: ["CMD", "mc", "ready", "local"] + interval: 10s + timeout: 5s + retries: 12 + + # Legt den Bucket an und stellt ihn auf oeffentlich lesbar. Laeuft einmal und + # beendet sich. Ohne diesen Schritt schlaegt der erste Upload fehl, und die + # Meldung nennt den Grund nicht. + minio-init: + image: minio/mc:latest + depends_on: + minio: + condition: service_healthy + environment: + MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?bitte setzen} + entrypoint: > + /bin/sh -c " + mc alias set local http://minio:9000 lite $$MINIO_ROOT_PASSWORD && + mc mb --ignore-existing local/media && + mc anonymous set download local/media && + echo 'Bucket media ist bereit' + " + networks: [internal] + restart: "no" + + lite: + image: fivemanage/lite:0.1.0-beta.23 + restart: unless-stopped + depends_on: + db: + condition: service_healthy + minio: + condition: service_healthy + environment: + PORT: "8080" + ENV: production + DB_DRIVER: mysql + # Go-MySQL-Form, wie in deren docker-compose.test.yml. + DSN: lite:${DB_PASSWORD:?bitte setzen}@tcp(db:3306)/fivemanage_lite + ADMIN_PASSWORD: ${ADMIN_PASSWORD:?bitte setzen} + API_TOKEN_HMAC_SECRET: ${API_TOKEN_HMAC_SECRET:?bitte setzen} + S3_PROVIDER: minio + AWS_ENDPOINT: http://minio:9000 + AWS_ACCESS_KEY_ID: lite + AWS_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:?bitte setzen} + AWS_BUCKET: media + AWS_REGION: auto + networks: [internal, proxy] + # KEIN ports: — der Reverse Proxy erreicht die App ueber das Netz `proxy`. + # Wer hier 8080 aufmacht, hat die Oberflaeche ohne TLS im Internet. + +networks: + internal: + driver: bridge + proxy: + # Das Netz, in dem der bestehende Reverse Proxy haengt. + name: ${PROXY_NETWORK:-proxy} + external: true + +volumes: + db: + minio: