feat(authentik): Installer — Docker, offizielles Compose, headless Bootstrap-Credentials + API-Token, Blueprints-Mount
This commit is contained in:
@@ -0,0 +1,139 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Authentik installer — runs inside the LXC, called by ct/authentik.sh
|
||||||
|
#
|
||||||
|
# Installs Docker + the official Authentik docker-compose stack, headless:
|
||||||
|
# - secrets generated on-host (PG_PASS, AUTHENTIK_SECRET_KEY) — never printed
|
||||||
|
# - bootstrap admin (akadmin) password + API token generated so that an
|
||||||
|
# agent can configure everything via API/blueprints without the UI
|
||||||
|
# - blueprints dir mounted via docker-compose.override.yml
|
||||||
|
# - optional dedicated SSH key for agent access appended to authorized_keys
|
||||||
|
#
|
||||||
|
# Idempotent: re-running keeps existing secrets/.env and only updates images.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
LIB_URL="${LIB_URL:-https://gitea.luki-net.org/luki-net/proxmox-scripts/raw/branch/main/lib}"
|
||||||
|
source <(curl -fsSL "$LIB_URL/install.func")
|
||||||
|
|
||||||
|
[[ "$EUID" -eq 0 ]] || { msg_err "Must run as root"; exit 1; }
|
||||||
|
|
||||||
|
CONF="/root/authentik.deploy.env"
|
||||||
|
[[ -f "$CONF" ]] || { msg_err "$CONF not found (host bootstrap incomplete)"; exit 1; }
|
||||||
|
set -a; . "$CONF"; set +a
|
||||||
|
: "${AUTH_DOMAIN:?missing AUTH_DOMAIN}"
|
||||||
|
APP_PORT="${APP_PORT:-9000}"
|
||||||
|
|
||||||
|
AK_DIR="/opt/authentik"
|
||||||
|
ENV_FILE="$AK_DIR/.env"
|
||||||
|
CRED_FILE="/root/authentik.credentials"
|
||||||
|
|
||||||
|
# ── base packages + Docker ────────────────────────────────────────────────────
|
||||||
|
setup_base_apt ca-certificates curl
|
||||||
|
if ! command -v docker >/dev/null 2>&1; then
|
||||||
|
msg_info "Installing Docker (get.docker.com)..."
|
||||||
|
curl -fsSL https://get.docker.com | sh >/dev/null
|
||||||
|
msg_ok "Docker $(docker --version | awk '{print $3}' | tr -d ',')"
|
||||||
|
else
|
||||||
|
msg_warn "Docker already present, skipping"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── optional: dedicated agent SSH key ────────────────────────────────────────
|
||||||
|
if [[ -n "${CLAUDE_SSH_PUBKEY:-}" ]]; then
|
||||||
|
mkdir -p /root/.ssh && chmod 700 /root/.ssh
|
||||||
|
touch /root/.ssh/authorized_keys && chmod 600 /root/.ssh/authorized_keys
|
||||||
|
if ! grep -qF "$CLAUDE_SSH_PUBKEY" /root/.ssh/authorized_keys; then
|
||||||
|
echo "$CLAUDE_SSH_PUBKEY" >> /root/.ssh/authorized_keys
|
||||||
|
msg_ok "Agent SSH key installed"
|
||||||
|
else
|
||||||
|
msg_warn "Agent SSH key already present"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── compose stack ─────────────────────────────────────────────────────────────
|
||||||
|
mkdir -p "$AK_DIR/blueprints" "$AK_DIR/media" "$AK_DIR/custom-templates" "$AK_DIR/certs"
|
||||||
|
cd "$AK_DIR"
|
||||||
|
|
||||||
|
if [[ ! -f docker-compose.yml ]]; then
|
||||||
|
msg_info "Fetching official Authentik compose file..."
|
||||||
|
curl -fsSL -o docker-compose.yml https://goauthentik.io/docker-compose.yml
|
||||||
|
msg_ok "docker-compose.yml fetched"
|
||||||
|
else
|
||||||
|
msg_warn "docker-compose.yml exists, keeping (idempotent)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Override: Blueprints in server+worker mounten, Port-Bind nur auf LXC-Netz nötig?
|
||||||
|
# Authentik bleibt im LAN hinter NPMplus — Standard-Bind reicht; Blueprints-Mount ergänzen.
|
||||||
|
if [[ ! -f docker-compose.override.yml ]]; then
|
||||||
|
cat > docker-compose.override.yml <<EOF
|
||||||
|
services:
|
||||||
|
server:
|
||||||
|
volumes:
|
||||||
|
- ./blueprints:/blueprints/custom:ro
|
||||||
|
worker:
|
||||||
|
volumes:
|
||||||
|
- ./blueprints:/blueprints/custom:ro
|
||||||
|
EOF
|
||||||
|
msg_ok "compose override (custom blueprints mount) written"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── secrets / env (idempotent: vorhandene .env bleibt) ────────────────────────
|
||||||
|
if [[ ! -f "$ENV_FILE" ]]; then
|
||||||
|
msg_info "Generating secrets (.env)..."
|
||||||
|
PG_PASS="$(openssl rand -base64 36 | tr -d '\n=/+' | cut -c1-32)"
|
||||||
|
AK_SECRET="$(openssl rand -base64 60 | tr -d '\n')"
|
||||||
|
AK_BOOT_PW="$(openssl rand -base64 24 | tr -d '\n=/+' | cut -c1-20)"
|
||||||
|
AK_BOOT_TOKEN="$(openssl rand -hex 32)"
|
||||||
|
cat >"$ENV_FILE" <<EOF
|
||||||
|
PG_PASS=$PG_PASS
|
||||||
|
AUTHENTIK_SECRET_KEY=$AK_SECRET
|
||||||
|
AUTHENTIK_BOOTSTRAP_PASSWORD=$AK_BOOT_PW
|
||||||
|
AUTHENTIK_BOOTSTRAP_TOKEN=$AK_BOOT_TOKEN
|
||||||
|
AUTHENTIK_BOOTSTRAP_EMAIL=admin@$AUTH_DOMAIN
|
||||||
|
COMPOSE_PORT_HTTP=$APP_PORT
|
||||||
|
${AUTHENTIK_TAG:+AUTHENTIK_TAG=$AUTHENTIK_TAG}
|
||||||
|
# E-Mail-Versand bewusst unkonfiguriert (Familien-Setup; bei Bedarf nachziehen):
|
||||||
|
# AUTHENTIK_EMAIL__HOST=...
|
||||||
|
EOF
|
||||||
|
chmod 600 "$ENV_FILE"
|
||||||
|
|
||||||
|
cat >"$CRED_FILE" <<EOF
|
||||||
|
Authentik — zentraler Homelab-IdP (nexus ADR-0003)
|
||||||
|
|
||||||
|
URL (LAN): http://$(hostname -I | awk '{print $1}'):$APP_PORT
|
||||||
|
URL (final): https://$AUTH_DOMAIN (nach NPMplus-Eintrag; Domain ist DAUERHAFT)
|
||||||
|
|
||||||
|
Bootstrap-Admin: akadmin
|
||||||
|
Passwort: $AK_BOOT_PW
|
||||||
|
API-Token: $AK_BOOT_TOKEN
|
||||||
|
-> für Agent-Automation (Blueprints/OIDC via API). Nach Abschluss der
|
||||||
|
Einrichtung rotieren oder widerrufen; menschlicher Admin nutzt eigenen
|
||||||
|
Account mit Passkey, NICHT akadmin.
|
||||||
|
|
||||||
|
Blueprints: $AK_DIR/blueprints (Quelle: nexus-hub infra/authentik/)
|
||||||
|
Stack: cd $AK_DIR && docker compose ps|logs|pull
|
||||||
|
EOF
|
||||||
|
chmod 600 "$CRED_FILE"
|
||||||
|
msg_ok "Secrets + credentials written ($CRED_FILE)"
|
||||||
|
else
|
||||||
|
msg_warn ".env exists — keeping existing secrets (idempotent)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ── start ─────────────────────────────────────────────────────────────────────
|
||||||
|
msg_info "Pulling images & starting Authentik (first start takes 1–2 min)..."
|
||||||
|
docker compose pull -q
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
|
# Warten bis der Server antwortet (Healthcheck)
|
||||||
|
for _ in $(seq 1 60); do
|
||||||
|
if curl -fsS "http://127.0.0.1:$APP_PORT/-/health/live/" >/dev/null 2>&1; then
|
||||||
|
msg_ok "Authentik is up (http://127.0.0.1:$APP_PORT)"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
curl -fsS "http://127.0.0.1:$APP_PORT/-/health/live/" >/dev/null 2>&1 || \
|
||||||
|
msg_warn "Authentik antwortet noch nicht — 'docker compose logs -f' prüfen (Migrationslauf kann dauern)"
|
||||||
|
|
||||||
|
shred -u "$CONF" 2>/dev/null || rm -f "$CONF"
|
||||||
|
apt_cleanup
|
||||||
|
msg_ok "authentik installation finished"
|
||||||
Reference in New Issue
Block a user