Skip to content

Instantly share code, notes, and snippets.

@noslin005
Created June 11, 2026 04:02
Show Gist options
  • Select an option

  • Save noslin005/fc6cb953168af745c97f885c27a199e7 to your computer and use it in GitHub Desktop.

Select an option

Save noslin005/fc6cb953168af745c97f885c27a199e7 to your computer and use it in GitHub Desktop.

Create Encrypted Netboot Image

Create disk image

truncate -s 5G rocky9-root.img

Encrypt the image using a password

cryptsetup luksFormat --type luks2 \
--cipher aes-xts-plain64 \
--key-size 512 \
--hash sha512 \
--pbkdf argon2id \
--force-password rocky9-root.img

cryptsetup luksDump rocky9-root.img

Unlock the luks device

cryptsetup open rocky9-root.img cryptroot

Make ext4 filesystem and mount it

mkfs.ext4 -O ^orphan_file -O ^metadata_csum_seed /dev/mapper/cryptroot
mkdir /mnt/rootfs
mount /dev/mapper/cryptroot /mnt/rootfs/

Setup the base OS

sudo dnf install -y \
    --installroot=/mnt/rootfs \
    --releasever=9 \
    --repofrompath=baseos,https://download.rockylinux.org/pub/rocky/9/BaseOS/x86_64/os/ \
    --repofrompath=appstream,https://download.rockylinux.org/pub/rocky/9/AppStream/x86_64/os/ \
    --repofrompath=crb,https://download.rockylinux.org/pub/rocky/9/CRB/x86_64/os/ \
    --disablerepo='\*' \
    --enablerepo=baseos \
    --enablerepo=appstream \
    --enablerepo=crb \
    @minimal-environment \
    clevis \
    clevis-luks \
    clevis-dracut \
    clevis-systemd \
    dracut
    cryptsetup \
    dracut-network \
    dracut-live \
    NetworkManager \
    kernel \
    kernel-modules \
    sudo \
    procps-ng \
    bash-completion

Enter CHROOT enviroment

  • Setup chroot
sudo mount --bind /sys/ /mnt/rootfs/sys
sudo mount --bind /proc /mnt/rootfs/proc
sudo mount --bind /dev/ /mnt/rootfs/dev
sudo cp /etc/resolv.conf /mnt/rootfs/etc/
sudo chroot /mnt/rootfs/ /bin/bash

Customization

  • Generate /etc/fstab
#UUID=4469430d-1615-4f05-a274-9bcfd6b2bbdf
UUID=$(blkid /dev/mapper/cryptroot -s UUID -o value)

cat <<EOF >/etc/fstab
UUID=${UUID} / ext4 defaults 0 1
EOF
  • Generate Account
useradd -m -G wheel -s /bin/bash kiosk
echo 'kiosk:YourSecretPassword'|chpasswd
  • Fix Locale
echo 'LANG=en_US.UTF-8' > /etc/locale.conf
  • OPTIONAL: Create rocky repo
cat <<EOF >/etc/yum.repos.d/rocky.repo
[baseos]
name=Rocky Linux 9 BaseOS
baseurl=https://download.rockylinux.org/pub/rocky/9/BaseOS/x86_64/os/
enabled=1
gpgcheck=1
gpgkey=https://download.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9

[appstream]
name=Rocky Linux 9 AppStream
baseurl=https://download.rockylinux.org/pub/rocky/9/AppStream/x86_64/os/
enabled=1
gpgcheck=1
gpgkey=https://download.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9

[crb]
name=Rocky Linux 9 CRB
baseurl=https://download.rockylinux.org/pub/rocky/9/CRB/x86_64/os/
enabled=1
gpgcheck=1
gpgkey=https://download.rockylinux.org/pub/rocky/RPM-GPG-KEY-Rocky-9
EOF
  • Add dracut module to include ca.cert. TODO: Change this to reflect your case
cat <<'EOF' >/usr/lib/dracut/modules.d/99tang-ca/module-setup.sh
#!/bin/bash

check() { return 0; }
depends() { return 0; }

install() {
    # Install the real CA bundle (not the symlink)
    inst_simple /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem

    # Recreate the symlink chain curl expects
    mkdir -p "${initdir}/etc/pki/tls/certs"
    ln -sf /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem "${initdir}/etc/pki/tls/certs/ca-bundle.crt"

    # Also install your custom CA cert
    inst_simple /etc/pki/ca-trust/source/anchors/lab-ca.crt
}
EOF
  • Configure dracut
cat <<EOF > /etc/dracut.conf.d/99-netboot.conf
hostonly="no"
hostonly_cmdline="yes"
add_dracutmodules+=" qemu-net qemu convertfs pollcdrom crypt clevis clevis-pin-tang network base livenet dmsquash-live tang-ca "
add_drivers+=" virtio_net virtio_pci e1000 ixgbe "
use_fstab="yes"
install_items+=" /usr/bin/ping /usr/bin/curl "
mdadmconf="no"
lvmconf="no"
squash_compress="xz"
early_microcode="no"
EOF
  • Generate the initramfs
dracut -fv --regenerate-all --hostonly-cmdline

Exit chroot and copy the initramfs and kernel

sudo cp /mnt/rootfs/boot/vmlinuz-5.14.0-687.12.1.el9_8.x86_64 vmlinuz
sudo cp /mnt/rootfs/boot/initramfs-5.14.0-687.12.1.el9_8.x86_64.img initrd.img

Umount and detach the LUKS volume

sudo umount -R /mnt/rootfs
sudo cryptsetup close crytroot

Bind the volume to tang server

sudo clevis luks bind -d rocky9-root.img tang '{"url":"https://10.12.0.100/tang"}' -- -k

Get the luks UUID

sudo cryptsetup luksDump rocky9-root.img|grep UUID
UUID:           bf588d92-1d78-41e6-85af-2793a337ecaa

Add CA cert

# Copy the lab-ca.crt to /etc/pki/ca-trust/source/anchors/lab-ca.crt
update-ca-trust extract

Test the image using qemu

#!/bin/bash
set -x

sudo qemu-system-x86_64 \
-enable-kvm \
-cpu host \
-m 4096 \
-smp 4 \
-nographic \
-kernel ./vmlinuz \
-initrd ./initrd.img \
-append "console=ttyS0 rd.neednet=1 ip=dhcp rd.auto=1 rd.luks=1 rd.luks.uuid=bf588d92-1d78-41e6-85af-2793a337ecaa root=UUID=4469430d-1615-4f05-a274-9bcfd6b2bbdf rd.timeout=60 selinux=0" \
-drive file=rocky9-root.img,format=raw,if=virtio \
-netdev bridge,id=net0,br=virbr0 \
-device virtio-net-pci,netdev=net0

If necessary add rd.debug rd.info to the append line

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment