- restructure boot/kickstarts/scripts/docs into homelab/ - docs: alma9->10 breaking changes, CIS hardening, kickstart changes - add find_cron_entries.sh helper and codex running memory notes Co-Authored-By: Claude Fable 5 <[email protected]>
11 KiB
Replication Guide
This document describes how to reproduce the AlmaLinux PXE + Kickstart environment on a fresh server1.
Topology
server1: PXE services- runs
dnsmasq - serves TFTP boot files
- serves Alma install tree and Kickstarts over HTTP
- runs
server2: install target- configured to check local disk first and fall back to PXE
Example addresses used in the current lab:
server1:192.168.50.1- host on
pxe-lab:192.168.50.254 server2: DHCP client on the same isolated PXE subnet
Replace these with your real values everywhere below.
Services
You need these on server1:
dnsmasq- an HTTP server such as
nginx,httpd, orcaddy - TFTP root directory
Common paths used in this repo:
- TFTP root:
/var/lib/tftpboot - HTTP root:
/var/www/html - Alma install tree:
/var/www/html/alma/10/BaseOS/x86_64/os - Kickstarts:
/var/www/html/kickstarts
1. Install Packages On Server 1
Example for AlmaLinux or RHEL-family hosts:
sudo dnf install -y dnsmasq nginx syslinux-tftpboot grub2-efi-x64 shim-x64
Example for Debian or Ubuntu:
sudo apt-get update
sudo apt-get install -y dnsmasq nginx pxelinux syslinux-common grub-efi-amd64-bin shim-signed
Package names vary slightly by distro. Adjust as needed for your host.
2. Prepare HTTP And TFTP Paths
sudo mkdir -p /var/lib/tftpboot/pxelinux.cfg
sudo mkdir -p /var/lib/tftpboot/EFI/BOOT
sudo mkdir -p /var/www/html/alma/10/BaseOS/x86_64/os
sudo mkdir -p /var/www/html/kickstarts
3. Copy AlmaLinux ISO Contents To HTTP Root
Place the ISO in this repo, then run:
./scripts/sync_alma_tree.sh \
--iso ./AlmaLinux-10.1-x86_64-minimal.iso \
--http-root /var/www/html/alma/10/BaseOS/x86_64/os
This mounts the ISO read-only and copies the contents into the HTTP install tree.
4. Copy PXE Boot Files
From the extracted Alma tree, copy:
images/pxeboot/vmlinuzimages/pxeboot/initrd.img
Example:
sudo cp /var/www/html/alma/10/BaseOS/x86_64/os/images/pxeboot/vmlinuz /var/lib/tftpboot/vmlinuz-alma10
sudo cp /var/www/html/alma/10/BaseOS/x86_64/os/images/pxeboot/initrd.img /var/lib/tftpboot/initrd-alma10.img
For BIOS clients, also copy PXELINUX assets:
sudo cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot/
sudo cp /usr/share/syslinux/menu.c32 /var/lib/tftpboot/
sudo cp /usr/share/syslinux/libutil.c32 /var/lib/tftpboot/
sudo cp /usr/share/syslinux/ldlinux.c32 /var/lib/tftpboot/
For UEFI clients, install or copy the GRUB EFI loader that matches your distro packaging.
Typical examples:
/boot/efi/EFI/BOOT/BOOTX64.EFI/boot/efi/EFI/almalinux/grubx64.efi/boot/efi/EFI/almalinux/shimx64.efi
5. Publish Kickstart Files
Copy the Kickstart file into the HTTP root:
sudo cp kickstarts/alma10-auto.ks /var/www/html/kickstarts/alma10-auto.ks
sudo cp scripts/post-install-bootstrap.sh /var/www/html/kickstarts/post-install-bootstrap.sh
The sample Kickstart expects to be reachable at:
http://192.168.50.1/kickstarts/alma10-auto.ks
Adjust the IP or hostname in:
kickstarts/alma10-auto.kskickstarts/post-install-bootstrap.shboot/grub2/grub.cfgboot/pxelinux.cfg/default
6. Install dnsmasq Config
Use dnsmasq/dnsmasq.conf.example as the base.
Important fields to customize:
- interface name
- DHCP range
- router and DNS values
dhcp-bootenable-tftptftp-root
Then install and restart:
sudo cp dnsmasq/dnsmasq.conf.example /etc/dnsmasq.d/pxe-alma.conf
sudo systemctl enable --now dnsmasq
sudo systemctl restart dnsmasq
7. Install PXE Menu Files
BIOS:
sudo cp boot/pxelinux.cfg/default /var/lib/tftpboot/pxelinux.cfg/default
UEFI:
sudo cp boot/grub2/grub.cfg /var/lib/tftpboot/grub.cfg
sudo cp boot/grub2/grub.cfg /var/lib/tftpboot/EFI/BOOT/grub.cfg
sudo cp /boot/efi/EFI/almalinux/grubx64.efi /var/lib/tftpboot/grubx64.efi
sudo chmod 644 /var/lib/tftpboot/EFI/BOOT/BOOTX64.EFI /var/lib/tftpboot/EFI/BOOT/grubx64.efi /var/lib/tftpboot/grubx64.efi
Some UEFI layouts expect the config under:
/var/lib/tftpboot/EFI/BOOT/grub.cfg/var/lib/tftpboot/grub/grub.cfg
Use the location expected by your GRUB EFI binary.
In the current AlmaLinux 10 UEFI lab, shim fetched EFI/BOOT/BOOTX64.EFI and then looked for:
/grubx64.efi/EFI/BOOT/grub.cfg
So the root-level grubx64.efi copy above was required for successful UEFI PXE handoff.
8. Make Sure HTTP Is Serving The Tree
Verify from another host:
curl -I http://192.168.50.1/alma/10/BaseOS/x86_64/os/
curl -I http://192.168.50.1/kickstarts/alma10-auto.ks
On AlmaLinux, the stock nginx package serves /usr/share/nginx/html by default. In the current lab, the published content is exposed by symlinking:
sudo ln -sfn /var/www/html/alma /usr/share/nginx/html/alma
sudo ln -sfn /var/www/html/kickstarts /usr/share/nginx/html/kickstarts
sudo nginx -t
sudo systemctl reload nginx
9. Optional: Proxy AppStream Through server1
If your PXE subnet is isolated and you want the installer to download packages without direct outbound internet access from server2, install squid on server1 and allow the PXE subnet to use it.
sudo dnf install -y squid
sudo sed -i '/^http_access allow localhost$/a http_access allow localnet' /etc/squid/squid.conf
sudo systemctl enable --now squid
sudo systemctl restart squid
Validate from server1:
curl -I -x http://127.0.0.1:3128 https://mirrors.almalinux.org/mirrorlist/10.1/appstream
The current Kickstart uses the local BaseOS tree and fetches AppStream through the proxy:
url --url="http://192.168.50.1/alma/10/BaseOS/x86_64/os"
repo --name="appstream" --mirrorlist="https://mirrors.almalinux.org/mirrorlist/10.1/appstream" --proxy="http://192.168.50.1:3128"
The sample Kickstart commits a salted SHA-512 root password hash with:
rootpw --iscrypted ...
Only the hash is stored in Git. If you rotate the password, generate a new hash with openssl passwd -6 and replace the rootpw line.
10. Give The Host Direct Access To pxe-lab
In the working lab, the libvirt bridge virbr1 already existed for pxe-lab, but the host itself did not have an IP on that subnet. Adding one made direct host-to-guest SSH validation possible without hopping through server1.
Runtime command used on the host:
sudo ip addr add 192.168.50.254/24 dev virbr1
Validation:
ip -brief addr show dev virbr1
ip route get 192.168.50.150
ping -c 2 192.168.50.150
If you want that to persist across host reboots, configure the bridge address through your host network manager instead of relying on the one-shot ip addr add command.
11. Boot Server 2
Set server2 to:
- UEFI PXE boot, or BIOS PXE boot depending on hardware
- disk first, network second
When PXE works correctly:
server2first checks the local disk- on a blank disk, firmware falls through to PXE
- it gets an IP from
dnsmasq - it downloads the bootloader from TFTP
- it loads kernel + initrd
- installer fetches the install tree from HTTP
- Kickstart runs unattended
This boot order is important. If network boot is left ahead of disk boot, the guest can re-enter PXE after the first successful install and start a second unattended reinstall.
12. Post-Install Bootstrap
The sample Kickstart calls scripts/post-install-bootstrap.sh during %post.
That script:
- installs
git,curl,sudo, and related basics if missing - clones your
kickstartrepo to/usr/local/valherun/kickstart - clones your
toolsrepo to/usr/local/valherun/tools - optionally runs:
- a local non-interactive
valherunaccount bootstrap that mirrors your current SSH keys, sudo policy, and a committed salted password hash kickstart/bash_profiles.sh --addusertools/bin/install_codex_access.sh --pubkey "$CODEX_PUBKEY" --no-reloadtools/bin/update_sshd_config.sh --no-reload
- a local non-interactive
This gives you a second-stage bootstrap after the base OS install is complete.
13. Post-Install Validation
In the working lab, server2 came up on 192.168.50.150 and the following direct checks from the host succeeded:
ping -c 2 192.168.50.150
ssh [email protected] 'id && hostnamectl --static && sudo -n true'
ssh [email protected] 'ls -d /usr/local/valherun/kickstart /usr/local/valherun/tools'
ssh [email protected] 'sudo systemctl is-active sshd firewalld qemu-guest-agent'
ssh [email protected] 'id'
Current observed state:
codexSSH works directly from the host and has passwordlesssudovalherunSSH works directly from the hostvalherunsudo requires a password- the installed hostname is still
alma10-auto
The valherun step is handled locally in this repo instead of calling kickstart/bin/create_valherun.sh because that upstream helper runs passwd valherun, which blocks unattended Kickstart %post. The local helper sets valherun with a salted SHA-512 password hash and the expected SSH keys. The SSH helpers are run with --no-reload so the install does not depend on reloading sshd inside the installer chroot.
The PXE bootstrap also pins the preferred codex public key directly in scripts/post-install-bootstrap.sh so unattended installs do not inherit the fallback key embedded in the shared tools helper. Those clones run over HTTPS through the proxy on server1, so no local tarball mirror is required.
The post-install bootstrap also exports proxy variables by default:
http_proxy=http://192.168.50.1:3128
https_proxy=http://192.168.50.1:3128
Notes About Your Existing kickstart.sh
Your current kickstart.sh is useful for interactive host bootstrap, but it is not ideal for unattended Kickstart %post as-is because:
- it prompts by default
--allre-enables the Unraid path internally
For unattended Alma installs, this repo uses the reusable sub-scripts directly instead.
Validation Checklist
Before attempting install:
dnsmasq --testcurl -Iagainst the Alma treecurl -Iagainst the Kickstart file- confirm
vmlinuzandinitrd.imgexist in TFTP root - confirm
server2can PXE on the intended NIC and VLAN
Suggested Next Improvements
- add a host-specific Kickstart per target machine
- add static DHCP reservation for
server2 - add UEFI HTTP Boot if the hardware supports it
- add a wrapper to sync repo files directly into
/srv/tftpand/srv/www