#version=DEVEL # veilor-os kickstart — Fedora 43 KDE base, hardened, minimal. # Build with livemedia-creator inside build/Containerfile. # ── Install source ── # Hard-code version (not $releasever) because lorax doesn't expand # inside kickstart `url`/`repo` directives. Updates repo critical: # base Fedora 43 ships selinux-policy 42.12 with pcre2-10.47-built # file_contexts.bin, which fails chroot %triggerin against host's # libselinux (built against pcre2 10.46). 43.7 in updates is rebuilt. url --mirrorlist="https://mirrors.fedoraproject.org/mirrorlist?repo=fedora-43&arch=x86_64" repo --name=updates --mirrorlist="https://mirrors.fedoraproject.org/mirrorlist?repo=updates-released-f43&arch=x86_64" --install # Local fix-repo: ships selinux-policy 43.7 + pcre2 10.47 paired (matched # regex versions) — bypasses Anaconda's repo-merger ignoring cost/priority # from updates. cost=1 = highest priority. Build via: # dnf download pcre2-10.47 selinux-policy-43.7 ... -d /tmp/veilor-fix-repo # createrepo_c /tmp/veilor-fix-repo repo --name=veilor-fix --baseurl=file:///tmp/veilor-fix-repo --install --cost=1 # ── Locale / keyboard / time (template — adjust per build) ── keyboard --xlayouts='us' lang en_GB.UTF-8 timezone Europe/London --utc # ── Install mode ── # Note: no display mode (text/graphical/cmdline) — livemedia-creator forbids. firstboot --disable eula --agreed # Build-time SELinux disabled to avoid PCRE2 regex version mismatch between # host libselinux and chroot's selinux-policy file_contexts.bin (pcre2 10.46 # vs 10.47). veilor-firstboot.service triggers `fixfiles -F onboot` and # `setenforce 1` on first boot to re-enable enforcing mode. selinux --permissive services --enabled=sshd,fail2ban,usbguard,tuned,auditd,firewalld,chronyd,sddm,veilor-firstboot,veilor-modules-lock # ── Network / hostname ── network --bootproto=dhcp --device=link --activate --hostname=veilor-os firewall --enabled --service=ssh # ── Identity (zero-prompt; only LUKS passphrase asked at install) ── # Note: `auth` command removed in pykickstart 3.x — defaults (sha512 shadow) apply. rootpw --lock user --name=admin --groups=wheel --gecos="veilor admin" --password="" --plaintext # ── Bootloader: kernel hardening flags ── bootloader --location=mbr --append="lockdown=integrity slab_nomerge init_on_alloc=1 init_on_free=1 randomize_kstack_offset=on vsyscall=none" # ── Live ISO partitioning (flat — for live rootfs build only) ── # NOTE: This is the *live* image kickstart. Final installed system uses # a separate installer kickstart (kickstart/install.ks, planned v0.2.1) # that does LUKS2 + btrfs subvols on the target disk. part / --fstype=ext4 --size=8192 # ── Packages ── %packages --excludedocs @^kde-desktop-environment @kde-apps @core @hardware-support @standard # live install plumbing (required by livemedia-creator --make-iso) dracut-live dracut-config-generic kernel grub2-efi-x64 shim-x64 efibootmgr # core hardening tools fail2ban fail2ban-firewalld usbguard usbguard-tools audit policycoreutils-python-utils tuned chrony firewalld plymouth # admin essentials git vim-enhanced tmux htop podman skopeo NetworkManager NetworkManager-wifi # fonts fontconfig freetype fira-code-fonts # remove fluff # Note: KDE Plasma 6 hard-deps on cups/geoclue2/ModemManager/PackageKit # transitively (plasma-print-manager, xdg-desktop-portal, NM-wwan etc), # so package removal breaks depsolve. Daemons disabled at runtime via # scripts/20-harden-kernel.sh instead. -abrt* -snapd -kde-connect -open-vm-tools-desktop -mlocate %end # ── Post-install (nochroot): copy overlay tree into installed root ── %post --nochroot set -eu SRC=/run/install/repo/veilor DEST=/mnt/sysimage if [[ -d $SRC/overlay ]]; then cp -a $SRC/overlay/. $DEST/ fi mkdir -p $DEST/usr/share/veilor-os cp -a $SRC/assets $DEST/usr/share/veilor-os/ cp -a $SRC/scripts $DEST/usr/share/veilor-os/ %end # ── Post-install (chroot): apply hardening, theme, branding ── %post set -uo pipefail exec > >(tee -a /var/log/veilor-install.log) 2>&1 echo "════════════════════════════════════════════════════════" echo " veilor-os install — %post" echo "════════════════════════════════════════════════════════" REPO=/usr/share/veilor-os chmod +x $REPO/scripts/*.sh $REPO/scripts/selinux/*.sh /usr/local/bin/veilor-power /usr/local/sbin/veilor-firstboot # Apply hardening bash $REPO/scripts/10-harden-base.sh bash $REPO/scripts/20-harden-kernel.sh # Build SELinux module bash $REPO/scripts/selinux/build-policy.sh || echo "[WARN] SELinux build failed; load on first boot" # Apply KDE theme + DuckSans + os-release branding bash $REPO/scripts/kde-theme-apply.sh # Force admin password set on first boot (chage expires immediately) chage -d 0 admin # zram swap (no disk swap; keys never leak to platter) dnf install -y zram-generator || true cat > /etc/systemd/zram-generator.conf << 'EOF' [zram0] zram-size = min(ram, 8192) compression-algorithm = zstd EOF # Enable services systemctl enable veilor-firstboot.service systemctl enable veilor-modules-lock.service systemctl enable sshd fail2ban usbguard tuned auditd firewalld chronyd # Default tuned profile = balanced (AC/battery udev rule will override) tuned-adm profile veilor-balanced 2>/dev/null || true # Lock root explicitly (kickstart --lock should already do this) passwd -l root # Sanity: zero references to onyx / personal IPs in installed system if grep -rqi 'onyx\|192\.168\.0\.\|fedora\.local' /etc/veilor* /etc/tuned/profiles/veilor-* 2>/dev/null; then echo "[ERR] brand leak detected in /etc — investigate" fi echo "════════════════════════════════════════════════════════" echo " veilor-os install complete" echo "════════════════════════════════════════════════════════" %end