Dotfiles/setup/tools/ansipa-proxmox-lxc.sh

241 lines
11 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/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 ~46 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."