Anaconda und Kickstart¶
Anaconda, welches hauptsächlich aus dem Hause Red Hat stammt, ist ein Installationsprogramm zur manuellen oder automatisierten Installation eines Linux-Betriebssystems (und nicht mit der freien wissenschaftlichen Python-Distribution mit dem gleichen Namen zu verwechseln). Anaconda bietet seinen Installationsassistenten je nach Wunsch oder System-Ressourcen per Web UI (Standard ab RHEL 10), GUI oder TUI an.
Anaconda wandelt sich von Version zu Version stark und wird meist einfacher und klarer. Mit RHEL 10 löst die browserbasierte Anaconda Web UI den bisherigen GTK-Installer als Standard ab. Der Text-Modus und die Kickstart-gestützte Installation funktionieren unverändert weiter.
Die Datei, um die Installation automatisiert durchzuführen (dem Installationsassistenten also die Antworten unterzuschieben), nennt sich Kickstart. Zu jeder Neuinstallation erzeugt Anaconda automatisch die Datei /root/anaconda-ks.cfg, die als Setup-Referenz dient, und mit der man das System unbeaufsichtigt wieder in den Ursprungszustand versetzen kann.
Eine Kickstart-Datei lässt sich wie folgt auf Korrektheit prüfen:
dnf --assumeyes install pykickstart
ksvalidator /root/anaconda-ks.cfg
Ist die Kickstart-Datei valide, beendet sich ksvalidator ohne Fehler. Mit --version RHEL10 lässt sich explizit gegen die RHEL-10-Syntax prüfen.
Aufruf einer Kickstart-Installation (früher genügte die Angabe von ks=, heute muss es inst.ks= heissen):
linux inst.ks=https://www.example.com/ks/mykickstart.cfg
Weiterführende Links
Kickstart-Referenz (pykickstart): https://pykickstart.readthedocs.io/en/latest/kickstart-docs.html
RHEL 10 Installations-Guide: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/10/html/interactively_installing_rhel_from_installation_media/
RHEL 10 Boot-Optionen: https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/10/html/boot_options_for_rhel_installer/
Kickstart-Datei¶
Kickstart-Dateien werden praktischerweise auf einem Webserver abgelegt. Zusätzlich hat man so die Möglichkeit, die Dateien auch dynamisch zu generieren.
Um eine automatisierte Installation durchzuführen, im GRUB-Menü des Installers E drücken, die gewünschten Parameter an die linux-Zeile anhängen und mit Ctrl-X booten. Seit RHEL 8 verwendet GRUB2 im BIOS- wie im UEFI-Modus die linux- und initrd-Kommandos (die früheren linuxefi/initrdefi-Varianten gibt es nicht mehr):
linux inst.ks=https://example.com/ks.cfg
Das setzt voraus, dass das System über die primäre Netzwerkkarte dynamisch eine IP-Adresse zugewiesen bekommt, mit der es auf den angegebenen Webserver zugreifen kann (statt des Namens des Webservers empfiehlt es sich, dessen IP-Adresse zu verwenden, um Namensauflösungsproblemen vorzubeugen). Falls das System über mehrere Netzwerkkarten verfügt, will Anaconda wissen, über welche es seine Netzwerkeinstellungen beziehen soll. Um diese Unterbrechung zu verhindern, hilft die direkte Angabe der primär zu verwendenden Netzwerkkarte:
linux inst.ks=https://example.com/ks.cfg ip=ens33:dhcp
Möchte man, dass Anaconda IP-Adresse und Netzmaske per Übergabe konfiguriert, verwendet man z.B.
linux inst.ks=https://example.com/ks.cfg ip=192.0.2.62::192.0.2.1:255.255.255.0:server.example.com:ens33:none nameserver=192.0.2.100 nameserver=192.0.2.101
Liegt die Kickstart-Datei auf einem HTTPS-Server mit selbstsigniertem Zertifikat, lässt sich die Zertifikatsprüfung mit inst.noverifyssl deaktivieren:
linux inst.ks=https://example.com/ks.cfg inst.noverifyssl
Bemerkung
Wer auf den grafischen Installer (bzw. ab RHEL 10 auf die Web UI) verzichten möchte oder muss, kann während der Installation einen Text-only-Modus erzwingen. Dazu im Installations-Menü die E-Taste drücken und inst.text an die linux-Zeile anhängen. Man beachte, dass so allerdings nur ein Minimal-System ohne aktive Netzwerkkarten installiert wird. Mit zusätzlichem inst.asknetwork wird die Netzwerkkarte während der Installation aktiviert. Die Installation solch eines Servers nimmt weniger als 5 Minuten in Anspruch.
Wird ein USB-Stick verwendet, kommt es auf einigen Maschinen vor, dass Anaconda das Betriebssystem unbedingt auf dem Stick installieren möchte (der Stick wird beispielsweise als /dev/sda erkannt, so dass man im Kickstart-File mit --driveorder=sdb,sda arbeiten muss). Der Parameter nousbstorage verhindert solche unschönen Workarounds, die zudem nicht zuverlässig und überall funktionieren:
linux nousbstorage ...
Falls das Kickstart-File auf einem CD-ROM/DVD liegt:
linux inst.ks=cdrom:/install.cfg
Allgemeiner Aufbau¶
Innerhalb der einzelnen Sektionen kommt es seltenst auf die Reihenfolge der Kommandos an. Im Zweifel Doku zu Rate ziehen.
# mandatory sections
command section
%packages section
%end
# optional sections
%pre
%end
%pre-install
%end
%post
%end
%onerror
%end
%traceback
%end
Command Section¶
Sammelsurium an Befehlen in der Command Section, aus dem Alltag:
# GUI/Web UI: Use graphical install (default on RHEL 10)
graphical
# GUI/TUI: Use textual install
text
# Installation Media: Use CDROM installation media
cdrom
# Installation Media: Use hard drive installation media
harddrive --partition=LABEL=RHEL-10-0-0-BaseOS-x86_64 --dir=/
# Installation Media: Use HTTP
url --url="http://198.51.100.10/rhel10/"
# Installation Media: Use an NFS share
nfs --server=198.51.100.10 --dir=/exports/rhel10
# Register with Red Hat Subscription Manager (RHEL only)
rhsm --organization=1234567 --activation-key=my-activation-key --connect-to-insights
# System Timezone (modern form: chrony via timesource)
timezone Europe/Zurich --utc
timesource --ntp-server=0.ch.pool.ntp.org
timesource --ntp-server=1.ch.pool.ntp.org
# System Timezone: Disable NTP entirely
timezone Europe/Zurich --utc
timesource --ntp-disable
# Keyboard Layout: Swiss German
keyboard --vckeymap=ch --xlayouts='ch'
# Keyboard Layout: US
keyboard --vckeymap=us --xlayouts='us'
# System Language
lang en_US.UTF-8
# Network: Set Hostname
network --hostname=localhost.localdomain
# Network: Static
network --bootproto=static --device=eth0 --gateway=192.0.2.1 --ip=192.0.2.62 --nameserver=192.0.2.100,192.0.2.101 --netmask=255.255.255.0 --ipv6=auto --activate
# Network: DHCP
network --bootproto=dhcp --device=enp1s0 --ipv6=auto --activate
# Run the Setup Agent on first boot
firstboot --enable
# Root password: Set root password
rootpw --iscrypted $6$SClI7oo...Mi/waVA3Frinvz0
# Root password: Lock the root account (then create an admin user via `user`)
rootpw --lock
# Root password: Allow SSH login as root with password (disabled by default since RHEL 9)
rootpw --iscrypted --allow-ssh $6$SClI7oo...Mi/waVA3Frinvz0
# System services
services --enabled="chronyd,sshd"
services --disabled="kdump"
# Only use the listed disks for installation
ignoredisk --only-use=vda,nvme0n1
# Partition clearing information
clearpart --none --initlabel
# System bootloader configuration
# On UEFI systems omit --location; Anaconda places the bootloader in the EFI system partition.
bootloader --append="crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M" --location=mbr --boot-drive=vda
# Disk: Automatic Partitioning
autopart --type=lvm
# Disk: Create platform-specific required partitions automatically (biosboot, /boot/efi, PReP)
reqpart --add-boot
# Boot Partition: Manual Partitioning with BIOS-/Legacy-Boot and XFS, on one partition
part /boot --fstype="xfs" --ondisk=sda --size=1024
part pv.01 --fstype="lvmpv" --ondisk=sda --size=1024 --grow
# Boot Partition: Manual Partitioning with UEFI-Boot and XFS
part /boot/efi --fstype="efi" --ondisk=nvme0n1 --size=600 --fsoptions="umask=0077,shortname=winnt"
part /boot --fstype="xfs" --ondisk=nvme0n1 --size=1024
# OS Partition
part pv.01 --fstype="lvmpv" --ondisk=nvme0n1 --size=1024 --grow
# Include a file that was created in Pre-Section
%include /tmp/disk-part.ks
# LVM: Volume Group (pesize defaults to 4 MiB, explicit here for clarity)
volgroup rhel --pesize=4096 pv.01
# LVM: LV - Unencrypted, XFS (/: use minimum 1024MB, but use more if available)
logvol swap --fstype="swap" --recommended --name=swap --vgname=rhel
logvol / --fstype="xfs" --grow --size=1024 --name=root --vgname=rhel
# LVM: LV - Encrypted with LUKS2, Ext4
logvol swap --fstype="swap" --size=7857 --encrypted --luks-version=luks2 --name=swap --vgname=rhel
logvol / --fstype="ext4" --size=967276 --encrypted --luks-version=luks2 --name=root --vgname=rhel
# LVM: LV - CIS-compliant (/home, /tmp, /var, /var/log, /var/log/audit and /var/tmp on their own partitions)
# all sizes are in MB
# the sizes of the LVM LV's below require a disk with 30 GB
# Anaconda creates the LVs in reverse order; LVs listed at the end will be created first
logvol /backup --fstype="xfs" --size=6144 --vgname=rhel --name=backup --fsoptions="nodev"
logvol /var --fstype="xfs" --size=6144 --vgname=rhel --name=var --fsoptions="nodev"
logvol / --fstype="xfs" --size=8192 --vgname=rhel --name=root
logvol /home --fstype="xfs" --size=1024 --vgname=rhel --name=home --fsoptions="nodev"
logvol /tmp --fstype="xfs" --size=1024 --vgname=rhel --name=tmp --fsoptions="nodev,noexec,nosuid"
logvol /var/log --fstype="xfs" --size=1024 --vgname=rhel --name=var_log --fsoptions="nodev,noexec,nosuid"
logvol /var/log/audit --fstype="xfs" --size=512 --vgname=rhel --name=var_log_audit --fsoptions="nodev,noexec,nosuid"
logvol /var/tmp --fstype="xfs" --size=1024 --vgname=rhel --name=var_tmp --fsoptions="nodev,noexec,nosuid"
logvol swap --fstype="swap" --recommended --vgname=rhel --name=swap
# Do not configure the X Window System
skipx
# Local repo on the installation medium
repo --name="AppStream" --baseurl=file:///run/install/repo/AppStream
# Do something at the end of the setup
shutdown
%addon com_redhat_kdump --enable --reserve-mb='auto'
%end
%addon com_redhat_kdump --disable --reserve-mb='auto'
%end
%addon org_fedora_oscap
content-type = scap-security-guide
profile = xccdf_org.ssgproject.content_profile_cis
%end
%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end
Bemerkung
Der aus RHEL 6/7 bekannte Befehl auth (bzw. authconfig) wurde mit RHEL 8 entfernt und wird in RHEL 10 stillschweigend ignoriert. Wer PAM/NSS anpassen will, macht das in %post per authselect select <profile>.
Tipp
Zur logvol-Direktive:
die alleinige Angabe von
--sizeerzeugt ein LogVol mit genau der angegebenen Grösse, in MB--growbedeutet: nimm dir mindestens--sizeMB, und wenn mehr Platz da ist, nimm dir den ganzen Rest, aber maximal bis zur optionalen--maxsize, und unter Berücksichtigung aller statischen Grössenangabenwird
--growmehrfach verwendet, werden die einzelnen LV zu gleichen Teilen erstelltstatt mit
--size,--maxsizeund--grow, die Absolutwerte darstellen, lässt sich auch mit--percentarbeiten
%packages Section¶
%packages
@^minimal-environment
aide
audit
chrony
firewalld
kexec-tools
libselinux
openscap
openscap-scanner
rsyslog
scap-security-guide
sudo
-mcstrans
-openldap-clients
-setroubleshoot
-squid
-telnet
-xorg-x11-server-common
-ypbind
%end
%pre Section¶
Wird vor dem Start des Setups ausgeführt. Im Beispiel wird eine Kickstart-Datei mit Informationen zu Disk-Grössen dynamisch generiert und in der Command-Section per %include eingebunden.
%pre --interpreter=/usr/bin/bash
touch /tmp/disk-part.ks
# get disk size in GiB
DISKSIZE=$(parted --script --machine /dev/sda unit GiB print | grep --extended-regexp "/dev/sda:[0-9]*GiB" | cut --delimiter=: --fields=2 | sed --expression='s/GiB$//')
if [ ! -e /sys/firmware/efi ]; then
# boot mode: BIOS
if [ "${DISKSIZE}" -gt 2000 ]; then
# and GPT needed -> create biosboot
echo "part biosboot --fstype=biosboot --size=1 --ondisk=sda" > /tmp/disk-part.ks
fi
fi
%end
%post Section¶
Die %post-Sektion wird nach der Betriebssystem-Installation und vor dem Poweroff/Reboot ausgeführt. Dieses Beispiel legt unter anderem vordefinierte Public SSH-Keys auf der Maschine ab.
%post --interpreter=/usr/bin/bash --log=/root/ks-post.log
dnf --assumeyes install nano wget
#---- Install our SSH keys ----
mkdir --mode=0700 /root/.ssh/
cat <<EOF >/root/.ssh/authorized_keys
ssh-ed25519 AAAA...ehO alice@linuxfabrik.ch
ssh-ed25519 AAAA...xYz bob@linuxfabrik.ch
EOF
### set permissions
chmod 0600 /root/.ssh/authorized_keys
### fix selinux context
restorecon -R /root/.ssh/
%end
Gehärtete Kickstart-Datei¶
Diese Kickstart-Datei (getestet mit RHEL 10) setzt die Security-Anforderungen der Security-Profile der CIS, PCI-DSS, Essential Eight, OSPP, STIG etc. um. Die Haupt-Anforderung liegt im Partitionierungsschema. Nachträgliche System-Anpassungen nimmt man am besten per Ansible oder Shell-Skript vor:
#version=RHEL10
# Use text mode install
text
# Run the Setup Agent on first boot
firstboot --enable
# Keyboard layouts
keyboard --vckeymap=ch --xlayouts='ch'
# System language
lang en_US.UTF-8
# Root password
# Plaintext password is: linuxfabrik
rootpw --iscrypted $6$YxsFrMkfy1PIRvCU$GJfIziATCSEOIaGLIrTa6aO1INNiNRforoW1k4N1AVju4FnCltEp6fOaq1GJdHTFaVuOmTpuTcrCAOXsXmtov1
# Do not configure the X Window System
skipx
# System services
services --enabled="chronyd,sshd,firewalld,auditd"
# System timezone
timezone Europe/Zurich --utc
timesource --ntp-server=0.ch.pool.ntp.org
timesource --ntp-server=1.ch.pool.ntp.org
# We will restrict root login
# Add a user that can login and escalate privileges
# Plaintext password is: linuxfabrik
user --name=linuxfabrik --groups=wheel --iscrypted --password=$6$YxsFrMkfy1PIRvCU$GJfIziATCSEOIaGLIrTa6aO1INNiNRforoW1k4N1AVju4FnCltEp6fOaq1GJdHTFaVuOmTpuTcrCAOXsXmtov1
# Configure firewall settings for the system (optional)
# --enabled reject incoming connections that are not in response to outbound requests
# --service=ssh allow sshd through the firewall
firewall --enabled --service=ssh
# State of SELinux on the installed system (optional)
# Defaults to enforcing
selinux --enforcing
# System bootloader configuration
# On UEFI systems omit --location; Anaconda places the bootloader in the EFI system partition.
bootloader --location=mbr --append="audit=1 audit_backlog_limit=8192 slub_debug=P page_poison=1 vsyscall=none"
# Initialize (format) all disks (optional)
zerombr
# The following partition layout scheme assumes disk of size 20GB or larger
# Modify size of partitions appropriately to reflect actual machine's hardware
#
# Remove Linux partitions from the system prior to creating new ones (optional)
# --linux erase all Linux partitions
# --initlabel initialize the disk label to the default based on the underlying architecture
clearpart --linux --initlabel
# Create required platform-specific partitions automatically (biosboot on BIOS/GPT, /boot/efi on UEFI)
reqpart --add-boot
# OS Partition
part pv.01 --fstype="lvmpv" --size=1024 --grow
# LVM: Volume Group
volgroup rhel --pesize=4096 pv.01
# LVM: LV - CIS-compliant (/home, /tmp, /var, /var/log, /var/log/audit and /var/tmp on their own partitions)
# all sizes are in MB
# the sizes of the LVM LV's below require a disk with 30 GB
# Anaconda creates the LVs in reverse order; LVs listed at the end will be created first
logvol /var --fstype="xfs" --size=6144 --vgname=rhel --name=var --fsoptions="nodev"
logvol / --fstype="xfs" --size=8192 --vgname=rhel --name=root
logvol /home --fstype="xfs" --size=1024 --vgname=rhel --name=home --fsoptions="nodev"
logvol /tmp --fstype="xfs" --size=1024 --vgname=rhel --name=tmp --fsoptions="nodev,noexec,nosuid"
logvol /var/log --fstype="xfs" --size=1024 --vgname=rhel --name=var_log --fsoptions="nodev,noexec,nosuid"
logvol /var/log/audit --fstype="xfs" --size=512 --vgname=rhel --name=var_log_audit --fsoptions="nodev,noexec,nosuid"
logvol /var/tmp --fstype="xfs" --size=1024 --vgname=rhel --name=var_tmp --fsoptions="nodev,noexec,nosuid"
logvol swap --fstype="swap" --recommended --vgname=rhel --name=swap
# Reboot after the installation is complete (optional)
# --eject attempt to eject CD or DVD media before rebooting
reboot --eject
%packages
@^minimal-environment
aide
audit
chrony
firewalld
openscap-scanner
scap-security-guide
sudo
%end
%pre
%end
%post --interpreter=/usr/bin/bash --log=/root/ks-post.log
#---- Install SSH keys ----
mkdir --mode=0700 /root/.ssh/
cat <<EOF >/root/.ssh/authorized_keys
ssh-ed25519 AAAAC3Nz... alice@linuxfabrik.ch
ssh-ed25519 AAAAC3Nz... bob@linuxfabrik.ch
EOF
### set permissions
chmod 0600 /root/.ssh/authorized_keys
### fix up selinux context
restorecon -R /root/.ssh/
%end
Troubleshooting¶
- DNF error: Error in POSTTRANS scriptlet in rpm package kernel-core
Kann an zu wenig Platz für
/var/tmpliegen. Hier sind mindestens 384 MB empfohlen.ksvalidatormeldetUnknown command: authDas
auth-Kommando existiert seit RHEL 8 nicht mehr. Zeile entfernen und PAM/NSS stattdessen in%postperauthselectkonfigurieren.
Built on 2026-04-15