From baf5e73cc1d4da1bff2776ce795d37a5bdf489ff Mon Sep 17 00:00:00 2001 From: The_miro Date: Thu, 2 Jul 2026 13:13:02 +0200 Subject: [PATCH] =?UTF-8?q?feat(tools):=20ansipa-proxmox-lxc.sh=20?= =?UTF-8?q?=E2=80=94=20pre-configured=20full-stack=20ansipa=20Proxmox=20LX?= =?UTF-8?q?C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generate everything needed to run the complete ansipa stack (FreeIPA + CheckMK + Keycloak + PostgreSQL + nginx gateway) inside a single Proxmox LXC container. Unlike freeipa-image.sh's proxmox-lxc target (which exports a FreeIPA-only CT rootfs), this runs the tested docker-compose stack inside a privileged, nesting-enabled CT ("Docker-in-LXC"), so it is the whole management plane in one container. Prompts for domain/realm/VMID/resources, generates all service secrets, and emits: pct-create-.sh, ansipa-.conf (nesting=1,keyctl=1,fuse=1 + the cgroup/apparmor allowances FreeIPA's systemd and Docker overlay2 need), a first-boot provisioner that installs Docker and brings the stack up via run.sh, a filled-in .env (mode 600), and a DEPLOY guide. Verified the generator emits correct, syntactically-valid artifacts. Documented in the ansipa Setup Guide. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MUhrcFU8J1Hnf7vNqNxZNi --- docs/md/ansipa-setup.md | 29 ++++ docs/md/index.md | 3 +- setup/tools/ansipa-proxmox-lxc.sh | 241 ++++++++++++++++++++++++++++++ 3 files changed, 272 insertions(+), 1 deletion(-) create mode 100755 setup/tools/ansipa-proxmox-lxc.sh diff --git a/docs/md/ansipa-setup.md b/docs/md/ansipa-setup.md index 6271fa2..9f20f6b 100644 --- a/docs/md/ansipa-setup.md +++ b/docs/md/ansipa-setup.md @@ -192,6 +192,35 @@ container-internal `172.30.0.12`. --- +## Deploying as a Proxmox LXC container + +To run the whole stack as a single Proxmox container, use the generator: + +```bash +bash setup/tools/ansipa-proxmox-lxc.sh [OUT_DIR] # default ~/ansipa-lxc-out +``` + +It prompts for domain/realm/VMID/resources, generates all secrets, and writes: + +| File | Purpose | +|------|---------| +| `pct-create-.sh` | `pct create` command — run on the Proxmox host | +| `ansipa-.conf` | LXC options to append to `/etc/pve/lxc/.conf` | +| `ansipa-provision.sh` | first-boot provisioner (installs Docker, brings the stack up) | +| `.env` | filled-in stack environment (generated passwords — mode 600) | +| `DEPLOY-.md` | step-by-step guide | + +The container is **privileged** with `nesting=1,keyctl=1,fuse=1` — required for +FreeIPA's systemd + Kerberos keyrings and Docker's overlay2. It runs the same +tested docker-compose stack inside the CT ("Docker-in-LXC"), so it is the full +ansipa deployment in one Proxmox container. Size it ≥6 GB RAM. + +> `setup/tools/freeipa-image.sh` has a separate `proxmox-lxc` target that +> exports a **FreeIPA-only** CT rootfs (no CheckMK/Keycloak/nginx) — use that if +> you want just the identity server; use `ansipa-proxmox-lxc.sh` for the full stack. + +--- + ## Client enrollment ```bash diff --git a/docs/md/index.md b/docs/md/index.md index f292fac..e6ddf89 100644 --- a/docs/md/index.md +++ b/docs/md/index.md @@ -71,7 +71,8 @@ Dotfiles/ │ │ ├── wds-deploy.sh # package netboot artifacts for WDS/PXE │ │ ├── write-usb.sh # write the ISO to a USB stick │ │ ├── generate-answerfile.sh # dry-run to produce answerfile.json -│ │ ├── proxmox-lxc-gen.sh # Proxmox LXC container generator (TUI) +│ │ ├── proxmox-lxc-gen.sh # generic Proxmox LXC container generator (TUI) +│ │ ├── ansipa-proxmox-lxc.sh # pre-configured full ansipa stack as a Proxmox LXC │ │ └── freeipa-image.sh # build the ansipa FreeIPA container image │ └── modules/ # Modular install scripts ├── desktopenvs/hyprlua/ # HyprLua (Lua-based Hyprland) configs diff --git a/setup/tools/ansipa-proxmox-lxc.sh b/setup/tools/ansipa-proxmox-lxc.sh new file mode 100755 index 0000000..1f98d76 --- /dev/null +++ b/setup/tools/ansipa-proxmox-lxc.sh @@ -0,0 +1,241 @@ +#!/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-.sh runnable pct create command (run on the Proxmox host) +# ansipa-.conf LXC options to append to /etc/pve/lxc/.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-.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) +SMB_SCAN_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" < "$OUT_DIR/pct-create-$VMID.sh" <> /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" < "$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" <> /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://: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."