#!/usr/bin/env bash # NEXARCH Core – Installer/Deployer fuer eine Debian/systemd-Zielumgebung. # # Baut alle Core-Binaries (cmd/core + die *-devserver), legt Postgres-Rolle # und Registry-Datenbank an (falls nicht vorhanden), wendet die # Registry-Migrationen an, generiert Secrets (falls nicht vorhanden) und # installiert+startet jeden Dienst als eigenen systemd-Service. # # Idempotent: mehrfacher Aufruf ist sicher — vorhandene Rolle/DB/Secrets # werden nicht ueberschrieben, Migrationen nur angewendet, wenn die # Registry-DB noch leer ist (siehe Abschnitt "Migrationen" unten). # # Aufruf (als root): ./deploy/install.sh # # Ueberschreibbar per Umgebungsvariable: # NEXARCH_INSTALL_DIR (Default: /opt/nexarch-core) # NEXARCH_PG_ROLE (Default: nexarch_core) # NEXARCH_PG_REGISTRY_DB (Default: nexarch_registry) # NEXARCH_BRANCH (Default: aktueller Branch dieses Checkouts) set -euo pipefail INSTALL_DIR="${NEXARCH_INSTALL_DIR:-/opt/nexarch-core}" PG_ROLE="${NEXARCH_PG_ROLE:-nexarch_core}" PG_DB="${NEXARCH_PG_REGISTRY_DB:-nexarch_registry}" ENV_FILE=/etc/nexarch/core.env SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" if [ "$(id -u)" -ne 0 ]; then echo "Bitte als root ausfuehren (legt Systembenutzer, systemd-Units und Postgres-Rolle an)." >&2 exit 1 fi echo "== 1. Systembenutzer ==" if ! id nexarch >/dev/null 2>&1; then useradd --system --no-create-home --shell /usr/sbin/nologin nexarch echo "Benutzer 'nexarch' angelegt." else echo "Benutzer 'nexarch' existiert bereits." fi echo "== 2. Postgres-Rolle und Registry-Datenbank ==" if ! sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname = '${PG_ROLE}'" | grep -q 1; then PG_PASSWORD="$(openssl rand -hex 24)" sudo -u postgres psql -v ON_ERROR_STOP=1 -c "CREATE ROLE ${PG_ROLE} WITH LOGIN PASSWORD '${PG_PASSWORD}';" echo "Rolle '${PG_ROLE}' angelegt." else echo "Rolle '${PG_ROLE}' existiert bereits — Passwort wird NICHT neu gesetzt (siehe ${ENV_FILE} fuer das vorhandene)." PG_PASSWORD="" fi if ! sudo -u postgres psql -tAc "SELECT 1 FROM pg_database WHERE datname = '${PG_DB}'" | grep -q 1; then sudo -u postgres psql -v ON_ERROR_STOP=1 -c "CREATE DATABASE ${PG_DB} OWNER ${PG_ROLE};" echo "Datenbank '${PG_DB}' angelegt." else echo "Datenbank '${PG_DB}' existiert bereits." fi # Fuer Tenant-Provisioning (CREATE DATABASE pro Mandant, Modell C) braucht # die Rolle CREATEDB-Recht auf der physischen Postgres-Instanz. sudo -u postgres psql -v ON_ERROR_STOP=1 -c "ALTER ROLE ${PG_ROLE} WITH CREATEDB;" >/dev/null echo "== 3. Secrets/Konfiguration ==" mkdir -p /etc/nexarch if [ ! -f "$ENV_FILE" ]; then if [ -z "${PG_PASSWORD}" ]; then echo "FEHLER: Rolle existierte bereits, aber ${ENV_FILE} fehlt — Passwort kann nicht rekonstruiert werden." >&2 echo "Entweder ${ENV_FILE} von Hand mit dem bekannten Passwort anlegen, oder die Rolle droppen und erneut installieren." >&2 exit 1 fi AUDIT_ADMIN_TOKEN="$(openssl rand -hex 32)" # Ed25519-Schluesselpaar fuer die Lizenzsignatur (LIC-01/LIC-04): # licadmin-devserver prueft Lizenzen nur mit dem OEFFENTLICHEN Schluessel, # der private Schluessel wird NICHT deployt, sondern separat fuer das # (noch zu bauende) offline Lizenz-Ausstellungswerkzeug aufbewahrt. KEYPAIR_DIR=/etc/nexarch/license-signing mkdir -p "$KEYPAIR_DIR" chmod 700 "$KEYPAIR_DIR" if [ ! -f "$KEYPAIR_DIR/private.b64" ]; then go run "$SCRIPT_DIR/gen-ed25519-keypair.go" > "$KEYPAIR_DIR/keypair.txt" grep '^PRIVATE=' "$KEYPAIR_DIR/keypair.txt" | cut -d= -f2 > "$KEYPAIR_DIR/private.b64" grep '^PUBLIC=' "$KEYPAIR_DIR/keypair.txt" | cut -d= -f2 > "$KEYPAIR_DIR/public.b64" chmod 600 "$KEYPAIR_DIR"/*.b64 "$KEYPAIR_DIR/keypair.txt" rm -f "$KEYPAIR_DIR/keypair.txt" fi LICENSE_PUBLIC_KEY="$(cat "$KEYPAIR_DIR/public.b64")" cat > "$ENV_FILE" </dev/null echo "angewendet: $(basename "$f")" done fi echo "== 6. systemd-Units ==" for tmpl in "$SCRIPT_DIR"/systemd/*.service.tmpl; do name="$(basename "$tmpl" .service.tmpl)" sed "s#__INSTALL_DIR__#${INSTALL_DIR}#g" "$tmpl" > "/etc/systemd/system/${name}.service" done systemctl daemon-reload for tmpl in "$SCRIPT_DIR"/systemd/*.service.tmpl; do name="$(basename "$tmpl" .service.tmpl)" systemctl enable --now "${name}.service" done echo "== Fertig ==" echo "Status pruefen mit: systemctl status 'nexarch-*'" echo "Health-Checks:" echo " curl -s http://localhost:8080/healthz" echo " curl -s http://localhost:8081/healthz # licadmin" echo " curl -s http://localhost:8082/healthz # tenantadmin" echo " curl -s http://localhost:8083/healthz # auditlog" echo " curl -s http://localhost:8084/healthz # statuspage" echo " curl -s http://localhost:8085/healthz # metrics" echo " curl -s http://localhost:8086/unprotected # secheaders (kein /healthz)"