setup: replace proxmox-vm target with proxmox-lxc in image builder

The previous proxmox-vm target (virt-customize + QCOW2) is replaced with
a proper Proxmox LXC CT template builder:

- Exports container rootfs as .tar.zst (same mechanism as the lxc target)
- Asks for CT ID, storage, bridge, memory, cores, disk size
- Generates pve-ct-<VMID>.conf with the required FreeIPA LXC options:
    unprivileged: 0
    lxc.apparmor.profile: unconfined
    lxc.cap.drop:
    lxc.mount.auto: proc:rw sys:rw cgroup:rw
    lxc.cgroup2.devices.allow: a
- Generates proxmox-lxc-setup.txt with the full 6-step setup guide
  (upload, pct create, apply LXC opts, set env vars, start, Keycloak)
- Optionally uploads template + conf to Proxmox host via SCP if a
  host is provided

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
main
The_miro 2026-05-18 11:27:50 +02:00
parent f66775ce54
commit 9e708556d5
3 changed files with 119 additions and 63 deletions

View File

@ -186,7 +186,7 @@ SELECTED=$(dialog --backtitle "$BACKTITLE" \
"cockpit" "Cockpit web UI · machines · podman" off \ "cockpit" "Cockpit web UI · machines · podman" off \
"ssh-server" "SSH server openssh · key-auth · enabled" off \ "ssh-server" "SSH server openssh · key-auth · enabled" off \
"freeipa-server" "FreeIPA Server interactive server setup + client gen" off \ "freeipa-server" "FreeIPA Server interactive server setup + client gen" off \
"freeipa-image" "FreeIPA Image OCI/LXC/Proxmox/VM builder + Keycloak" off \ "freeipa-image" "FreeIPA Image OCI/LXC/Proxmox LXC builder + Keycloak" off \
"python" "Python tools pyright · pipx · pynvim" off \ "python" "Python tools pyright · pipx · pynvim" off \
"zfs" "ZFS zfs-dkms kernel module" off \ "zfs" "ZFS zfs-dkms kernel module" off \
"wprs" "WPRS wprs-git (AUR)" off \ "wprs" "WPRS wprs-git (AUR)" off \

View File

@ -71,8 +71,8 @@ TARGET=$(dialog --backtitle "$BACKTITLE" \
--title " Select Target Format " \ --title " Select Target Format " \
--menu "Choose the output format:" 16 70 4 \ --menu "Choose the output format:" 16 70 4 \
"docker" "Docker / Podman image (local + optional registry push)" \ "docker" "Docker / Podman image (local + optional registry push)" \
"lxc" "LXC / Proxmox CT template (.tar.zst rootfs archive)" \ "lxc" "LXC template (.tar.zst rootfs, generic LXC/LXD)" \
"proxmox-vm" "Proxmox VM (cloud-init QCOW2, requires virt-customize)" \ "proxmox-lxc" "Proxmox LXC CT template + conf + optional upload" \
"oci-archive" "OCI archive (skopeo tarball for air-gapped import)" \ "oci-archive" "OCI archive (skopeo tarball for air-gapped import)" \
3>&1 1>&2 2>&3) || { clear; echo "Aborted."; exit 0; } 3>&1 1>&2 2>&3) || { clear; echo "Aborted."; exit 0; }
@ -119,12 +119,18 @@ if [[ "$WITH_KEYCLOAK" == true ]]; then
ask "Keycloak realm name [$KC_REALM]:"; read -r I; KC_REALM="${I:-$KC_REALM}" ask "Keycloak realm name [$KC_REALM]:"; read -r I; KC_REALM="${I:-$KC_REALM}"
fi fi
# Proxmox VM cloud image (only if proxmox-vm selected) # Proxmox LXC extra config
CLOUD_IMAGE_URL="" PVE_HOST=""; PVE_VMID="100"; PVE_STORAGE="local"; PVE_BRIDGE="vmbr0"
if [[ "$TARGET" == "proxmox-vm" ]]; then PVE_MEMORY="4096"; PVE_CORES="4"; PVE_DISK_SIZE="20"
if [[ "$TARGET" == "proxmox-lxc" ]]; then
echo echo
ROCKY_URL="https://dl.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud.latest.x86_64.qcow2" ask "Proxmox host (blank to skip upload):"; read -r PVE_HOST
ask "Cloud image URL [$ROCKY_URL]:"; read -r I; CLOUD_IMAGE_URL="${I:-$ROCKY_URL}" ask "Container ID [100]:"; read -r I; PVE_VMID="${I:-100}"
ask "Storage for rootfs [local-lvm]:"; read -r I; PVE_STORAGE="${I:-local-lvm}"
ask "Network bridge [vmbr0]:"; read -r I; PVE_BRIDGE="${I:-vmbr0}"
ask "Memory MB [4096]:"; read -r I; PVE_MEMORY="${I:-4096}"
ask "CPU cores [4]:"; read -r I; PVE_CORES="${I:-4}"
ask "Disk size GB [20]:"; read -r I; PVE_DISK_SIZE="${I:-20}"
fi fi
# ─── Confirm ────────────────────────────────────────────────────────────────── # ─── Confirm ──────────────────────────────────────────────────────────────────
@ -225,65 +231,115 @@ LXCTXT
log "Instructions: $OUTPUT_DIR/lxc-import-instructions.txt" log "Instructions: $OUTPUT_DIR/lxc-import-instructions.txt"
;; ;;
proxmox-vm) proxmox-lxc)
section "Proxmox VM — cloud-init QCOW2" section "Proxmox LXC CT template"
TEMPLATE_NAME="freeipa-server-proxmox-lxc.tar.zst"
TEMPLATE_PATH="$OUTPUT_DIR/$TEMPLATE_NAME"
if ! command -v virt-customize &>/dev/null; then info "Creating temporary container to export rootfs..."
error "virt-customize not found. Install libguestfs-tools:" TMP_CTR="freeipa-pve-export-$$"
error " sudo pacman -S libguestfs # Arch" $ENGINE create --name "$TMP_CTR" "$IMAGE_TAG" /bin/true
error " sudo dnf install libguestfs-tools # Fedora/RHEL"
exit 1 info "Exporting rootfs..."
fi if command -v zstd &>/dev/null; then
if ! command -v qemu-img &>/dev/null; then $ENGINE export "$TMP_CTR" | zstd -T0 -o "$TEMPLATE_PATH"
error "qemu-img not found. Install qemu-img / qemu-tools." else
exit 1 warn "zstd not found — falling back to gzip (.tar.gz)"
TEMPLATE_NAME="freeipa-server-proxmox-lxc.tar.gz"
TEMPLATE_PATH="$OUTPUT_DIR/$TEMPLATE_NAME"
$ENGINE export "$TMP_CTR" | gzip -9 > "$TEMPLATE_PATH"
fi fi
$ENGINE rm "$TMP_CTR" &>/dev/null
log "Template: $TEMPLATE_PATH"
CLOUD_IMG="$TMP_D/cloud-base.qcow2" # Generate Proxmox CT config file
QCOW2_OUT="$OUTPUT_DIR/freeipa-server.qcow2" CT_CONF="$OUTPUT_DIR/pve-ct-${PVE_VMID}.conf"
cat > "$CT_CONF" <<CONFEOF
info "Downloading cloud image..." # Proxmox LXC config for FreeIPA server — copy to /etc/pve/lxc/${PVE_VMID}.conf
curl -L --progress-bar -o "$CLOUD_IMG" "$CLOUD_IMAGE_URL" # FreeIPA requires a privileged container with unconfined AppArmor and full cgroup access.
arch: amd64
info "Customizing image (installing FreeIPA packages)..." cores: $PVE_CORES
virt-customize -a "$CLOUD_IMG" \
--install freeipa-server,freeipa-server-dns,ansible-core,python3-netaddr \
--copy-in "$IMAGE_SRC/ipa-first-boot.sh":/usr/local/sbin/ \
--copy-in "$IMAGE_SRC/ipa-first-boot.service":/etc/systemd/system/ \
--run-command "chmod +x /usr/local/sbin/ipa-first-boot.sh" \
--run-command "systemctl enable ipa-first-boot.service" \
--selinux-relabel
qemu-img convert -O qcow2 "$CLOUD_IMG" "$QCOW2_OUT"
log "QCOW2: $QCOW2_OUT"
# Cloud-init snippet
cat > "$OUTPUT_DIR/cloud-init-user-data.yml" <<CIEOF
#cloud-config
# Attach this as cloud-init user-data when creating the Proxmox VM.
hostname: ${IPA_HOSTNAME%%.*} hostname: ${IPA_HOSTNAME%%.*}
fqdn: $IPA_HOSTNAME memory: $PVE_MEMORY
manage_etc_hosts: true net0: name=eth0,bridge=$PVE_BRIDGE,firewall=0,ip=dhcp
ostype: fedora
rootfs: $PVE_STORAGE:vm-${PVE_VMID}-disk-0,size=${PVE_DISK_SIZE}G
swap: 512
unprivileged: 0
lxc.apparmor.profile: unconfined
lxc.cap.drop:
lxc.mount.auto: proc:rw sys:rw cgroup:rw
lxc.cgroup2.devices.allow: a
CONFEOF
log "CT config: $CT_CONF"
write_files: # Generate setup guide
- path: /etc/environment cat > "$OUTPUT_DIR/proxmox-lxc-setup.txt" <<GUIDEOF
append: true Proxmox LXC setup guide — FreeIPA server
content: | ==========================================
Template: $TEMPLATE_NAME
CT ID: $PVE_VMID
Storage: $PVE_STORAGE
Bridge: $PVE_BRIDGE
── Step 1: Upload template ─────────────────────────────────
scp $TEMPLATE_PATH root@<proxmox-host>:/var/lib/vz/template/cache/
── Step 2: Create the container ────────────────────────────
pct create $PVE_VMID local:vztmpl/$TEMPLATE_NAME \\
--hostname ${IPA_HOSTNAME%%.*} \\
--memory $PVE_MEMORY --cores $PVE_CORES \\
--rootfs $PVE_STORAGE:${PVE_DISK_SIZE} \\
--net0 name=eth0,bridge=$PVE_BRIDGE,ip=dhcp \\
--ostype fedora --unprivileged 0 \\
--features nesting=1
── Step 3: Apply required LXC options ──────────────────────
# FreeIPA needs unconfined AppArmor and full cgroup access.
# Copy the generated config or append these lines:
cat >> /etc/pve/lxc/$PVE_VMID.conf <<EOF
lxc.apparmor.profile: unconfined
lxc.cap.drop:
lxc.mount.auto: proc:rw sys:rw cgroup:rw
lxc.cgroup2.devices.allow: a
EOF
── Step 4: Set FreeIPA configuration ───────────────────────
pct start $PVE_VMID
pct exec $PVE_VMID -- bash -c 'cat >> /etc/environment <<EOF
IPA_DOMAIN=$IPA_DOMAIN IPA_DOMAIN=$IPA_DOMAIN
IPA_REALM=$IPA_REALM IPA_REALM=$IPA_REALM
IPA_HOSTNAME=$IPA_HOSTNAME
IPA_ADMIN_PASSWORD=ChangeMe123! IPA_ADMIN_PASSWORD=ChangeMe123!
IPA_DM_PASSWORD=ChangeMe456! IPA_DM_PASSWORD=ChangeMe456!
IPA_SETUP_DNS=false
EOF'
pct stop $PVE_VMID
runcmd: ── Step 5: Start and watch first-boot ──────────────────────
- systemctl enable --now ipa-first-boot.service pct start $PVE_VMID
CIEOF pct exec $PVE_VMID -- journalctl -fu ipa-first-boot
log "Cloud-init snippet: $OUTPUT_DIR/cloud-init-user-data.yml" # First-boot installs FreeIPA (~10 min). Done when you see:
# "ipa-first-boot complete"
info "Proxmox VM import:" ── Step 6 (optional): Keycloak stack ───────────────────────
info " qm create <VMID> --name freeipa --memory 4096 --cores 4 --net0 virtio,bridge=vmbr0" # Run the Keycloak constellation on a separate CT or VM,
info " qm importdisk <VMID> $QCOW2_OUT local-lvm" # then configure LDAP federation:
info " qm set <VMID> --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-<VMID>-disk-0" # IPA_SERVER=$IPA_HOSTNAME KC_ADMIN_PASSWORD=<pw> \\
info " qm set <VMID> --ide2 local-lvm:cloudinit --boot c --bootdisk scsi0" # IPA_DOMAIN=$IPA_DOMAIN IPA_DM_PASSWORD=<pw> \\
# ./keycloak-configure.sh
GUIDEOF
log "Setup guide: $OUTPUT_DIR/proxmox-lxc-setup.txt"
# Optional: upload to Proxmox host
if [[ -n "$PVE_HOST" ]]; then
section "Uploading template to $PVE_HOST"
scp "$TEMPLATE_PATH" "root@${PVE_HOST}:/var/lib/vz/template/cache/"
scp "$CT_CONF" "root@${PVE_HOST}:/etc/pve/lxc/${PVE_VMID}.conf"
log "Template uploaded to $PVE_HOST"
info "Next: pct create $PVE_VMID local:vztmpl/$TEMPLATE_NAME ..."
info " (see $OUTPUT_DIR/proxmox-lxc-setup.txt for full command)"
fi
;; ;;
oci-archive) oci-archive)

View File

@ -221,7 +221,7 @@ SELECTED_APPS=$(dialog --backtitle "$BACKTITLE" \
"cockpit" "Cockpit web UI · machines · podman" off \ "cockpit" "Cockpit web UI · machines · podman" off \
"ssh-server" "SSH server openssh · key-auth · enabled" off \ "ssh-server" "SSH server openssh · key-auth · enabled" off \
"freeipa-server" "FreeIPA Server interactive server setup + client gen" off \ "freeipa-server" "FreeIPA Server interactive server setup + client gen" off \
"freeipa-image" "FreeIPA Image OCI/LXC/Proxmox/VM builder + Keycloak" off \ "freeipa-image" "FreeIPA Image OCI/LXC/Proxmox LXC builder + Keycloak" off \
"python" "Python tools pyright · pipx · pynvim" off \ "python" "Python tools pyright · pipx · pynvim" off \
"zfs" "ZFS zfs-dkms kernel module" off \ "zfs" "ZFS zfs-dkms kernel module" off \
"wprs" "WPRS wprs-git (AUR)" off \ "wprs" "WPRS wprs-git (AUR)" off \