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
parent
f66775ce54
commit
9e708556d5
|
|
@ -186,7 +186,7 @@ SELECTED=$(dialog --backtitle "$BACKTITLE" \
|
|||
"cockpit" "Cockpit web UI · machines · podman" off \
|
||||
"ssh-server" "SSH server openssh · key-auth · enabled" 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 \
|
||||
"zfs" "ZFS zfs-dkms kernel module" off \
|
||||
"wprs" "WPRS wprs-git (AUR)" off \
|
||||
|
|
|
|||
|
|
@ -70,10 +70,10 @@ command -v dialog &>/dev/null || { sudo pacman -S --noconfirm dialog; }
|
|||
TARGET=$(dialog --backtitle "$BACKTITLE" \
|
||||
--title " Select Target Format " \
|
||||
--menu "Choose the output format:" 16 70 4 \
|
||||
"docker" "Docker / Podman image (local + optional registry push)" \
|
||||
"lxc" "LXC / Proxmox CT template (.tar.zst rootfs archive)" \
|
||||
"proxmox-vm" "Proxmox VM (cloud-init QCOW2, requires virt-customize)" \
|
||||
"oci-archive" "OCI archive (skopeo tarball for air-gapped import)" \
|
||||
"docker" "Docker / Podman image (local + optional registry push)" \
|
||||
"lxc" "LXC template (.tar.zst rootfs, generic LXC/LXD)" \
|
||||
"proxmox-lxc" "Proxmox LXC CT template + conf + optional upload" \
|
||||
"oci-archive" "OCI archive (skopeo tarball for air-gapped import)" \
|
||||
3>&1 1>&2 2>&3) || { clear; echo "Aborted."; exit 0; }
|
||||
|
||||
# ─── Keycloak? ───────────────────────────────────────────────────────────────
|
||||
|
|
@ -119,12 +119,18 @@ if [[ "$WITH_KEYCLOAK" == true ]]; then
|
|||
ask "Keycloak realm name [$KC_REALM]:"; read -r I; KC_REALM="${I:-$KC_REALM}"
|
||||
fi
|
||||
|
||||
# Proxmox VM cloud image (only if proxmox-vm selected)
|
||||
CLOUD_IMAGE_URL=""
|
||||
if [[ "$TARGET" == "proxmox-vm" ]]; then
|
||||
# Proxmox LXC extra config
|
||||
PVE_HOST=""; PVE_VMID="100"; PVE_STORAGE="local"; PVE_BRIDGE="vmbr0"
|
||||
PVE_MEMORY="4096"; PVE_CORES="4"; PVE_DISK_SIZE="20"
|
||||
if [[ "$TARGET" == "proxmox-lxc" ]]; then
|
||||
echo
|
||||
ROCKY_URL="https://dl.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud.latest.x86_64.qcow2"
|
||||
ask "Cloud image URL [$ROCKY_URL]:"; read -r I; CLOUD_IMAGE_URL="${I:-$ROCKY_URL}"
|
||||
ask "Proxmox host (blank to skip upload):"; read -r PVE_HOST
|
||||
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
|
||||
|
||||
# ─── Confirm ──────────────────────────────────────────────────────────────────
|
||||
|
|
@ -225,65 +231,115 @@ LXCTXT
|
|||
log "Instructions: $OUTPUT_DIR/lxc-import-instructions.txt"
|
||||
;;
|
||||
|
||||
proxmox-vm)
|
||||
section "Proxmox VM — cloud-init QCOW2"
|
||||
proxmox-lxc)
|
||||
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
|
||||
error "virt-customize not found. Install libguestfs-tools:"
|
||||
error " sudo pacman -S libguestfs # Arch"
|
||||
error " sudo dnf install libguestfs-tools # Fedora/RHEL"
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v qemu-img &>/dev/null; then
|
||||
error "qemu-img not found. Install qemu-img / qemu-tools."
|
||||
exit 1
|
||||
info "Creating temporary container to export rootfs..."
|
||||
TMP_CTR="freeipa-pve-export-$$"
|
||||
$ENGINE create --name "$TMP_CTR" "$IMAGE_TAG" /bin/true
|
||||
|
||||
info "Exporting rootfs..."
|
||||
if command -v zstd &>/dev/null; then
|
||||
$ENGINE export "$TMP_CTR" | zstd -T0 -o "$TEMPLATE_PATH"
|
||||
else
|
||||
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
|
||||
$ENGINE rm "$TMP_CTR" &>/dev/null
|
||||
log "Template: $TEMPLATE_PATH"
|
||||
|
||||
CLOUD_IMG="$TMP_D/cloud-base.qcow2"
|
||||
QCOW2_OUT="$OUTPUT_DIR/freeipa-server.qcow2"
|
||||
|
||||
info "Downloading cloud image..."
|
||||
curl -L --progress-bar -o "$CLOUD_IMG" "$CLOUD_IMAGE_URL"
|
||||
|
||||
info "Customizing image (installing FreeIPA packages)..."
|
||||
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.
|
||||
# Generate Proxmox CT config file
|
||||
CT_CONF="$OUTPUT_DIR/pve-ct-${PVE_VMID}.conf"
|
||||
cat > "$CT_CONF" <<CONFEOF
|
||||
# Proxmox LXC config for FreeIPA server — copy to /etc/pve/lxc/${PVE_VMID}.conf
|
||||
# FreeIPA requires a privileged container with unconfined AppArmor and full cgroup access.
|
||||
arch: amd64
|
||||
cores: $PVE_CORES
|
||||
hostname: ${IPA_HOSTNAME%%.*}
|
||||
fqdn: $IPA_HOSTNAME
|
||||
manage_etc_hosts: true
|
||||
memory: $PVE_MEMORY
|
||||
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:
|
||||
- path: /etc/environment
|
||||
append: true
|
||||
content: |
|
||||
IPA_DOMAIN=$IPA_DOMAIN
|
||||
IPA_REALM=$IPA_REALM
|
||||
IPA_ADMIN_PASSWORD=ChangeMe123!
|
||||
IPA_DM_PASSWORD=ChangeMe456!
|
||||
# Generate setup guide
|
||||
cat > "$OUTPUT_DIR/proxmox-lxc-setup.txt" <<GUIDEOF
|
||||
Proxmox LXC setup guide — FreeIPA server
|
||||
==========================================
|
||||
Template: $TEMPLATE_NAME
|
||||
CT ID: $PVE_VMID
|
||||
Storage: $PVE_STORAGE
|
||||
Bridge: $PVE_BRIDGE
|
||||
|
||||
runcmd:
|
||||
- systemctl enable --now ipa-first-boot.service
|
||||
CIEOF
|
||||
log "Cloud-init snippet: $OUTPUT_DIR/cloud-init-user-data.yml"
|
||||
── Step 1: Upload template ─────────────────────────────────
|
||||
scp $TEMPLATE_PATH root@<proxmox-host>:/var/lib/vz/template/cache/
|
||||
|
||||
info "Proxmox VM import:"
|
||||
info " qm create <VMID> --name freeipa --memory 4096 --cores 4 --net0 virtio,bridge=vmbr0"
|
||||
info " qm importdisk <VMID> $QCOW2_OUT local-lvm"
|
||||
info " qm set <VMID> --scsihw virtio-scsi-pci --scsi0 local-lvm:vm-<VMID>-disk-0"
|
||||
info " qm set <VMID> --ide2 local-lvm:cloudinit --boot c --bootdisk scsi0"
|
||||
── 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_REALM=$IPA_REALM
|
||||
IPA_HOSTNAME=$IPA_HOSTNAME
|
||||
IPA_ADMIN_PASSWORD=ChangeMe123!
|
||||
IPA_DM_PASSWORD=ChangeMe456!
|
||||
IPA_SETUP_DNS=false
|
||||
EOF'
|
||||
pct stop $PVE_VMID
|
||||
|
||||
── Step 5: Start and watch first-boot ──────────────────────
|
||||
pct start $PVE_VMID
|
||||
pct exec $PVE_VMID -- journalctl -fu ipa-first-boot
|
||||
# First-boot installs FreeIPA (~10 min). Done when you see:
|
||||
# "ipa-first-boot complete"
|
||||
|
||||
── Step 6 (optional): Keycloak stack ───────────────────────
|
||||
# Run the Keycloak constellation on a separate CT or VM,
|
||||
# then configure LDAP federation:
|
||||
# IPA_SERVER=$IPA_HOSTNAME KC_ADMIN_PASSWORD=<pw> \\
|
||||
# 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)
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ SELECTED_APPS=$(dialog --backtitle "$BACKTITLE" \
|
|||
"cockpit" "Cockpit web UI · machines · podman" off \
|
||||
"ssh-server" "SSH server openssh · key-auth · enabled" 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 \
|
||||
"zfs" "ZFS zfs-dkms kernel module" off \
|
||||
"wprs" "WPRS wprs-git (AUR)" off \
|
||||
|
|
|
|||
Loading…
Reference in New Issue