Files
sshkeyvault/docker-compose.yml
T
florian.wildeandClaude Opus 5.5 4a23930b54 feat(worker): Worker mit pg-boss, Vorgaenge und Docker-Betrieb (#007)
Die Oberflaeche legt einen Vorgang an und schickt nur dessen ID in die
Warteschlange; der Worker fuehrt ihn aus und haelt Status, Ergebnis
oder Fehler fest. So bleiben lange SSH-Vorgaenge aus dem Webprozess
heraus, und der Fortschritt ist ohne Job-Interna sichtbar.

Kein automatisches Wiederholen: ein halb ausgefuehrter Schreibvorgang
auf einem Host gehoert vor einen Menschen. Fehlertexte aus fremden
Bibliotheken erreichen die Oberflaeche nie.

Dockerfile und Compose fuer den Betrieb: Master-Key als Secret nur im
Worker, Datenbank in einem internen Netz.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:21:41 +02:00

115 lines
3.8 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SSHKeyVault – Betrieb mit Weboberflaeche, Worker und Datenbank.
# 1. cp .env.example .env und Werte eintragen (mindestens SSHKV_APP_SECRET, POSTGRES_PASSWORD,
# SSHKV_APP_URL, SSHKV_BREAKGLASS_PASSWORD)
# 2. Master-Key erzeugen (nur fuer den Worker lesbar, Container-Benutzer 1001):
# mkdir -p geheim && head -c 32 /dev/urandom > geheim/master.key
# sudo chown 1001:1001 geheim/master.key && sudo chmod 400 geheim/master.key
# 3. docker compose up -d
# Nur im internen Netz/VPN betreiben und einen Reverse Proxy mit TLS davorsetzen (docs/betrieb).
name: sshkv
services:
db:
image: postgres:17-alpine
container_name: sshkv-db
restart: unless-stopped
environment:
POSTGRES_USER: sshkv
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD fehlt in der .env}
POSTGRES_DB: sshkv
volumes:
- datenbank:/var/lib/postgresql/data
networks: [datenbank]
healthcheck:
test: ["CMD-SHELL", "pg_isready -U sshkv"]
interval: 10s
timeout: 5s
retries: 10
# Laeuft einmal je Start: Schema einspielen, Notfall-Admin und Vorlagen anlegen.
migrate:
build:
context: .
target: bauen
image: sshkv-migrate
restart: "no"
depends_on:
db:
condition: service_healthy
command: ["sh", "-c", "pnpm prisma migrate deploy && pnpm prisma db seed"]
environment:
DATABASE_URL: postgresql://sshkv:${POSTGRES_PASSWORD}@db:5432/sshkv?schema=public
SSHKV_BREAKGLASS_USER: ${SSHKV_BREAKGLASS_USER:-notfall}
SSHKV_BREAKGLASS_PASSWORD: ${SSHKV_BREAKGLASS_PASSWORD:-}
networks: [datenbank]
web:
build: .
image: sshkv
container_name: sshkv-web
restart: unless-stopped
depends_on:
migrate:
condition: service_completed_successfully
environment:
DATABASE_URL: postgresql://sshkv:${POSTGRES_PASSWORD}@db:5432/sshkv?schema=public
SSHKV_APP_URL: ${SSHKV_APP_URL:?SSHKV_APP_URL fehlt in der .env}
SSHKV_APP_SECRET: ${SSHKV_APP_SECRET:?SSHKV_APP_SECRET fehlt in der .env}
SSHKV_OIDC_ISSUER: ${SSHKV_OIDC_ISSUER:-}
SSHKV_OIDC_CLIENT_ID: ${SSHKV_OIDC_CLIENT_ID:-}
SSHKV_OIDC_CLIENT_SECRET: ${SSHKV_OIDC_CLIENT_SECRET:-}
SSHKV_OIDC_NAME: ${SSHKV_OIDC_NAME:-authentik}
SSHKV_OIDC_GROUP_ADMIN: ${SSHKV_OIDC_GROUP_ADMIN:-sshkv-admins}
SSHKV_OIDC_GROUP_OPERATOR: ${SSHKV_OIDC_GROUP_OPERATOR:-sshkv-operators}
SSHKV_OIDC_GROUP_READER: ${SSHKV_OIDC_GROUP_READER:-sshkv-readers}
# Absichtlich KEIN Master-Key: eine Luecke im Webprozess allein entschluesselt keine
# Private Keys. Nach aussen braucht er nur den OIDC-Anbieter.
ports:
- "${SSHKV_BIND:-127.0.0.1}:${SSHKV_PORT:-3400}:3400"
networks: [datenbank, aussen]
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3400/api/gesundheit"]
interval: 30s
timeout: 5s
retries: 5
start_period: 20s
worker:
image: sshkv
container_name: sshkv-worker
restart: unless-stopped
command: ["./start.sh", "worker"]
depends_on:
migrate:
condition: service_completed_successfully
web:
condition: service_started
environment:
DATABASE_URL: postgresql://sshkv:${POSTGRES_PASSWORD}@db:5432/sshkv?schema=public
SSHKV_APP_SECRET: ${SSHKV_APP_SECRET}
SSHKV_MASTER_KEY_FILE: /run/secrets/master_key
SSHKV_SYNC_CRON: ${SSHKV_SYNC_CRON:-30 2 * * *}
secrets:
- master_key
# Der Worker braucht die Datenbank und den Weg zu den Hosts.
networks: [datenbank, aussen]
healthcheck:
test: ["CMD-SHELL", "pgrep -f dist/worker.mjs > /dev/null"]
interval: 60s
timeout: 5s
retries: 3
secrets:
master_key:
file: ${SSHKV_MASTER_KEY_HOST_FILE:-./geheim/master.key}
networks:
# Die Datenbank hat keinen Weg nach draussen.
datenbank:
internal: true
aussen: {}
volumes:
datenbank: