#!/usr/bin/env bash
# =============================================================================
# ansipa-proxmox-lxc.sh — generate a pre-configured ansipa Proxmox LXC container
#
# Produces everything needed to stand up the FULL ansipa stack (FreeIPA +
# CheckMK + Keycloak + PostgreSQL + nginx gateway) inside a single Proxmox LXC
# container, using the tested docker-compose deployment run inside the CT
# ("Docker-in-LXC"). This is the whole management plane in one container, unlike
# freeipa-image.sh's proxmox-lxc target which exports a FreeIPA-only rootfs.
#
# Why Docker-in-LXC instead of native install:
#   FreeIPA + CheckMK + Keycloak are already packaged and wired together as a
#   compose stack that this repo tests end-to-end. Running that stack inside a
#   privileged, nesting-enabled LXC reuses all of it verbatim and keeps the
#   Proxmox container reproducible.
#
# OUTPUT (written to an output dir, default ~/ansipa-lxc-out):
#   pct-create-<vmid>.sh   runnable pct create command (run on the Proxmox host)
#   ansipa-<vmid>.conf     LXC options to append to /etc/pve/lxc/<vmid>.conf
#   ansipa-provision.sh    first-boot provisioner (installs Docker + brings the
#                          stack up); copied into the CT and run once
#   .env                   filled-in ansipa stack environment (secrets!)
#   DEPLOY-<vmid>.md       step-by-step deployment guide
#
# Requirements on the workstation running THIS script: bash, openssl (for
# password generation). The Proxmox host needs a Debian 12 CT template.
# =============================================================================

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DOTFILES_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
IMAGE_SRC="$DOTFILES_DIR/setup/modules/FreeipaAnsible/image"

RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'
BLUE='\033[0;34m'; CYAN='\033[0;36m'; MAGENTA='\033[0;35m'; NC='\033[0m'
log()     { echo -e "${GREEN}[+]${NC} $*"; }
warn()    { echo -e "${YELLOW}[!]${NC} $*"; }
error()   { echo -e "${RED}[✗]${NC} $*" >&2; }
info()    { echo -e "${CYAN}[i]${NC} $*"; }
section() { echo -e "\n${BLUE}━━━ $* ━━━${NC}"; }
ask()     { printf "${MAGENTA}[?]${NC} %s " "$*"; }

[[ $EUID -eq 0 ]] && { error "Run as your normal user (not root)."; exit 1; }

gen_pw() { openssl rand -base64 18 2>/dev/null | tr -d '/+=' | cut -c1-20; }

# ─── Gather configuration ─────────────────────────────────────────────────────
section "ansipa Proxmox LXC generator"
info "Generates a pre-configured full-stack ansipa container for Proxmox."
echo

ask "IPA domain (e.g. corp.example.com):"; read -r IPA_DOMAIN
[[ -z "$IPA_DOMAIN" ]] && { error "IPA domain is required."; exit 1; }
ask "IPA server FQDN [ipa.$IPA_DOMAIN]:"; read -r I; IPA_HOSTNAME="${I:-ipa.$IPA_DOMAIN}"
ask "Kerberos realm [${IPA_DOMAIN^^}]:"; read -r I; IPA_REALM="${I:-${IPA_DOMAIN^^}}"

ask "Proxmox VMID [910]:"; read -r I; VMID="${I:-910}"
ask "CT hostname [ansipa]:"; read -r I; CT_HOSTNAME="${I:-ansipa}"
ask "Proxmox storage [local-lvm]:"; read -r I; PVE_STORAGE="${I:-local-lvm}"
ask "Template storage [local]:"; read -r I; TPL_STORAGE="${I:-local}"
ask "Debian CT template [debian-12-standard_12.7-1_amd64.tar.zst]:"; read -r I
CT_TEMPLATE="${I:-debian-12-standard_12.7-1_amd64.tar.zst}"
# FreeIPA alone wants ~2 GB; the full stack (CheckMK/Keycloak/Postgres) needs headroom.
ask "RAM MB [6144]:"; read -r I; CT_RAM="${I:-6144}"
ask "Cores [4]:"; read -r I; CT_CORES="${I:-4}"
ask "Disk GB [20]:"; read -r I; CT_DISK="${I:-20}"
ask "Bridge [vmbr0]:"; read -r I; CT_BRIDGE="${I:-vmbr0}"
ask "Static IP CIDR or 'dhcp' [dhcp]:"; read -r I; CT_IP="${I:-dhcp}"
ask "Advertised CheckMK URL for clients (e.g. http://ansipa.$IPA_DOMAIN:8090) [blank=set later]:"
read -r CMK_ADVERTISED_URL

