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 GUI oder TUI an.

Anaconda wandelt sich von Version zu Version stark und wird meist einfacher und klarer. Trotzdem hält sich das Gerücht, dass Anaconda ein DAU-Filter sei, da er an den entscheidenden Stellen nicht so intuitiv und für Linux-Einsteiger wenig geeignet ist.

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:

yum -y install pykickstart
ksvalidator /root/anaconda-ks.cfg

Ist die Kickstart-Datei vailde, beendet sich ksvalidator ohne Fehler.

Aufruf einer Kickstart-Installation (früher genügte die Angabe von ks=, heute muss es inst.ks= heissen):

boot: linux inst.ks=https://www.example.com/ks/mykickstart.cfg

Weiterführende Links

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, drückt man im ersten Installations-Screen von RHEL die Taste Esc, gelangt so in den Kommandozeilenmodus und tippt:

linux ks=http://webserver/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 ks=http://webserver/ks.cfg ksdevice=eth1

Möchte man, dass Anaconda IP-Adresse und Netzmaske per Übergabe konfiguriert, verwendet man z.B.

linux ks=http://webserver/ks.cfg append hostname=host.example.com ip=192.0.2.74 netmask=255.255.255.0 dns=1.1.1.1,1.0.0.1 gw=192.0.2.1 ksdevice=ens10

Bemerkung

Wer auf den grafischen Installer verzichten möchte oder muss, kann während der Installation einen Text-only Modus erzwingen. Dazu im Installations-Menü die ESC-Taste drücken und auf der Kommandozeile den Befehl linux text eingeben. Man beachte, dass so allerdings nur ein Minimal-System ohne aktive Netzwerkkarten installiert wird. Der erweiterte Befehl linux text asknetwork installiert und aktiviert diese zusätzlich. 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 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:

# System authorization information
auth --enableshadow --passalgo=sha512

# GUI/TUI: Use graphical install
graphical

# GUI/TUI: Use textual install
text

# Installation Media: Use CDROM installation media
cdrom

# Installation Media: Use hard drive installation media
harddrive --dir=None --partition=/dev/mapper/live-base

# Installation Media: Use HTTP or FTP
url --url="http://10.80.32.58/iso"

# System Timezone
timezone Europe/Zurich --utc

# System Timezone
timezone Europe/Zurich --isUtc --nontp

# 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.168.122.1 --ip=192.168.122.111 --nameserver=1.0.0.1,1.1.1.1 --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: Don't set a root password
rootpw --lock

# System services
services --disabled="chronyd"
services --enabled="chronyd"

ignoredisk --only-use=vda,nvme0n1

# Partition clearing information
clearpart --none --initlabel

# System bootloader configuration
bootloader --append=" crashkernel=auto" --location=mbr --boot-drive=vda

# Disk: Automatic Partitioning
autopart --type=lvm

# 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 Ext4, on one partition
part /boot --fstype="ext4" --ondisk=nvme0n1 --size=1024
part /boot/efi --fstype="efi" --ondisk=nvme0n1 --size=600 --fsoptions="umask=0077,shortname=winnt"

# 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 (requires >= 4GB Disk)
volgroup centos --pesize=4096 pv.01

# LVM: LV - Unencrypted, XFS (/: use minimum 1024MB, but use more if available)
logvol swap  --fstype="swap" --recommended --name=swap --vgname=centos
logvol / --fstype="xfs" --grow --size=1024 --name=root --vgname=centos

# LVM: LV - Encrypted, Ext4
logvol swap --fstype="swap" --size=7857 --encrypted --luks-version=luks2 --name=swap --vgname=centos
logvol / --fstype="ext4" --size=967276 --encrypted --luks-version=luks2 --name=root --vgname=centos


# 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=centos --name=backup        --fsoptions="nodev"
logvol /var           --fstype="xfs" --size=6144     --vgname=centos --name=var           --fsoptions="nodev"
logvol /              --fstype="xfs" --size=8192     --vgname=centos --name=root
logvol /home          --fstype="xfs" --size=1024     --vgname=centos --name=home          --fsoptions="nodev"
logvol /tmp           --fstype="xfs" --size=1024     --vgname=centos --name=tmp           --fsoptions="nodev,noexec,nosuid"
logvol /var/log       --fstype="xfs" --size=1024     --vgname=centos --name=var_log       --fsoptions="nodev,noexec,nosuid"
logvol /var/log/audit --fstype="xfs" --size=512      --vgname=centos --name=var_log_audit --fsoptions="nodev,noexec,nosuid"
logvol /var/tmp       --fstype="xfs" --size=1024     --vgname=centos --name=var_tmp       --fsoptions="nodev,noexec,nosuid"
logvol swap           --fstype="swap" --recommended  --vgname=centos --name=swap


