# FreeIPA Install Procedure Full reproduction guide for `domain-controller.sweet.home`. Tested on Rocky Linux 9.8 (GenericCloud), VMID 108, `pve1.sweet.home`. ## Prerequisites - Proxmox node with `local-zfs` storage and internet access from guests - Rocky Linux 9 GenericCloud image downloaded (see step 1) - SSH access to Proxmox node as a user with `sudo` for `qm`/`pvesm` - The operator's SSH public key available to inject via cloud-init --- ## Step 1 — Download Rocky Linux 9 GenericCloud image On the Proxmox node, download to your ISO/image store: ```bash wget -O /mnt/pve/server-iso/Rocky-9-GenericCloud.latest.x86_64.qcow2 \ https://download.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud.latest.x86_64.qcow2 ``` The image is ~617 MB. The Proxmox storage must be configured to accept both ISO images and disk images (set "Content" to include "Disk image" in the Proxmox UI for that storage). --- ## Step 2 — Prepare the VM in Proxmox Use an existing VM or create a new one. The config used for VMID 108: - **CPU**: 2 cores, x86-64-v2-AES - **RAM**: 2048 MB - **Disk**: 32 GB on `local-zfs` - **BIOS**: SeaBIOS (GenericCloud uses MBR — not UEFI) - **Network**: virtio on `vmbr0`, firewall enabled - **QEMU guest agent**: enabled If rebuilding an existing VM (e.g. replacing a prior OS): ```bash # On pve1 — stop the VM sudo qm stop # Remove existing disks from config sudo qm set --delete scsi0,efidisk0 # Switch to SeaBIOS if the VM was UEFI sudo qm set --bios seabios # Free old disk volumes from storage sudo pvesm free local-zfs:vm--disk-0 sudo pvesm free local-zfs:vm--disk-1 ``` ### Import the Rocky image and configure cloud-init ```bash # Import image as a new disk sudo qm importdisk /mnt/pve/server-iso/Rocky-9-GenericCloud.latest.x86_64.qcow2 local-zfs # Check what disk name was assigned sudo qm config # look for unused0: local-zfs:vm--disk-N # Attach as scsi0 (adjust disk name from above) sudo qm set --scsi0 local-zfs:vm--disk-0,iothread=1 # Resize to 32 GB sudo qm disk resize scsi0 32G # Add cloud-init drive sudo qm set --ide2 local-zfs:cloudinit # Write SSH public key to a temp file echo 'ssh-rsa AAAA... wayne@stream' > /tmp/admin-key.pub # (use the key from variables.nix adminSshKey) # Configure cloud-init # Use the LAN gateway as temporary DNS — IPA itself will be the DNS at # 192.168.2.253, but it's not running yet at this point in the install. sudo qm set \ --ciuser wayne \ --sshkeys /tmp/admin-key.pub \ --ipconfig0 ip=dhcp \ --nameserver 192.168.2.254 \ --searchdomain sweet.home # Set boot order sudo qm set --boot order=scsi0 # Start VM sudo qm start ``` ### Note on SSH key mismatch The GenericCloud image injects the cloud-init SSH key on first boot. If you need to add an additional key (e.g. from a different machine) after first boot, mount the disk via nbd while the VM is stopped: ```bash sudo qm stop sudo qemu-nbd --connect=/dev/nbd1 --format=raw /dev/zvol/rpool/data/vm--disk-0 # wait 2s, then: sudo mount /dev/nbd1p4 /mnt/vm # p4 is the root partition on Rocky 9 GenericCloud sudo tee -a /mnt/vm/home/wayne/.ssh/authorized_keys <<< 'ssh-ed25519 AAAA... extra-key' sudo umount /mnt/vm sudo qemu-nbd --disconnect /dev/nbd1 sudo qm start ``` Rocky 9 GenericCloud partition layout: `p1`=BIOS boot (2M), `p2`=EFI (100M), `p3`=/boot (1G), `p4`=/ (rest). --- ## Step 3 — First-boot system preparation SSH in as `wayne` once cloud-init has completed (usually 60–90 s): ```bash ssh wayne@ ``` ### Add swap (required — FreeIPA needs headroom beyond 1.7 GB RAM) ```bash sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap defaults 0 0' | sudo tee -a /etc/fstab ``` ### Set static IP via NetworkManager ```bash CON=$(nmcli -t -f NAME con show --active | head -1) sudo nmcli con mod "$CON" \ ipv4.method manual \ ipv4.addresses 192.168.2.253/24 \ ipv4.gateway 192.168.2.254 \ ipv4.dns 192.168.2.254 \ ipv4.dns-search sweet.home # Note: using the gateway as DNS here — after IPA installs it becomes the # authoritative resolver at 192.168.2.253. Clients should then point to # 192.168.2.253 for sweet.home resolution. sudo nmcli con up "$CON" ``` ### Fix /etc/hosts (cloud-init maps FQDN to 127.0.0.1 — IPA requires real IP) ```bash sudo sed -i '/domain-controller/d' /etc/hosts echo '192.168.2.253 domain-controller.sweet.home domain-controller' \ | sudo tee -a /etc/hosts # Prevent cloud-init from resetting this on reboot sudo sed -i 's/manage_etc_hosts: true/manage_etc_hosts: false/' \ /etc/cloud/cloud.cfg ``` --- ## Step 4 — Install FreeIPA packages ```bash sudo dnf install -y ipa-server ipa-server-dns ``` This pulls ~200 packages including 389-ds, Dogtag PKI, BIND, and MIT Kerberos. Takes 5–10 minutes depending on mirror speed. --- ## Step 5 — Run the unattended install Generate strong passwords (min 8 chars; store them in your password manager): ```bash DM_PASS=$(openssl rand -base64 24 | tr -dc 'A-Za-z0-9' | head -c 24) ADMIN_PASS=$(openssl rand -base64 24 | tr -dc 'A-Za-z0-9' | head -c 24) echo "Directory Manager: $DM_PASS" echo "IPA Admin: $ADMIN_PASS" # Save both in your password manager NOW before proceeding ``` Run the installer (takes 15–20 minutes): ```bash sudo ipa-server-install \ --realm=SWEET.HOME \ --domain=sweet.home \ --hostname=domain-controller.sweet.home \ --ds-password="$DM_PASS" \ --admin-password="$ADMIN_PASS" \ --setup-dns \ --forwarder=192.168.2.254 \ --no-dnssec-validation \ --no-ntp \ --unattended ``` Key flags: - `--setup-dns` — install BIND as IPA's authoritative DNS for `sweet.home` - `--forwarder=192.168.2.254` — forward non-sweet.home queries to the LAN gateway - `--no-dnssec-validation` — skip DNSSEC (home lab has no DNSSEC chain) - `--no-ntp` — Proxmox handles time sync for guests; don't install chrony --- ## Step 6 — Verify ```bash # All services should show RUNNING ipactl status # Get a Kerberos ticket and confirm echo "$ADMIN_PASS" | kinit admin klist # Check DNS SRV records are in place dig +short _kerberos._udp.sweet.home SRV @127.0.0.1 # Expected: 0 100 88 domain-controller.sweet.home. ``` --- ## Step 7 — Back up the CA certificate ```bash # On domain-controller (encrypted with Directory Manager password) ls -lh /root/cacert.p12 # Copy to a safe location scp root@domain-controller:/root/cacert.p12 ~/backups/ipa-cacert.p12 ``` This file is required if you ever set up a replica or need to re-issue service certificates.