feat(betrieb): native Installation, Proxmox-Einzeiler und Abnahme
Prüfung / pruefung (push) Canceled after 0s
Prüfung / pruefung (pull_request) Canceled after 0s
Prüfung / e2e (push) Canceled after 0s
Prüfung / e2e (pull_request) Canceled after 0s

Zwei Wege in den Betrieb, beide so weit gefahren, wie es hier moeglich war.

deploy/install.sh richtet Debian 13 in neun Schritten ein: PostgreSQL 17 hoert
nur am Unix-Socket, der Dienstnutzer hat kein Login, die Geheimnisse entstehen
im Zielsystem und liegen 0600 bei root. Die Umgebungsdatei wird nie
ueberschrieben -- auch nicht beim Aktualisieren, sonst enden alle Sitzungen und
die verschluesselten Bind-Passwoerter waeren unlesbar.

deploy/proxmox/laufzettel.sh legt den Container an und ruft install.sh darin
auf. Der pct-Teil ist ungetestet, weil kein PVE-Host zur Verfuegung stand; die
Gegenprobe steht als Pruefliste in docs/betrieb/proxmox.md, das Folge-Issue ist
#024.

Die Abnahme gegen alle 61 Kriterien hat drei Zusagen ohne Deckung gefunden, alle
behoben: der Healthcheck des Webdienstes konnte nie bestehen (busybox loest
localhost nach ::1 auf, Next lauscht nur auf IPv4), die CI-Pipeline konnte in
keinem Job gruen werden (kein LDAP-Dienst, kein gestarteter Server, kein
shellcheck), und der README nannte fuer die Entwicklungsdatenbank den falschen
Port.

Closes #19
This commit is contained in:
Florian Wilde
2026-09-26 15:53:01 +02:00
parent fbbb634e56
commit bf1e52cf73
20 changed files with 3663 additions and 103 deletions
+35 -3
View File
@@ -38,7 +38,29 @@ services:
target: bauen
restart: "no"
environment:
DATABASE_URL: ${DATABASE_URL:-postgresql://${POSTGRES_USER:-laufzettel}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-laufzettel}?schema=public}
# Immer aus den Einzelteilen, **nie** aus einer DATABASE_URL der .env: dort
# steht die Adresse fuer die Entwicklung (localhost und ein offener Port),
# und im Container zeigt sie ins Leere. Wer den dokumentierten Weg ging,
# bekam einen Stand, der nicht startet — gefunden bei der Abnahme zu #019.
# Im Compose-Stand heisst die Datenbank immer `postgres`, das ist der
# Dienstname im Netz `intern`.
DATABASE_URL: postgresql://${POSTGRES_USER:-laufzettel}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-laufzettel}?schema=public
#
# Fuer die Migrationen braucht es nichts weiter — wohl aber fuer den Seed,
# der ueber denselben Dienst gefahren wird:
# `docker compose run --rm migrate pnpm db:seed` (siehe README).
#
# APP_SECRET verschluesselt das Bind-Passwort der Beispiel-Verzeichnis-
# quelle. Ohne es brach der Seed mit einem Stapelverlauf ab, und zwar
# nachdem er die Vorlagen schon angelegt hatte — gefunden bei der Abnahme
# zu #019: der dokumentierte Befehl scheiterte auf einer frischen
# Installation.
APP_SECRET: ${APP_SECRET:?APP_SECRET fehlt in der .env}
SEED_MODE: ${SEED_MODE:-INTERN}
SEED_ADMIN_EMAIL: ${SEED_ADMIN_EMAIL:-}
SEED_ADMIN_PASSWORD: ${SEED_ADMIN_PASSWORD:-}
SEED_ORG_NAME: ${SEED_ORG_NAME:-}
SEED_ORG_KUERZEL: ${SEED_ORG_KUERZEL:-}
depends_on:
postgres:
condition: service_healthy
@@ -55,7 +77,13 @@ services:
GIT_SHA: ${GIT_SHA:-}
restart: unless-stopped
environment:
DATABASE_URL: ${DATABASE_URL:-postgresql://${POSTGRES_USER:-laufzettel}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-laufzettel}?schema=public}
# Immer aus den Einzelteilen, **nie** aus einer DATABASE_URL der .env: dort
# steht die Adresse fuer die Entwicklung (localhost und ein offener Port),
# und im Container zeigt sie ins Leere. Wer den dokumentierten Weg ging,
# bekam einen Stand, der nicht startet — gefunden bei der Abnahme zu #019.
# Im Compose-Stand heisst die Datenbank immer `postgres`, das ist der
# Dienstname im Netz `intern`.
DATABASE_URL: postgresql://${POSTGRES_USER:-laufzettel}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-laufzettel}?schema=public
APP_SECRET: ${APP_SECRET:?APP_SECRET fehlt in der .env}
APP_URL: ${APP_URL:?APP_URL fehlt in der .env}
AUTH_LOCAL_ENABLED: ${AUTH_LOCAL_ENABLED:-false}
@@ -83,7 +111,11 @@ services:
- intern
- extern
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/gesundheit"]
# 127.0.0.1, nicht localhost: busybox-wget loest localhost zuerst nach ::1
# auf, Next lauscht aber nur auf 0.0.0.0:3000. Der Healthcheck schlug
# deshalb dauerhaft fehl, waehrend die App einwandfrei antwortete -
# gefunden bei der Abnahme zu #019.
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/api/gesundheit"]
interval: 30s
timeout: 5s
retries: 5