# Do not configure the X Window System
skipx

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

Tipp

Zur logvol-Direktive:

  • die alleinige Angabe von --size erzeugt ein LogVol mit genau der angegebenen Grösse, in MB

  • --grow bedeutet: nimm dir mindestens --size MB, und wenn mehr Platz da ist, nimm dir den ganzen Rest, aber maximal bis zur optionalen --maxsize, und vorheriger Berücksichtigung aller statischen Grössenangaben

  • wird --grow mehrfach verwendet, werden die einzelnen LV zu gleichen Teilen erstellt

  • statt mit --size, --maxsize und --grow, die Absolutwerte darstellen, lässt sich auch mit --percent arbeiten

%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
-xinetd
-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
#!/bin/sh
touch /tmp/disk-part.ks
# get disk size in GiB
DISKSIZE=$(parted -sm /dev/sda unit GiB print | grep -e "/dev/sda:[0-9]*GiB" | cut -d: -f2 | sed -e '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. Diese Beispiel legt unter anderem vordefinierte Public SSH-Keys auf der Maschine ab.

%post
yum -y install nano wget

#---- Install our SSH keys ----
mkdir -m0700 /root/.ssh/

cat <<EOF >/root/.ssh/authorized_keys
ssh-rsa AAAA...ddNKw== alice@linuxfabrik.ch
ssh-ed25519 AAAA...ehO 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 CentOS 8) setzt die Security-Anforderungen der Security-Profile der CIS, PCI-DSS, E8, 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=RHEL8

# 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: password
rootpw --iscrypted $6$YxsFrMkfy1PIRvCU$GJfIziATCSEOIaGLIrTa6aO1INNiNRforoW1k4N1AVju4FnCltEp6fOaq1GJdHTFaVuOmTpuTcrCAOXsXmtov1


# Do not configure the X Window System
skipx

# System services
services --disabled="chronyd"

# System timezone
timezone Europe/Zurich --isUtc --nontp


# We will restrict root login
# Add a user that can login and escalate privileges
# Plaintext password is: password
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
# --ssh     allow sshd service through the firewall
firewall --enabled --ssh

# State of SELinux on the installed system (optional)
# Defaults to enforcing
selinux --enforcing


# System bootloader configuration
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


# Boot Partition: Manual Partitioning with BIOS-/Legacy-Boot and XFS, on one partition
part /boot --fstype="xfs" --size=1024

# OS Partition
part pv.01 --fstype="lvmpv" --size=1024 --grow


# LVM: Volume Group
volgroup centos --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=centos --name=var           --fsoptions="nodev"
logvol /              --fstype="xfs" --size=8192     --vgname=centos --name=root
logvol /home          --fstype="xfs" --size=1024     --vgname=centos --name=home          --fsoptions="nodev"
logvol /tmp           --fstype="xfs" --size=1024     --vgname=centos --name=tmp           --fsoptions="nodev,noexec,nosuid"
logvol /var/log       --fstype="xfs" --size=1024     --vgname=centos --name=var_log       --fsoptions="nodev,noexec,nosuid"
logvol /var/log/audit --fstype="xfs" --size=512      --vgname=centos --name=var_log_audit --fsoptions="nodev,noexec,nosuid"
logvol /var/tmp       --fstype="xfs" --size=1024     --vgname=centos --name=var_tmp       --fsoptions="nodev,noexec,nosuid"
logvol swap           --fstype="swap" --recommended  --vgname=centos --name=swap


# Reboot after the installation is complete (optional)
# --eject   attempt to eject CD or DVD media before rebooting
reboot --eject


%packages
@^minimal-environment
%end


%pre

%end


%post
#---- Install SSH keys ----
mkdir -m0700 /root/.ssh/

cat <<EOF >/root/.ssh/authorized_keys
ssh-rsa AAAAB3Nz...
ssh-ed25519 AAAAC3Nz...
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/tmp liegen. Hier sind mindestens 384 MB empfohlen.

Built on 2024-02-26