Archived
feat(freeipa): add domain-controller setup — Rocky Linux 9 + FreeIPA 4.13
Installs and documents the FreeIPA identity management server at domain-controller.sweet.home (VMID 108, pve1). Provides Kerberos, LDAP, and integrated DNS for the SWEET.HOME realm. New section: freeipa/ - docs/install.md: full step-by-step reproduction procedure including Proxmox VM prep (Rocky Linux 9 GenericCloud, SeaBIOS, cloud-init), swap setup, static IP, /etc/hosts fix, ipa-server-install flags - docs/pihole-dns.md: how to configure Pi-hole to forward sweet.home queries to the FreeIPA BIND instance - scripts/install.sh: idempotent install script with pre-flight checks; reads passwords from env or interactive prompt (never commits them) - scripts/configure-pihole-dns.sh: idempotent Pi-hole forwarder setup - scripts/verify.sh: read-only health check (13 checks, 0 side effects) - CLAUDE.md: host guardrails for domain-controller Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015Jbvxx4xbHVcx1NkK3vtmK
This commit is contained in:
Executable
+130
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env bash
|
||||
# FreeIPA server install script for domain-controller.sweet.home
|
||||
#
|
||||
# Run this on a fresh Rocky Linux 9 VM that already has:
|
||||
# - Correct hostname: domain-controller.sweet.home
|
||||
# - Static IP: 192.168.2.138/24
|
||||
# - Gateway: 192.168.2.254
|
||||
# - DNS: 192.168.2.253 (Pi-hole)
|
||||
# - sudo access for the current user
|
||||
#
|
||||
# The script will prompt for passwords if not set via environment:
|
||||
# IPA_DM_PASSWORD Directory Manager password (store in password manager)
|
||||
# IPA_ADMIN_PASSWORD IPA admin Kerberos password (store in password manager)
|
||||
#
|
||||
# Full procedure: see docs/install.md
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
IPA_REALM="SWEET.HOME"
|
||||
IPA_DOMAIN="sweet.home"
|
||||
IPA_HOSTNAME="domain-controller.sweet.home"
|
||||
IPA_IP="192.168.2.138"
|
||||
IPA_DNS_FORWARDER="192.168.2.253"
|
||||
|
||||
# ── Password handling ────────────────────────────────────────────────────────
|
||||
|
||||
if [[ -z "${IPA_DM_PASSWORD:-}" ]]; then
|
||||
read -r -s -p "Directory Manager password (min 8 chars): " IPA_DM_PASSWORD
|
||||
echo
|
||||
fi
|
||||
if [[ -z "${IPA_ADMIN_PASSWORD:-}" ]]; then
|
||||
read -r -s -p "IPA admin password (min 8 chars): " IPA_ADMIN_PASSWORD
|
||||
echo
|
||||
fi
|
||||
|
||||
if [[ ${#IPA_DM_PASSWORD} -lt 8 || ${#IPA_ADMIN_PASSWORD} -lt 8 ]]; then
|
||||
echo "ERROR: passwords must be at least 8 characters" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── Pre-flight checks ────────────────────────────────────────────────────────
|
||||
|
||||
echo "==> Checking hostname..."
|
||||
actual_fqdn=$(hostname -f)
|
||||
if [[ "$actual_fqdn" != "$IPA_HOSTNAME" ]]; then
|
||||
echo "ERROR: hostname -f returned '$actual_fqdn', expected '$IPA_HOSTNAME'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "==> Checking /etc/hosts entry..."
|
||||
if ! grep -q "$IPA_IP $IPA_HOSTNAME" /etc/hosts; then
|
||||
echo "ERROR: /etc/hosts does not have '$IPA_IP $IPA_HOSTNAME'" >&2
|
||||
echo "Fix: sudo sed -i '/$IPA_HOSTNAME/d' /etc/hosts && echo '$IPA_IP $IPA_HOSTNAME ${IPA_HOSTNAME%%.*}' | sudo tee -a /etc/hosts" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "==> Checking Python FQDN resolution..."
|
||||
resolved=$(python3 -c "import socket; print(socket.gethostbyname('$IPA_HOSTNAME'))" 2>/dev/null || true)
|
||||
if [[ "$resolved" != "$IPA_IP" ]]; then
|
||||
echo "ERROR: $IPA_HOSTNAME resolves to '$resolved', expected '$IPA_IP'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "==> Checking internet connectivity..."
|
||||
if ! ping -c1 -W5 8.8.8.8 >/dev/null 2>&1; then
|
||||
echo "ERROR: no internet connectivity (needed for package install)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── Swap ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
if ! swapon --show | grep -q .; then
|
||||
echo "==> Creating 2 GB swap file (FreeIPA needs headroom)..."
|
||||
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress
|
||||
sudo chmod 600 /swapfile
|
||||
sudo mkswap /swapfile
|
||||
sudo swapon /swapfile
|
||||
grep -q '/swapfile' /etc/fstab || echo '/swapfile none swap defaults 0 0' | sudo tee -a /etc/fstab
|
||||
else
|
||||
echo "==> Swap already configured, skipping."
|
||||
fi
|
||||
|
||||
# ── Packages ─────────────────────────────────────────────────────────────────
|
||||
|
||||
echo "==> Installing FreeIPA server packages..."
|
||||
sudo dnf install -y ipa-server ipa-server-dns
|
||||
|
||||
# ── Install ──────────────────────────────────────────────────────────────────
|
||||
|
||||
echo "==> Running ipa-server-install (15–20 min)..."
|
||||
sudo ipa-server-install \
|
||||
--realm="$IPA_REALM" \
|
||||
--domain="$IPA_DOMAIN" \
|
||||
--hostname="$IPA_HOSTNAME" \
|
||||
--ds-password="$IPA_DM_PASSWORD" \
|
||||
--admin-password="$IPA_ADMIN_PASSWORD" \
|
||||
--setup-dns \
|
||||
--forwarder="$IPA_DNS_FORWARDER" \
|
||||
--no-dnssec-validation \
|
||||
--no-ntp \
|
||||
--unattended
|
||||
|
||||
# ── Verify ───────────────────────────────────────────────────────────────────
|
||||
|
||||
echo "==> Verifying services..."
|
||||
sudo ipactl status
|
||||
|
||||
echo "==> Verifying Kerberos ticket..."
|
||||
echo "$IPA_ADMIN_PASSWORD" | kinit admin
|
||||
klist
|
||||
|
||||
echo "==> Verifying DNS SRV records..."
|
||||
dig +short _kerberos._udp."$IPA_DOMAIN" SRV @127.0.0.1
|
||||
|
||||
echo ""
|
||||
echo "======================================================================"
|
||||
echo "Setup complete. Next steps:"
|
||||
echo ""
|
||||
echo " 1. Save passwords to your password manager (if not already done)."
|
||||
echo ""
|
||||
echo " 2. Configure Pi-hole to forward $IPA_DOMAIN DNS to $IPA_IP:"
|
||||
echo " bash scripts/configure-pihole-dns.sh <pihole-host>"
|
||||
echo ""
|
||||
echo " 3. Back up the CA certificates:"
|
||||
echo " scp root@$IPA_HOSTNAME:/root/cacert.p12 ~/backups/ipa-cacert.p12"
|
||||
echo " (Encrypted with the Directory Manager password)"
|
||||
echo ""
|
||||
echo " 4. Access the Web UI at:"
|
||||
echo " https://$IPA_HOSTNAME/ipa/ui/"
|
||||
echo "======================================================================"
|
||||
Reference in New Issue
Block a user