docs: Rollout-131-Vorbereitung #186

Closed
patrick wants to merge 3 commits from docs/rollout-131-vorbereitung into main
pull from: docs/rollout-131-vorbereitung
7 changed files with 484 additions and 0 deletions

No files matched your search

+182
View File
@@ -0,0 +1,182 @@
#!/usr/bin/env bash
# Rollout-Abschluss fuer Host 131 (Vorstufe zur Produktion): fuehrt die
# verbleibenden manuellen Schritte aus docs/ROLLOUT-131-VORBEREITUNG.md,
# Abschnitt 5 (Schritte 3-9) automatisiert aus.
#
# Setzt voraus, dass deploy/rollout-131-sync.sh bereits gelaufen ist (Build-
# Pruefung + Env-Datei-Grundgeruest) UND dass die 5 echten TODO-Werte in
# /etc/nexarch/connect-app.env und /etc/nexarch/dms-app.env von Hand
# eingetragen wurden -- dieses Skript generiert/raet sie NICHT.
#
# Aufruf (als root, auf Host 131): ./deploy/rollout-131-apply.sh
#
# Idempotent: mehrfacher Aufruf ist sicher (Units werden neu geschrieben,
# aber Env-Dateien nie ueberschrieben; systemctl enable --now ist idempotent).
# Gibt NIRGENDS einen Secret-/Token-Wert aus, auch nicht beim Pruefen ob eine
# Variable gesetzt ist.
set -euo pipefail
REPO_DIR="${NEXARCH_ROLLOUT_REPO_DIR:-/root/nexarch-code}"
ENV_DIR=/etc/nexarch
DMS_INSTALL_DIR="${NEXARCH_DMS_INSTALL_DIR:-/opt/nexarch-dms}"
CONNECT_INSTALL_DIR="${NEXARCH_CONNECT_INSTALL_DIR:-/opt/nexarch-connect}"
DMS_STORAGE_DIR="${NEXARCH_DMS_STORAGE_DIR:-/var/lib/nexarch-dms/storage}"
DMS_STAGING_DIR="${NEXARCH_DMS_STAGING_DIR:-/var/lib/nexarch-dms/staging}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ "$(id -u)" -ne 0 ]; then
echo "Bitte als root ausfuehren." >&2
exit 1
fi
# Prueft nur ob eine Variable gesetzt UND nicht mehr als "# TODO" markiert
# ist -- gibt den Wert selbst nie aus.
require_set() {
local file="$1" name="$2"
local line
line="$(grep "^${name}=" "$file" 2>/dev/null || true)"
if [ -z "$line" ]; then
echo "FEHLT: ${name} in ${file} (Variable existiert gar nicht)" >&2
return 1
fi
if echo "$line" | grep -q '# TODO'; then
echo "OFFEN: ${name} in ${file} ist noch als TODO markiert" >&2
return 1
fi
if [ "$line" = "${name}=" ]; then
echo "LEER: ${name} in ${file} ist gesetzt, aber ohne Wert" >&2
return 1
fi
return 0
}
echo "== 1. Pruefe die 5 echten TODO-Werte =="
missing=0
require_set "$ENV_DIR/connect-app.env" NEXARCH_CONNECT_APP_LISTEN_ADDR || missing=1
require_set "$ENV_DIR/connect-app.env" NEXARCH_CONNECT_APP_TENANT_DSN || missing=1
require_set "$ENV_DIR/dms-app.env" NEXARCH_DMS_APP_CORE_SERVICE_TOKEN || missing=1
require_set "$ENV_DIR/dms-app.env" NEXARCH_DMS_APP_KEK_CLIENT_ID || missing=1
require_set "$ENV_DIR/dms-app.env" NEXARCH_DMS_APP_KEK_CLIENT_SECRET || missing=1
if [ "$missing" -eq 1 ]; then
echo "Abbruch: mindestens ein TODO-Wert fehlt noch (siehe oben)." >&2
echo "Trage die fehlenden Werte von Hand in die genannten Dateien ein und starte das Skript erneut." >&2
exit 1
fi
echo "Alle 5 TODO-Werte sind gesetzt."
echo "== 2. Build (falls rollout-131-sync.sh das noch nicht getan hat) =="
for mod in dms connect; do
if [ -f "$REPO_DIR/$mod/go.mod" ]; then
( cd "$REPO_DIR/$mod" && go build ./... && go vet ./... )
echo "gebaut/verifiziert: $mod"
else
echo "FEHLER: $REPO_DIR/$mod/go.mod nicht gefunden -- Code-Sync vorher ausfuehren." >&2
exit 1
fi
done
echo "== 3. Binaries kopieren =="
mkdir -p "$DMS_INSTALL_DIR/bin" "$CONNECT_INSTALL_DIR/bin"
( cd "$REPO_DIR/dms" && go build -o "$DMS_INSTALL_DIR/bin/dms-app" ./cmd/app )
( cd "$REPO_DIR/dms" && go build -o "$DMS_INSTALL_DIR/bin/dms-worker" ./cmd/worker )
( cd "$REPO_DIR/connect" && go build -o "$CONNECT_INSTALL_DIR/bin/connect-app" ./cmd/connect-app )
echo "Binaries liegen unter ${DMS_INSTALL_DIR}/bin und ${CONNECT_INSTALL_DIR}/bin."
if id nexarch >/dev/null 2>&1; then
chown -R nexarch:nexarch "$DMS_INSTALL_DIR" "$CONNECT_INSTALL_DIR"
else
echo "WARNUNG: Systembenutzer 'nexarch' existiert nicht -- Units werden trotzdem als User=nexarch geschrieben (wie bei Core/Archive ueblich), legen den Benutzer aber nicht an. Falls er fehlt, vor dem Start anlegen: useradd --system --no-create-home --shell /usr/sbin/nologin nexarch" >&2
fi
echo "== 4. Storage-/Staging-Verzeichnisse fuer DMS anlegen =="
mkdir -p "$DMS_STORAGE_DIR" "$DMS_STAGING_DIR"
if id nexarch >/dev/null 2>&1; then
chown -R nexarch:nexarch "$DMS_STORAGE_DIR" "$DMS_STAGING_DIR"
fi
echo "== 5. dms-worker.env anlegen (falls noch nicht vorhanden) =="
# Uebernimmt was direkt aus der bereits fertigen dms-app.env ableitbar ist
# (beide gehoeren zum selben Dienst/Mandanten). Werte werden aus der
# Quelldatei kopiert, nie hier im Skript ausgegeben.
if [ ! -f "$ENV_DIR/dms-worker.env" ]; then
for v in NEXARCH_DMS_APP_TENANT_DSN NEXARCH_DMS_APP_TENANT_SLUG \
NEXARCH_DMS_APP_STORAGE_DIR NEXARCH_DMS_APP_STORAGE_SIGNING_SECRET \
NEXARCH_DMS_APP_STORAGE_PUBLIC_BASE_URL NEXARCH_DMS_APP_USAGE_ENDPOINT_URL \
NEXARCH_DMS_APP_USAGE_CLIENT_ID NEXARCH_DMS_APP_USAGE_CLIENT_SECRET \
NEXARCH_DMS_APP_KEK_ENDPOINT_URL NEXARCH_DMS_APP_KEK_CLIENT_ID \
NEXARCH_DMS_APP_KEK_CLIENT_SECRET NEXARCH_DMS_APP_RETENTION_BASE_URL; do
line="$(grep "^${v}=" "$ENV_DIR/dms-app.env" 2>/dev/null || true)"
if [ -n "$line" ] && ! echo "$line" | grep -q '# TODO'; then
# NEXARCH_DMS_APP_* -> NEXARCH_DMS_WORKER_* (gleicher Suffix)
worker_name="NEXARCH_DMS_WORKER_${v#NEXARCH_DMS_APP_}"
worker_value="${line#*=}"
echo "${worker_name}=${worker_value}" >> "$ENV_DIR/dms-worker.env"
fi
done
{
echo "NEXARCH_DMS_WORKER_METRICS_ADDR=127.0.0.1:8601"
echo "NEXARCH_DMS_WORKER_KOSIT_ADDR=127.0.0.1:8610"
echo "NEXARCH_DMS_WORKER_CONCURRENCY=2"
} >> "$ENV_DIR/dms-worker.env"
chmod 600 "$ENV_DIR/dms-worker.env"
if id nexarch >/dev/null 2>&1; then
chown nexarch:nexarch "$ENV_DIR/dms-worker.env"
fi
echo "${ENV_DIR}/dms-worker.env angelegt (Werte aus dms-app.env uebernommen, Metrics-Adresse + KoSIT-Sidecar + Concurrency gesetzt)."
echo "Pruefe danach von Hand, ob NEXARCH_DMS_WORKER_TENANT_SLUG/_STORAGE_* uebernommen wurden -- ohne Storage-Variablen werden Fachjobs nicht verarbeitet (siehe dms/docs/BETRIEB-UMGEBUNGSVARIABLEN.md, Abschnitt dms-worker)."
else
echo "${ENV_DIR}/dms-worker.env existiert bereits -- wird nicht ueberschrieben."
fi
echo "== 6. systemd-Units installieren =="
sed -e "s#__INSTALL_DIR__#${CONNECT_INSTALL_DIR}#g" \
"$SCRIPT_DIR/systemd/nexarch-connect-app.service.tmpl" > /etc/systemd/system/nexarch-connect-app.service
sed -e "s#__INSTALL_DIR__#${DMS_INSTALL_DIR}#g" \
-e "s#__STORAGE_DIR__#${DMS_STORAGE_DIR}#g" \
-e "s#__STAGING_DIR__#${DMS_STAGING_DIR}#g" \
"$SCRIPT_DIR/systemd/nexarch-dms-app.service.tmpl" > /etc/systemd/system/nexarch-dms-app.service
sed -e "s#__INSTALL_DIR__#${DMS_INSTALL_DIR}#g" \
-e "s#__STORAGE_DIR__#${DMS_STORAGE_DIR}#g" \
"$SCRIPT_DIR/systemd/nexarch-dms-worker.service.tmpl" > /etc/systemd/system/nexarch-dms-worker.service
echo "Units geschrieben: nexarch-connect-app, nexarch-dms-app, nexarch-dms-worker"
echo "== 7. daemon-reload =="
systemctl daemon-reload
echo "== 8. account-api neu starten (Code wurde durch rollout-131-sync.sh bereits neu gebaut) =="
systemctl restart nexarch-account-api
echo "Warte auf /auth/module-jwks..."
ok=0
for i in 1 2 3 4 5 6 7 8 9 10; do
if curl -sf --max-time 2 http://127.0.0.1:8099/auth/module-jwks >/dev/null 2>&1; then
ok=1
break
fi
sleep 2
done
if [ "$ok" -ne 1 ]; then
echo "FEHLER: http://127.0.0.1:8099/auth/module-jwks antwortet nach Neustart und 20s Wartezeit nicht." >&2
echo "Abbruch -- Connect/DMS wuerden ohne funktionierende JWKS-Route mit ungueltigen Tokens starten." >&2
echo "Pruefe: journalctl -u nexarch-account-api -n 50" >&2
exit 1
fi
echo "account-api liefert /auth/module-jwks."
echo "== 9. connect-app, dms-app, dms-worker aktivieren und starten =="
systemctl enable --now nexarch-connect-app.service
systemctl enable --now nexarch-dms-app.service
systemctl enable --now nexarch-dms-worker.service
echo "== 10. Health-Check =="
"$SCRIPT_DIR/rollout-131-healthcheck.sh"
echo "== Fertig =="
echo "Bei NICHT-ERREICHBAR-Eintraegen oben: journalctl -u <dienstname> -n 50 pruefen."
echo "Die fuenf bereits vor diesem Rollout fehlgeschlagenen Archive-Backup-/Scrub-Dienste"
echo "(siehe docs/ROLLOUT-131-VORBEREITUNG.md, Abschnitt 1) sind unabhaengig davon und"
echo "wurden von diesem Skript nicht angefasst."
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env bash
# Health-Check nach dem manuellen Rollout auf Host 131 (Vorstufe zur
# Produktion). Fuehrt selbst KEINEN Dienststart aus, nur Lesezugriffe
# (curl gegen bekannte Ports). Aufruf: ./deploy/rollout-131-healthcheck.sh
set -uo pipefail
check() {
local name="$1" url="$2"
local code
code=$(curl -s -o /dev/null -w '%{http_code}' --max-time 3 "$url" 2>/dev/null)
if [ "$code" = "000" ]; then
printf ' %-32s %-45s NICHT ERREICHBAR\n' "$name" "$url"
else
printf ' %-32s %-45s HTTP %s\n' "$name" "$url" "$code"
fi
}
echo "== Core (bereits laufend erwartet) =="
check "nexarch-core" "http://127.0.0.1:8080/healthz"
check "account-api" "http://127.0.0.1:8099/healthz"
check "account-api-jwks" "http://127.0.0.1:8099/auth/module-jwks"
check "kek-api" "http://127.0.0.1:8102/healthz"
check "policy-api" "http://127.0.0.1:8093/healthz"
echo "== DMS (Erstinstallation durch diesen Rollout) =="
check "dms-app" "http://127.0.0.1:8600/healthz"
check "dms-worker-metrics" "http://127.0.0.1:8601/metrics"
check "dms-kosit-sidecar" "http://127.0.0.1:8610/healthz"
echo "== Connect (Erstinstallation durch diesen Rollout) =="
check "connect-app" "http://127.0.0.1:9500/healthz"
echo
echo "Hinweis: Ports/Pfade aus deploy/ports.tsv bzw. den jeweiligen"
echo "BETRIEB-UMGEBUNGSVARIABLEN.md-Dokumenten je Modul; falls ein Dienst auf"
echo "einer anderen Adresse laeuft als hier angenommen, dieses Skript"
echo "entsprechend anpassen (kein Autodiscovery, um keine falsche Sicherheit"
echo "vorzutaeuschen)."
+92
View File
@@ -0,0 +1,92 @@
#!/usr/bin/env bash
# Rollout-Vorbereitung fuer Host 131 (Vorstufe zur Produktion): Build-Pruefung
# + Env-Datei-Ergaenzung. Ruft bewusst KEIN systemctl start/restart/stop auf
# — das ist der letzte, manuelle Schritt (siehe ROLLOUT-131-VORBEREITUNG.md).
#
# Setzt voraus, dass der Code bereits auf 131 aktuell ist (Code-Sync vorher
# von der Entwicklungsmaschine aus, NICHT von diesem Skript):
# rsync -az --delete --exclude='.git' code/ root@192.168.1.131:/root/nexarch-code/
#
# Aufruf (als root, auf Host 131): ./deploy/rollout-131-sync.sh
#
# Idempotent: mehrfacher Aufruf ist sicher. Bestehende Env-Variablen werden
# NIE ueberschrieben, nur fehlende ergaenzt. App-interne Secrets (die zu
# keinem anderen Dienst passen muessen) werden dabei direkt mit einem
# zufaelligen Wert befuellt; alles was einen konkreten, extern bekannten Wert
# braucht (URLs, Tokens die zu einem anderen Dienst passen muessen), bleibt
# als "# TODO"-Platzhalter stehen.
set -euo pipefail
REPO_DIR="${NEXARCH_ROLLOUT_REPO_DIR:-/root/nexarch-code}"
ENV_DIR=/etc/nexarch
if [ "$(id -u)" -ne 0 ]; then
echo "Bitte als root ausfuehren." >&2
exit 1
fi
echo "== 1. Build-Pruefung je Modul =="
for mod in . dms archive mail ai workflow connect; do
if [ -f "$REPO_DIR/$mod/go.mod" ]; then
echo "-- $mod --"
(cd "$REPO_DIR/$mod" && go build ./... && go vet ./...)
fi
done
# Fehlende Env-Variable ergaenzen, ohne eine bestehende Zeile anzufassen.
# $1 = Env-Datei, $2 = Variablenname, $3 = Platzhalterkommentar
ensure_var() {
local file="$1" name="$2" hint="$3"
mkdir -p "$(dirname "$file")"
touch "$file"
if ! grep -q "^${name}=" "$file"; then
echo "${name}= # TODO ${hint}" >> "$file"
echo " ergaenzt (Platzhalter): ${name} in ${file}"
fi
}
# Wie ensure_var, aber befuellt mit einem frisch generierten Zufallswert
# statt eines Platzhalters -- nur fuer Secrets, die ausschliesslich intern
# von diesem einen Dienst selbst verwendet werden (kein Abgleich mit einem
# anderen Dienst noetig). Der Wert wird nie ausgegeben oder in eine Variable
# geschrieben, die spaeter gedruckt werden koennte.
ensure_var_autogen() {
local file="$1" name="$2" purpose="$3"
mkdir -p "$(dirname "$file")"
touch "$file"
if ! grep -q "^${name}=" "$file"; then
printf '%s=' "$name" >> "$file"
openssl rand -hex 32 >> "$file"
echo " ergaenzt (neu generiertes Secret): ${name} in ${file} (${purpose})"
fi
}
echo "== 2. Env-Datei-Ergaenzung (nur fehlende Variablen, keine Ueberschreibung) =="
echo "-- connect-app.env (neu, Connect API-02) --"
ensure_var "$ENV_DIR/connect-app.env" NEXARCH_CONNECT_APP_LISTEN_ADDR "z.B. 127.0.0.1:9500"
ensure_var "$ENV_DIR/connect-app.env" NEXARCH_CONNECT_APP_TENANT_DSN "Postgres-DSN fuer den Connect-Mandanten"
echo "-- dms-app.env (Ergaenzungen aus dieser Session gehaerteter Konfiguration) --"
# Pflicht zum Start ueberhaupt (TENANT_DSN/TENANT_SLUG waren auf 131 bei der
# Bestandsaufnahme bereits gesetzt, hier nur zur Vollstaendigkeit abgesichert):
ensure_var "$ENV_DIR/dms-app.env" NEXARCH_DMS_APP_CORE_JWKS_URL "JWKS-Endpunkt von account-api: http://127.0.0.1:8099/auth/module-jwks -- ACHTUNG: auf 131 lief account-api zum Zeitpunkt dieser Vorbereitung noch auf einem Stand VOR F-07 (Route antwortet 404); nach dem Rollout-Sync von account-api selbst (Core-Modul, Teil dieses Skripts) UND einem Neustart von nexarch-account-api diesen Endpunkt erneut pruefen"
ensure_var "$ENV_DIR/dms-app.env" NEXARCH_DMS_APP_STAGING_DIR "Verzeichnis fuer Upload-Staging, z.B. /var/lib/nexarch-dms/staging (Pflicht bei gesetztem DSN)"
# App-interne Secrets, sicher automatisch generierbar:
ensure_var_autogen "$ENV_DIR/dms-app.env" NEXARCH_DMS_APP_DOWNLOAD_SIGNING_SECRET "Schluessel fuer Download-URLs, rein intern, kein Abgleich mit anderem Dienst noetig"
# Braucht einen zu einem anderen, bereits laufenden Dienst passenden Wert --
# NICHT automatisch generieren, sonst stiller Mismatch statt Fehlermeldung:
ensure_var "$ENV_DIR/dms-app.env" NEXARCH_DMS_APP_CORE_BASE_URL "Core-Registry-Basis-URL fuer INT-14 Tenant-Bestaetigung: http://127.0.0.1:8080 (nexarch-core NEXARCH_LISTEN_ADDR auf 131)"
ensure_var "$ENV_DIR/dms-app.env" NEXARCH_DMS_APP_CORE_SERVICE_TOKEN "Service-Token fuer Core-Aufrufe -- muss identisch zu einem auf Core-Seite hinterlegten Token sein (Secret, nicht selbst generierbar ohne Core-seitige Gegenstelle)"
ensure_var "$ENV_DIR/dms-app.env" NEXARCH_DMS_APP_POLICY_URL "Core-Policy-Endpunkt fuer RBAC-06: http://127.0.0.1:8093 (policy-api auf 131) -- leer = Rechtepruefung bleibt aus (Fallback, kein Fehler)"
ensure_var "$ENV_DIR/dms-app.env" NEXARCH_DMS_APP_POLICY_SERVICE_TOKEN "Service-Token fuer den Policy-Endpunkt -- muss zu NEXARCH_POLICY_SERVICE_TOKEN in policy-api.env auf 131 passen (Secret, dort abschreiben, nicht neu generieren)"
ensure_var "$ENV_DIR/dms-app.env" NEXARCH_DMS_APP_KEK_ENDPOINT_URL "KEK-Bezugsdienst-URL: http://127.0.0.1:8102 (kek-api auf 131) -- laut bestehender Doku auf 131 derzeit nicht gesetzt, ohne KEK-Bezug kein Textkopie-Verschluesselung (FDN-22)"
ensure_var "$ENV_DIR/dms-app.env" NEXARCH_DMS_APP_KEK_CLIENT_ID "Client-ID fuer den KEK-Bezug -- muss zu kek-api passen"
ensure_var "$ENV_DIR/dms-app.env" NEXARCH_DMS_APP_KEK_CLIENT_SECRET "Client-Secret fuer den KEK-Bezug -- muss zu kek-api passen (Secret)"
echo "Hinweis: AI und Workflow haben noch KEINEN eigenen cmd/-Dienst (Library-only)."
echo "Keine Env-Datei/kein systemd-Unit fuer diese beiden Module noetig, solange das so bleibt."
echo "== Fertig. Naechste Schritte siehe docs/ROLLOUT-131-VORBEREITUNG.md (manuell). =="
@@ -0,0 +1,23 @@
[Unit]
Description=NEXARCH Connect - connect-app (API-02)
After=network.target postgresql.service
Wants=postgresql.service
[Service]
Type=simple
User=nexarch
Group=nexarch
EnvironmentFile=/etc/nexarch/connect-app.env
ExecStart=__INSTALL_DIR__/bin/connect-app
Restart=on-failure
RestartSec=3
WorkingDirectory=__INSTALL_DIR__
# QA-15 F-13/OPS-08: reiner Netzwerkdienst (HTTP + Postgres-DSN aus
# EnvironmentFile), keine eigene Schreibarbeit im Dateisystem.
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,26 @@
[Unit]
Description=NEXARCH DMS - dms-app
After=network.target postgresql.service
Wants=postgresql.service
[Service]
Type=simple
User=nexarch
Group=nexarch
EnvironmentFile=/etc/nexarch/dms-app.env
ExecStart=__INSTALL_DIR__/bin/dms-app
Restart=on-failure
RestartSec=3
WorkingDirectory=__INSTALL_DIR__
# QA-15 F-13/OPS-08: Storage-/Staging-Verzeichnisse liegen ausserhalb von
# ProtectSystem=strict (siehe NEXARCH_DMS_APP_STORAGE_DIR/_STAGING_DIR in
# dms-app.env) -- ReadWritePaths traegt beide ein, Pfade muessen zu den
# Werten in der EnvironmentFile passen.
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=__STORAGE_DIR__ __STAGING_DIR__
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,24 @@
[Unit]
Description=NEXARCH DMS - dms-worker
After=network.target postgresql.service
Wants=postgresql.service
[Service]
Type=simple
User=nexarch
Group=nexarch
EnvironmentFile=/etc/nexarch/dms-worker.env
ExecStart=__INSTALL_DIR__/bin/dms-worker
Restart=on-failure
RestartSec=3
WorkingDirectory=__INSTALL_DIR__
# QA-15 F-13/OPS-08: siehe nexarch-dms-app.service.tmpl -- Storage-Pfad
# muss zu NEXARCH_DMS_WORKER_STORAGE_DIR in dms-worker.env passen.
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=__STORAGE_DIR__
[Install]
WantedBy=multi-user.target
+99
View File
@@ -0,0 +1,99 @@
# Rollout-Vorbereitung Host 131 (Vorstufe zur Produktion)
Stand: main Head `54589a4e`. Dieses Dokument bereitet den Rollout vor, führt ihn aber NICHT aus — kein Dienst wird gestartet oder neu gestartet. Das ist ausdrücklich der letzte, manuelle Schritt des Nutzers (Sicherheitsfilter blockt automatisierte Production-Deploy-Aktionen kategorisch).
Installierbare Artefakte liegen im Repo, nicht nur als Text hier:
- `deploy/systemd/nexarch-connect-app.service.tmpl` (neu)
- `deploy/systemd/nexarch-dms-app.service.tmpl` (neu — gab es bisher gar nicht im Repo, da `dms-app` noch nie deployt wurde)
- `deploy/systemd/nexarch-dms-worker.service.tmpl` (neu, gleicher Grund)
- `deploy/rollout-131-sync.sh` (idempotent, kein `systemctl start/restart/stop`) — **bereits einmal real auf 131 ausgeführt** (2026-09-26), Ergebnis siehe Abschnitt 2/3
- `deploy/rollout-131-healthcheck.sh` (neu) — nach dem manuellen Dienststart auszuführen, prüft alle relevanten Ports per `curl`, startet selbst nichts
## 1. Was auf 131 aktuell läuft
Geprüft per `systemctl list-units` und Prozessliste (2026-09-25):
**Aktiv und laufend (unverändert lassen, sofern nicht unten als "Neustart nötig" markiert):**
- `nexarch-core`, `nexarch-account-api`, `nexarch-kek-api`, `nexarch-notify-api`, `nexarch-notifyprefs-api`, `nexarch-policy-api`, `nexarch-rbac-admin-api`, `nexarch-resync-api` (Core)
- `nexarch-archive-moduleadapter-api`, `nexarch-archive-retention-api`, `nexarch-archive-restoretest-metrics`, `nexarch-archive-scrub-metrics` (Archive)
- `nexarch-dms-kosit` (DMS KoSIT-Validator, Loopback-Sidecar, MET-07-Vorbedingung)
- Sechs Devserver: `nexarch-auditlog-devserver`, `nexarch-licadmin-devserver`, `nexarch-metrics-devserver`, `nexarch-secheaders-devserver`, `nexarch-statuspage-devserver`, `nexarch-tenantadmin-devserver`
- Sechs Web-Frontends (`next-server`-Prozesse): `nexarch-web-account`, `nexarch-web-audit-log`, `nexarch-web-lic-admin`, `nexarch-web-notifications`, `nexarch-web-rbac-admin`, `nexarch-web-status-page`, `nexarch-web-tenant-admin`
**Bereits fehlgeschlagen, unabhängig von diesem Rollout (nicht Teil dieses Auftrags, nur dokumentiert):**
- `nexarch-archive-backup-full`, `nexarch-archive-backup-incremental`, `nexarch-archive-objectbackup-rotate`, `nexarch-archive-reconcile`, `nexarch-archive-scrub` — Status `failed`. Ursache nicht untersucht (außerhalb des Auftrags), sollte vor dem eigentlichen Rollout separat geprüft werden.
**Nicht vorhanden auf 131 (bisher nirgends deployed):**
- `dms-app` selbst (nur der KoSIT-Sidecar läuft, nicht der eigentliche DMS-Dienst) — trotz `dms-app.env` vorhanden
- Mail (kein `mail-api`/`mail-rules-api`-Dienst, keine Env-Datei)
- AI, Workflow, Connect — komplett neu für 131
## 2. Build-Ergebnis (real ausgeführt, 2026-09-26)
`deploy/rollout-131-sync.sh` wurde tatsächlich auf 131 ausgeführt (Code vorher per `rsync -az --delete --exclude='.git'` synchronisiert). Ergebnis: **alle sieben Module bauen sauber** (`go build ./...` + `go vet ./...`, exit 0) — Core, `dms`, `archive`, `mail`, `ai`, `workflow`, `connect`. Kompilierfehler wären hier aufgefallen, es gab keine.
**Wichtig:** AI und Workflow haben (Stand main Head `54589a4e`) keinen eigenen `cmd/`-Dienst — reine Bibliotheks-Module. Für sie gibt es nichts zu installieren/starten. Kein Unit-Template dafür angelegt (wäre eine Attrappe für ein nicht existierendes Binary).
## 3. Neue Umgebungsvariablen je Dienst
### Connect (`connect-app`, neuer Dienst)
`/etc/nexarch/connect-app.env` wurde angelegt. **Verbleibende echte TODOs (2 von 2)** — beides Werte, die nur der Nutzer festlegen kann (Portwahl bzw. Ziel-Datenbank), nicht automatisch ableitbar:
| Variable | Status | Zweck |
|---|---|---|
| `NEXARCH_CONNECT_APP_LISTEN_ADDR` | TODO | Horch-Adresse, z. B. `127.0.0.1:9500` |
| `NEXARCH_CONNECT_APP_TENANT_DSN` | TODO | Postgres-DSN für den Connect-Mandanten |
### DMS (`dms-app`, noch nicht auf 131 installiert — dieser Rollout würde ihn erstmals aufsetzen)
`/etc/nexarch/dms-app.env` hatte 12 der ~86 in `dms/docs/BETRIEB-UMGEBUNGSVARIABLEN.md` dokumentierten Variablen gesetzt. Beim realen Lauf von `rollout-131-sync.sh` (2026-09-26) wurden die für den Start kritischen fehlenden Variablen ergänzt — **6 davon automatisch mit einem echten, für 131 zutreffenden Wert befüllt** (reine URLs/Pfade, keine Geheimnisse, oder lokal generierte Secrets, oder von einem anderen bereits laufenden Dienst auf 131 abgeschrieben ohne den Wert je auszugeben):
| Variable | Status | Wert/Herkunft |
|---|---|---|
| `NEXARCH_DMS_APP_CORE_JWKS_URL` | gesetzt | `http://127.0.0.1:8099/auth/module-jwks` — **Achtung:** account-api lief zum Zeitpunkt der Vorbereitung noch auf einem Stand vor F-07, Route antwortete 404. Der Code auf 131 wurde durch `rollout-131-sync.sh` bereits neu gebaut; ein `systemctl restart nexarch-account-api` (durch den Nutzer) sollte die Route freischalten — vor dem `dms-app`-Start mit `curl` erneut prüfen |
| `NEXARCH_DMS_APP_STAGING_DIR` | gesetzt | `/var/lib/nexarch-dms/staging` (angelegt) |
| `NEXARCH_DMS_APP_DOWNLOAD_SIGNING_SECRET` | gesetzt | lokal mit `openssl rand -hex 32` generiert (rein intern, kein Abgleich nötig) |
| `NEXARCH_DMS_APP_CORE_BASE_URL` | gesetzt | `http://127.0.0.1:8080` (nexarch-core auf 131) |
| `NEXARCH_DMS_APP_POLICY_URL` | gesetzt | `http://127.0.0.1:8093` (policy-api auf 131) |
| `NEXARCH_DMS_APP_KEK_ENDPOINT_URL` | gesetzt | `http://127.0.0.1:8102` (kek-api auf 131) |
| `NEXARCH_DMS_APP_POLICY_SERVICE_TOKEN` | gesetzt | vom bereits laufenden `policy-api.env` (`NEXARCH_POLICY_SERVICE_TOKEN`) 1:1 übernommen, Wert nie ausgegeben |
**Verbleibende echte TODOs (3):**
| Variable | Zweck |
|---|---|
| `NEXARCH_DMS_APP_CORE_SERVICE_TOKEN` | Tenant-Bestätigung gegen Core-Registry (INT-14) — braucht einen auf Core-Seite hinterlegten, passenden Wert; nicht ohne Core-seitige Gegenstelle generierbar |
| `NEXARCH_DMS_APP_KEK_CLIENT_ID` / `_CLIENT_SECRET` | KEK-Bezug — laut bestehender Doku auf 131 "derzeit nicht gesetzt"; braucht eine echte Registrierung bei `kek-api`, kann nicht geraten werden |
### AI, Workflow, Mail
Kein `cmd/`-Dienst (AI/Workflow) bzw. kein bisher deployter Dienst (Mail) — keine Env-Datei nötig für diesen Rollout-Schritt. Sobald AI/Workflow einen eigenen Dienst bekommen (kein Ticket dafür bisher vorhanden), braucht dieses Dokument eine Ergänzung.
## 4. Neustart-Bedarf bestehender Dienste
Kein bereits laufender Dienst MUSS für die reine Installation von Connect neu gestartet werden — Connect ist ein komplett neuer, unabhängiger Prozess. Ein Neustart von `nexarch-core`/`nexarch-policy-api`/etc. ist nur nötig, wenn deren EIGENE Env-Dateien geändert werden — das tut `rollout-131-sync.sh` nicht (nur `connect-app.env` und `dms-app.env` werden ergänzt, beide betreffen keinen aktuell laufenden Dienst).
## 5. Manuelle Schritte für den Nutzer (der eigentliche Rollout)
Schritte 1–2 wurden bereits real ausgeführt (siehe Abschnitt 2/3) und müssen nur wiederholt werden, falls sich main-Head seither geändert hat.
**Primärer Weg:** die restlichen Schritte (3–9 unten) sind jetzt in `deploy/rollout-131-apply.sh` automatisiert. Nachdem die 5 TODO-Werte eingetragen sind, genügt:
```
sudo ./deploy/rollout-131-apply.sh
```
Das Skript bricht kontrolliert ab, wenn ein TODO-Wert noch fehlt, wenn der Build fehlschlägt, oder wenn `account-api` nach dem Neustart `/auth/module-jwks` nicht innerhalb von 20s liefert — es macht in keinem dieser Fälle blind weiter. Es ruft `systemctl restart`/`enable --now` nur für die in diesem Rollout betroffenen Dienste auf (`nexarch-account-api`, `nexarch-connect-app`, `nexarch-dms-app`, `nexarch-dms-worker`), keine anderen. Am Ende führt es automatisch `rollout-131-healthcheck.sh` aus.
**Einzelschritte als Referenz/Fallback**, falls das Skript nicht genutzt werden soll oder ein Einzelschritt manuell wiederholt werden muss:
1. ~~Code synchronisieren~~ (erledigt, `rsync` von der Entwicklungsmaschine gegen `main` Head `54589a4e`)
2. ~~`./deploy/rollout-131-sync.sh` ausführen~~ (erledigt, alle 7 Module bauen sauber, Env-Dateien ergänzt)
3. Die 5 verbleibenden echten `# TODO`-Werte von Hand eintragen (Abschnitt 3 nennt sie einzeln): `NEXARCH_CONNECT_APP_LISTEN_ADDR`, `NEXARCH_CONNECT_APP_TENANT_DSN`, `NEXARCH_DMS_APP_CORE_SERVICE_TOKEN`, `NEXARCH_DMS_APP_KEK_CLIENT_ID`, `NEXARCH_DMS_APP_KEK_CLIENT_SECRET`
4. Binaries an ihren Zielort kopieren (Muster wie bei bestehenden Diensten, z. B. `/opt/nexarch-connect/bin/connect-app`, `/opt/nexarch-dms/bin/dms-app`, `/opt/nexarch-dms/bin/dms-worker`) und die drei neuen `.service.tmpl`-Dateien (`nexarch-connect-app`, `nexarch-dms-app`, `nexarch-dms-worker`) nach `/etc/systemd/system/` kopieren, dabei `__INSTALL_DIR__` (und bei DMS zusätzlich `__STORAGE_DIR__`/`__STAGING_DIR__`) durch die echten Pfade ersetzen
5. Für `dms-worker` fehlt noch eine eigene `/etc/nexarch/dms-worker.env` (siehe `dms/docs/BETRIEB-UMGEBUNGSVARIABLEN.md`, Abschnitt "dms-worker") — bisher nicht angelegt, da dieser Rollout sich auf `dms-app` konzentriert hat; ohne sie verarbeitet kein Worker die Jobqueue
6. `systemctl daemon-reload`
7. `nexarch-account-api` neu starten (Code wurde bereits neu gebaut, Route `/auth/module-jwks` fehlt im aktuell laufenden Prozess noch — siehe Abschnitt 3), danach mit `curl http://127.0.0.1:8099/auth/module-jwks` verifizieren
8. `systemctl enable --now nexarch-connect-app nexarch-dms-app` (und `nexarch-dms-worker`, sobald Schritt 5 erledigt ist)
9. `./deploy/rollout-131-healthcheck.sh` ausführen (neu, liest nur, startet nichts) — zeigt kompakt welcher Dienst erreichbar ist
10. Bei Bedarf weitere, bereits laufende Dienste neu starten, falls deren eigene Env-Dateien geändert wurden (aktuell: nur `nexarch-account-api`, siehe Schritt 7 — kein anderer Dienst betroffen)
Die fünf bereits fehlgeschlagenen Backup-/Scrub-/Reconcile-Dienste (Abschnitt 1) sind unabhängig von diesem Rollout und sollten separat untersucht werden.