Files
sendsecret/docker-compose.yml
Lucas Orth 681fc1649a SendSecret: Erstimport und Umstellung auf Tag-Deployment
Wrapper-Frontend vor cryptgeon: der Browser verschluesselt lokal, per Mail
geht nur der Link raus.

Fuer das Deployment nach den Konventionen aus DEPLOY.md hergerichtet:

- docker-compose.yml mit festem Projekt- und Container-Namen, kein
  ports-Mapping, Healthcheck als Deploy-Gate. cryptgeon und redis liegen
  im internen Netz, nur app haengt im Web-Netz.
- cryptgeon von latest auf 2.9.3 gepinnt. Das ist derselbe Stand, den
  latest bisher geliefert hat; 2.6.2 existiert nicht.
- /healthz in server.js, vor dem Catch-all-Proxy registriert.
- Dockerfile auf npm ci mit Lockfile und non-root umgestellt.
- .gitea/workflows/deploy.yml: Build und Syntaxpruefung vor dem Deploy,
  .env aus dem Repo-Secret DOTENV.

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

71 lines
2.4 KiB
YAML

# Fester Projektname. Ohne das leitet Compose ihn aus dem Verzeichnisnamen
# ab - und der ist im CI-Job ein anderer als auf dem Host.
name: sendsecret
services:
# Der Wrapper: eigenes Frontend, Mailversand, Proxy auf cryptgeon.
# Das ist der einzige Dienst, den der Nginx Proxy Manager sieht.
app:
# Versionstag ermoeglicht Rollback ohne Rebuild.
image: sendsecret:${IMAGE_TAG:-latest}
build: ./app
# Fester Name: das ist die Adresse, auf die der Proxy zeigt.
container_name: sendsecret
restart: unless-stopped
# Wird im Workflow aus dem Secret DOTENV erzeugt.
env_file: .env
depends_on:
- cryptgeon
networks:
- nginx-proxy-manager_default
- internal
# Pflicht: der Deploy-Schritt nutzt --wait und macht das zum Gate.
# Abweichung von den 60s der Vorlage: bei --wait-timeout 180 reicht ein
# 60s-Intervall nur fuer drei Versuche - der Deploy wuerde beim ersten
# Fehlschlag knapp.
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3000/healthz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 15s
timeout: 5s
retries: 3
start_period: 10s
# Cryptgeon haelt die verschluesselten Notizen. Version gepinnt: die
# Frontend-Bundles verschluesseln mit occulto 2.0.6 gegen dieses API-Format.
cryptgeon:
image: cupcakearmy/cryptgeon:2.9.3
container_name: sendsecret-cryptgeon
restart: unless-stopped
depends_on:
redis:
condition: service_healthy
environment:
REDIS_URL: redis://redis/
ALLOW_ADVANCED: 'false'
# Bewusst nicht im Web-Netz: erreichbar nur ueber den Proxy in app.
networks:
- internal
# Reiner Zwischenspeicher, ohne Persistenz - Notizen sind einmalig
# abrufbar und sollen einen Neustart nicht ueberleben. Deshalb kein Volume.
redis:
image: redis:7-alpine
command: redis-server --save "" --appendonly no
container_name: sendsecret-redis
restart: unless-stopped
networks:
- internal
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 5
# Kein ports-Mapping: Der Proxy erreicht app ueber das gemeinsame Netz unter
# dem Container-Namen. cryptgeon und redis haengen nur im internen Netz.
networks:
nginx-proxy-manager_default:
external: true
internal:
name: sendsecret-internal