OUT_DIR="${1:-$HOME/ansipa-lxc-out}"
mkdir -p "$OUT_DIR"

# ─── Generate secrets ─────────────────────────────────────────────────────────
section "Generating secrets"
IPA_ADMIN_PASSWORD=$(gen_pw); IPA_DM_PASSWORD=$(gen_pw)
CMK_ADMIN_PASSWORD=$(gen_pw); KC_ADMIN_PASSWORD=$(gen_pw); KC_DB_PASSWORD=$(gen_pw)
LUKS_KEY_UPLOAD_PASSWORD=$(gen_pw)
log "Generated admin/service passwords (saved in $OUT_DIR/.env — keep it safe)."

# ─── .env for the ansipa stack ────────────────────────────────────────────────
cat > "$OUT_DIR/.env" <<EOF
# ansipa stack environment — generated by ansipa-proxmox-lxc.sh
IPA_HOSTNAME=$IPA_HOSTNAME
IPA_DOMAIN=$IPA_DOMAIN
IPA_REALM=$IPA_REALM
IPA_ADMIN_PASSWORD=$IPA_ADMIN_PASSWORD
IPA_DM_PASSWORD=$IPA_DM_PASSWORD
IPA_SETUP_DNS=false
IPA_SETUP_KRA=false

LUKS_KEY_UPLOAD_PASSWORD=$LUKS_KEY_UPLOAD_PASSWORD

CMK_ADMIN_PASSWORD=$CMK_ADMIN_PASSWORD
CMK_SITE_ID=cmk
CMK_ADVERTISED_URL=$CMK_ADVERTISED_URL

KC_HOSTNAME=${IPA_HOSTNAME/ipa./sso.}
KC_ADMIN=admin
KC_ADMIN_PASSWORD=$KC_ADMIN_PASSWORD
KC_DB_PASSWORD=$KC_DB_PASSWORD

ANSIPA_HTTP_PORT=8088
EOF
chmod 600 "$OUT_DIR/.env"

# ─── pct create script ────────────────────────────────────────────────────────
# Privileged + nesting + keyctl + fuse: FreeIPA runs systemd and Docker needs
# nesting/overlay; keyctl is required by Kerberos/SSSD keyrings inside the CT.
NET_LINE="name=eth0,bridge=$CT_BRIDGE,ip=dhcp"
[[ "$CT_IP" != "dhcp" ]] && NET_LINE="name=eth0,bridge=$CT_BRIDGE,ip=$CT_IP"

cat > "$OUT_DIR/pct-create-$VMID.sh" <<EOF
#!/usr/bin/env bash
# Run on the Proxmox host. Creates the ansipa LXC container.
set -euo pipefail

pct create $VMID $TPL_STORAGE:vztmpl/$CT_TEMPLATE \\
  --hostname $CT_HOSTNAME \\
  --cores $CT_CORES \\
  --memory $CT_RAM \\
  --swap 2048 \\
  --rootfs $PVE_STORAGE:$CT_DISK \\
  --net0 $NET_LINE \\
  --features nesting=1,keyctl=1,fuse=1 \\
  --unprivileged 0 \\
  --onboot 1 \\
  --start 0

echo "Created CT $VMID. Now append the extra options and start it:"
echo "  cat ansipa-$VMID.conf >> /etc/pve/lxc/$VMID.conf"
echo "  pct start $VMID"
echo "  pct push $VMID ansipa-provision.sh /root/ansipa-provision.sh"
echo "  pct push $VMID .env /root/.env"
echo "  pct exec $VMID -- bash /root/ansipa-provision.sh"
EOF
chmod +x "$OUT_DIR/pct-create-$VMID.sh"

# ─── LXC config extras ────────────────────────────────────────────────────────
# Docker overlay2 + FreeIPA need these cgroup/device allowances in a CT.
cat > "$OUT_DIR/ansipa-$VMID.conf" <<EOF
# Append to /etc/pve/lxc/$VMID.conf — enables Docker + FreeIPA inside the CT.
lxc.apparmor.profile: unconfined
lxc.cgroup2.devices.allow: a
lxc.cap.drop:
lxc.mount.auto: proc:rw sys:rw
EOF

# ─── First-boot provisioner (runs INSIDE the container) ───────────────────────
cat > "$OUT_DIR/ansipa-provision.sh" <<'PROVEOF'
#!/usr/bin/env bash
# ansipa-provision.sh — runs once inside the LXC to bring up the ansipa stack.
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive

