2026-04-30 03:43:33 +01:00
|
|
|
#version=DEVEL
|
|
|
|
|
# veilor-os kickstart — Fedora 43 KDE base, hardened, minimal.
|
|
|
|
|
# Build with livemedia-creator inside build/Containerfile.
|
|
|
|
|
|
|
|
|
|
# ── Install source ──
|
2026-04-30 10:07:58 +01:00
|
|
|
# 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.
|
2026-04-30 11:16:30 +01:00
|
|
|
url --mirrorlist="https://mirrors.fedoraproject.org/mirrorlist?repo=fedora-43&arch=x86_64"
|
2026-04-30 12:04:49 +01:00
|
|
|
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
|
2026-04-30 03:43:33 +01:00
|
|
|
|
|
|
|
|
# ── Locale / keyboard / time (template — adjust per build) ──
|
|
|
|
|
keyboard --xlayouts='us'
|
|
|
|
|
lang en_GB.UTF-8
|
|
|
|
|
timezone Europe/London --utc
|
|
|
|
|
|
|
|
|
|
# ── Install mode ──
|
2026-04-30 04:11:46 +01:00
|
|
|
# Note: no display mode (text/graphical/cmdline) — livemedia-creator forbids.
|
2026-04-30 03:43:33 +01:00
|
|
|
firstboot --disable
|
|
|
|
|
eula --agreed
|
2026-04-30 09:43:33 +01:00
|
|
|
# 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
|
2026-04-30 13:44:51 +01:00
|
|
|
# veilor-firstboot + veilor-modules-lock enabled via %post after overlay
|
|
|
|
|
# copy (units don't exist yet at services-config phase).
|
|
|
|
|
services --enabled=sshd,fail2ban,usbguard,tuned,auditd,firewalld,chronyd,sddm
|
2026-04-30 03:43:33 +01:00
|
|
|
|
|
|
|
|
# ── Network / hostname ──
|
|
|
|
|
network --bootproto=dhcp --device=link --activate --hostname=veilor-os
|
|
|
|
|
firewall --enabled --service=ssh
|
|
|
|
|
|
|
|
|
|
# ── Identity (zero-prompt; only LUKS passphrase asked at install) ──
|
2026-04-30 04:03:10 +01:00
|
|
|
# Note: `auth` command removed in pykickstart 3.x — defaults (sha512 shadow) apply.
|
2026-04-30 03:43:33 +01:00
|
|
|
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"
|
|
|
|
|
|
2026-04-30 04:12:26 +01:00
|
|
|
# ── 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
|
2026-04-30 03:43:33 +01:00
|
|
|
|
|
|
|
|
# ── Packages ──
|
|
|
|
|
%packages --excludedocs
|
|
|
|
|
@^kde-desktop-environment
|
|
|
|
|
@kde-apps
|
|
|
|
|
@core
|
|
|
|
|
@hardware-support
|
|
|
|
|
@standard
|
|
|
|
|
|
2026-04-30 04:08:08 +01:00
|
|
|
# live install plumbing (required by livemedia-creator --make-iso)
|
|
|
|
|
dracut-live
|
|
|
|
|
dracut-config-generic
|
|
|
|
|
kernel
|
|
|
|
|
grub2-efi-x64
|
2026-04-30 15:07:04 +01:00
|
|
|
grub2-pc
|
|
|
|
|
grub2-pc-modules
|
|
|
|
|
grub2-tools
|
|
|
|
|
grub2-tools-extra
|
2026-04-30 04:08:08 +01:00
|
|
|
shim-x64
|
|
|
|
|
efibootmgr
|
2026-04-30 15:07:04 +01:00
|
|
|
syslinux
|
|
|
|
|
isomd5sum
|
2026-04-30 04:08:08 +01:00
|
|
|
|
2026-04-30 10:45:58 +01:00
|
|
|
|
2026-04-30 03:43:33 +01:00
|
|
|
# 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
|
2026-04-30 03:57:17 +01:00
|
|
|
fira-code-fonts
|
2026-04-30 03:43:33 +01:00
|
|
|
|
2026-04-30 04:31:49 +01:00
|
|
|
# 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.
|
2026-04-30 03:43:33 +01:00
|
|
|
-abrt*
|
|
|
|
|
-snapd
|
|
|
|
|
-kde-connect
|
|
|
|
|
-open-vm-tools-desktop
|
|
|
|
|
-mlocate
|
|
|
|
|
|
|
|
|
|
%end
|
|
|
|
|
|
|
|
|
|
# ── Post-install (nochroot): copy overlay tree into installed root ──
|
|
|
|
|
%post --nochroot
|
|
|
|
|
set -eu
|
|
|
|
|
DEST=/mnt/sysimage
|
2026-04-30 14:14:07 +01:00
|
|
|
|
|
|
|
|
# Try multiple source paths:
|
|
|
|
|
# /run/install/repo/veilor — boot ISO (--virt mode)
|
|
|
|
|
# /work — bind mount in CI container
|
|
|
|
|
# $(dirname kickstart)/.. — local --no-virt builds
|
|
|
|
|
SRC=""
|
|
|
|
|
for candidate in /run/install/repo/veilor /work /mnt/work; do
|
|
|
|
|
if [[ -d $candidate/overlay ]]; then
|
|
|
|
|
SRC=$candidate
|
|
|
|
|
break
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
# Fallback: derive from kickstart path. Anaconda passes ks via --kickstart=<path>.
|
|
|
|
|
if [[ -z $SRC ]]; then
|
|
|
|
|
KS_PATH=$(ps -ef | grep -oP -- '--kickstart[= ]\K[^ ]+' | head -1)
|
|
|
|
|
if [[ -n $KS_PATH && -d $(dirname "$KS_PATH")/../overlay ]]; then
|
|
|
|
|
SRC=$(realpath "$(dirname "$KS_PATH")/..")
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [[ -z $SRC ]]; then
|
|
|
|
|
echo "[ERR] cannot locate veilor-os repo source — overlay/scripts not copied" >&2
|
|
|
|
|
exit 1
|
2026-04-30 03:43:33 +01:00
|
|
|
fi
|
2026-04-30 14:14:07 +01:00
|
|
|
|
|
|
|
|
echo "[INFO] using SRC=$SRC"
|
|
|
|
|
cp -a "$SRC/overlay/." "$DEST/"
|
|
|
|
|
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/"
|
2026-04-30 03:43:33 +01:00
|
|
|
%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
|