echo "[ansipa] Installing Docker + git..."
apt-get update -qq
apt-get install -y -qq ca-certificates curl git >/dev/null
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release; echo $VERSION_CODENAME) stable" \
    > /etc/apt/sources.list.d/docker.list
apt-get update -qq
apt-get install -y -qq docker-ce docker-ce-cli containerd.io docker-compose-plugin >/dev/null
systemctl enable --now docker

echo "[ansipa] Fetching the ansipa stack..."
git clone --depth 1 https://git.abdelbaki.eu/The_miro/Dotfiles.git /opt/ansipa-src 2>/dev/null \
    || { cd /opt/ansipa-src && git pull; }
STACK=/opt/ansipa
mkdir -p "$STACK"
cp -r /opt/ansipa-src/setup/modules/FreeipaAnsible/image/. "$STACK/"
cp /root/.env "$STACK/.env"

echo "[ansipa] Starting the full stack (this builds the FreeIPA image + first-boot ~10 min)..."
cd "$STACK"
# cgroup v2 hosts need run.sh (compose can't express --cgroupns host for FreeIPA).
if [ "$(stat -fc %T /sys/fs/cgroup 2>/dev/null)" = "cgroup2fs" ]; then
    bash ./run.sh all
else
    docker compose up -d
fi

echo "[ansipa] Stack starting. Watch first-boot with:"
echo "  docker logs -f freeipa"
echo "[ansipa] Once healthy, wire Keycloak↔FreeIPA LDAP:  cd $STACK && ./keycloak-configure.sh"
PROVEOF
chmod +x "$OUT_DIR/ansipa-provision.sh"

# ─── Deployment guide ─────────────────────────────────────────────────────────
cat > "$OUT_DIR/DEPLOY-$VMID.md" <<EOF
# ansipa Proxmox LXC — deployment ($CT_HOSTNAME, VMID $VMID)

Generated by \`ansipa-proxmox-lxc.sh\`. Runs the full ansipa stack
(FreeIPA + CheckMK + Keycloak + PostgreSQL + nginx) as Docker containers
inside a privileged, nesting-enabled Proxmox LXC.

## 1. Copy these files to the Proxmox host
\`\`\`
scp pct-create-$VMID.sh ansipa-$VMID.conf ansipa-provision.sh .env root@PROXMOX:/root/ansipa/
\`\`\`

## 2. Create and provision the container (on the Proxmox host)
\`\`\`
cd /root/ansipa
# Ensure the Debian template exists:  pveam update && pveam download $TPL_STORAGE $CT_TEMPLATE
bash pct-create-$VMID.sh
cat ansipa-$VMID.conf >> /etc/pve/lxc/$VMID.conf
pct start $VMID
pct push $VMID .env /root/.env
pct push $VMID ansipa-provision.sh /root/ansipa-provision.sh
pct exec $VMID -- bash /root/ansipa-provision.sh
\`\`\`

## 3. Access
- Portal / all UIs: \`http://<CT-IP>:8088/\` (put your reverse proxy in front — see docs/md/ansipa-setup.md)
- FreeIPA: \`/ipa/ui/\`  ·  CheckMK: \`/cmk/\`  ·  Keycloak: \`/auth/\`
- Admin passwords are in \`.env\` (IPA_ADMIN_PASSWORD, CMK_ADMIN_PASSWORD, KC_ADMIN_PASSWORD).

## Notes
- The CT is **privileged** with nesting/keyctl/fuse — required for FreeIPA's
  systemd + Kerberos keyrings and Docker's overlay2. Do not run untrusted
  workloads in it.
- RAM: ${CT_RAM} MB. FreeIPA + CheckMK + Keycloak together need ~4–6 GB.
- Firewall: open the ansipa ports (see docs/md/ansipa-setup.md → Ports).
EOF

# ─── Summary ──────────────────────────────────────────────────────────────────
section "Done"
log "Artifacts written to: $OUT_DIR"
info "  pct-create-$VMID.sh   — create the CT (run on Proxmox host)"
info "  ansipa-$VMID.conf     — append to /etc/pve/lxc/$VMID.conf"
info "  ansipa-provision.sh   — first-boot provisioner (run inside CT)"
info "  .env                  — stack secrets (mode 600 — keep safe)"
info "  DEPLOY-$VMID.md       — full deployment guide"
echo
warn "The .env contains generated admin passwords in plain text. Store it securely."
