User Tools

Site Tools


notes:linux_automatic_network_install

This is an old revision of the document!


Linux Automatic Network Install

General outline:

  • PXE boot server with support for “legacy” BIOS and EFI boot; most VMs use “legacy” and most recent equipment uses EFI
  • HTTP server for EL (it doesn't support downloading a kickstart file from TFTP server, what a shame)
  • A set of boot images and minimal autoinstall files for Debian (at least, Bookworm) and EL (at least, Oracle Linux 8)

dnsmasq

The default Debian's dnsmasq configuration can use the base configuration and the drop directory. We opt to use the latter.

The most configuration is /etc/dnsmasq.d/base.conf:

/etc/dnsmasq.d/base.conf
no-dhcp-interface = tun0

server = 10.226.130.130
server = 10.226.130.131
no-resolv

domain = test.ucom.am, 172.31.1.0/24,   local
domain = test.ucom.am, 172.31.255.0/24, local
domain-needed
expand-hosts

# no dynamic allocation for DHCP service on this subnet; static allocation via dhcp-host will still be possible
dhcp-range = 192.168.205.224, static
dhcp-range = 172.31.255.0,    static

# allocate dynamically from this subnet
dhcp-range = 172.31.1.34, 172.31.1.62, 1h

dhcp-authoritative
dhcp-option = option:ntp-server, 10.226.130.130, 10.226.130.131

dhcp-hostsfile = /srv/dhcp-hostsfile.cfg

enable-tftp
tftp-root = /srv/tftp

dhcp-match = set:bios, option:client-arch,  0
dhcp-match = set:uefi, option:client-arch,  7
dhcp-match = set:uefi, option:client-arch,  9
dhcp-match = set:http, option:client-arch, 16

dhcp-boot = tag:bios, pxelinux.0
dhcp-boot = tag:uefi, bootx64.efi

#pxe-prompt = "Select a system to boot"
#pxe-prompt = "Press F8 for menu.", 60
#pxe-service = x86PC, "Boot from local disk"
#pxe-service = x86PC, "Run pxelinux", pxelinux

log-queries
log-dhcp

It references the /srv/dhcp-hostsfile.cfg where we can match certain MACs to IP addresses and names. This is mostly convenient for networks defined as “static DHCP ranges” above, since this way only hosts listed in the hostsfile will be provided a service. Also we can put other hosts there, for example, VMs, to fix IP addresses. Example contents is:

/srv/dhcp-hostsfile.cfg
BC:24:11:51:CF:FC, 172.31.1.5,  docker-vm
BC:24:11:70:C7:44, 172.31.1.6,  docker-ct
BC:24:11:4B:AE:DD, 172.31.1.4,  test-pve
BC:24:11:D4:97:9C, 172.31.1.27, hpprobook-image
BC:24:11:C9:B6:69, 172.31.1.7,  gns3
BC:24:11:28:81:76, 172.31.1.28, test-lvm

Also the static hosts may be defined in a sidecar file living in /etc/dnsmasq.d/:

/etc/dnsmasq.d/dhcp-static-hosts.conf
dhcp-host = 38:ea:a7:33:b5:98, 38:ea:a7:33:b5:99, 172.31.255.5,  vh-e1-b5
dhcp-host = 38:ea:a7:32:40:7c, 38:ea:a7:32:40:7d, 172.31.255.6,  vh-e1-b6
dhcp-host = 38:ea:a7:91:77:a8, 38:ea:a7:91:77:a9, 172.31.255.13, vh-e1-b13
dhcp-host = 38:ea:a7:91:76:44, 38:ea:a7:91:76:45, 172.31.255.14, vh-e1-b14

I put auxiliary DNS records into a separate file too:

-
cname = boot.test.ucom.am, vmgw.test.ucom.am

Mini HTTPD

Needed for EL variants to be able to run installer from the network. We only set data_dir=/srv/tftp in /etc/mini-httpd.conf; this directory is already served by TFTP; we can use a separate directory, but this setup feels simpler.

Debian: preseed

Debian conveniently maintains all the required bits for the netboot as an archive distributed through its mirrors, available, for example, here. From it, we need only two files (which can be also downloaded separately):

File Target Description
debian-installer/amd64/initrd.gz /srv/tftp/debian-bookworm/initrd.gz initramfs
debian-installer/amd64/linux /srv/tftp/debian-bookworm/linux kernel

Also need to create a bootloader configuration as /srv/tftp/pxelinux.cfg/debian-bookworm and a preseed file as /srv/tftp/debian-bookworm/preseed-noswap.cfg.

Bootloader configuration

/srv/tftp/pxelinux.cfg/debian-bookworm
default debian-bookworm-auto
timeout 0

label debian-bookworm-auto
    kernel debian-bookworm/linux
    append priority=critical initrd=debian-bookworm/initrd.gz debian-installer/language=en debian-installer/country=AM debian-installer/locale=ru_RU.UTF-8 keyboard-configuration/xkb-keymap=ru netcfg/get_hostname=install keyboard-configuration/optionscode=grp:caps_lock_toggle,grp_led:scroll preseed/url=tftp://boot.test.ucom.am/debian-bookworm/preseed-noswap.cfg

Example preseed file

Works for Bullseye too (it was actually originally developed for Bullseye, but worked with Bookworm like a charm)!

/srv/tftp/debian-bookworm/preseed-noswap.cfg
#_preseed_V1

# Preseeding only locale sets language, country and locale.

# For network booting, this comes too late; one needs to put those into command line,
# and the language there should be "en" or it will ask about it on the terminal
d-i debian-installer/language string ru
d-i debian-installer/country string AM
d-i debian-installer/locale string ru_RU.UTF-8
d-i localechooser/supported-locales multiselect ru_RU.UTF-8

# Keyboard selection.
d-i console-setup/ask_detect boolean false
d-i keyboard-configuration/xkb-keymap select ru
d-i keyboard-configuration/optionscode string grp:caps_toggle,lv3:ralt_switch,compose:rctrl,grp_led:scroll
d-i keyboard-configuration/layoutcode string us,ru
d-i keyboard-configuration/variantcode string ,
d-i keyboard-configuration/toggle select Caps Lock
d-i keyboard-configuration/altgr select Right Alt (AltGr)
d-i keyboard-configuration/compose select Right Control

### Clock and time zone setup
d-i clock-setup/utc boolean true
d-i time/zone string Asia/Yerevan

### Mirror settings
# If you select ftp, the mirror/country string does not need to be set.
d-i mirror/country string AM
d-i mirror/http/directory string /debian/
d-i mirror/http/hostname string deb.debian.org
d-i mirror/https/hostname string deb.debian.org
d-i mirror/http/mirror select deb.debian.org
d-i mirror/https/mirror select deb.debian.org
#d-i mirror/http/proxy string http://gw:8118/
#d-i mirror/https/proxy string http://gw:8118/

### Partitioning
d-i partman-auto/method string regular
d-i partman-auto/disk string /dev/sda
d-i partman-auto/expert_recipe string system-disk ::          \
              2047 0 -1 ext4                                  \
                      $primary{ }                             \
                      method{ format } format{ }              \
                      use_filesystem{ } filesystem{ ext4 }    \
                      mountpoint{ / }                         \
              .                                               \

# empty line above is REQUIRED due to continuation

# This makes partman automatically partition without confirmation.
d-i partman-partitioning/confirm_write_new_label boolean true
d-i partman/choose_partition select finish
d-i partman/confirm boolean true
d-i partman/confirm_nooverwrite boolean true

# Skip question about not having swap partition
partman-basicfilesystems partman-basicfilesystems/no_swap boolean false

### Account setup
# Set root password encrypted using a crypt(3) hash
#d-i passwd/root-password-crypted password $6$Ljketui4$hSnALWF8hKnbaWZpkj6xtx7PzWdMdgTJL7cdvfrj5byHq1BVp0KBxQbkKm5O9onjdwyKPmz3W22F.Q

# Set root with no password; the login will be possible with SSH key
d-i passwd/root-password-crypted password *

# Don't disable a root login
d-i passwd/root-login boolean true

# Skip a user creation
d-i passwd/make-user boolean false

# Or make user with known passord
#d-i passwd/user-uid string 1000
#d-i passwd/user-fullname string ${var.ssh_fullname}
#d-i passwd/username string ${var.ssh_username}
#d-i passwd/user-password password ${var.ssh_password}
#d-i passwd/user-password-again password ${var.ssh_password}
#d-i user-setup/allow-password-weak boolean true
#d-i user-setup/encrypt-home boolean false

### Package selection
d-i hw-detect/load_media boolean false
apt-cdrom-setup apt-setup/cdrom/set-first boolean false

#tasksel tasksel/first standard
tasksel tasksel/first multiselect standard, ssh-server
#d-i pkgsel/include string openssh-server qemu-guest-agent
d-i pkgsel/include string openssh-server sudo mc
d-i pkgsel/install-language-support boolean false

# disable automatic package updates
d-i pkgsel/update-policy select none
d-i pkgsel/upgrade select full-upgrade

# disable popularity contest
d-i popularity-contest/participate boolean false

# choose cloud kernel and minimum initramfs
bootstrap-base base-installer/initramfs-tools/driver-policy select  dep
bootstrap-base base-installer/kernel/linux/initramfs-tools/driver-policy string dep
bootstrap-base base-installer/kernel/image select  linux-image-cloud-amd64

### Bootloader
# This is fairly safe to set, it makes grub install automatically to the MBR
# if no other operating system is detected on the machine.
d-i grub-installer/only_debian boolean true

# This one makes grub-installer install to the MBR if it also finds some other
# OS, which is less safe as it might not be able to boot that other OS.
d-i grub-installer/with_other_os boolean true

# Avoid a question!
grub-installer grub-installer/bootdev string /dev/sda

# Avoid that last message about the install being complete, just reboot when finished
d-i finish-install/reboot_in_progress note

### Add SSH key for root
d-i preseed/late_command string \
  mkdir -p -m 700 /target/root/.ssh; \
  echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAKQCaZovi1a1UKy6Az3JSFP/3P4tP3ReknM//5eoOvk merlin@uc-s4m75657" > /target/root/.ssh/authorized_keys; \
  in-target chown --recursive root:root /root/.ssh; \
  in-target chmod 0600 /root/.ssh/authorized_keys;

Additional documentation

Enterprise Linux: kickstart

Oddly enough, OL8 installs with root enabled SSH with password by default. I guess we should not set any password for root, disable the password authentication (change to PermitRootLogin: without-password) and set a key in a %post section.

Need to consider which else packages may be omitted.

A directory tree

For Oracle Linux, the best is to obtain a “Boot UEK” ISO image, approx. 1G of size (obviously, the more “enterpriseish” is the system, the less efficient it is).

We extract the following files:

File Target Description
images/install.img /srv/tftp/ol8u9/images/install.img SquashFS with the installer
images/pxeboot/initrd.img /srv/tftp/ol8u9/initrd.img initramfs
images/pxeboot/vmlinuz /srv/tftp/ol8u9/vmlinuz kernel

Also need to create a bootloader configuration as /srv/tftp/pxelinux.cfg/ol8u9 and a kickstart file as /srv/tftp/ol8u9/ks.cfg (see below for examples). Since installer can't obtain components from TFTP server, we need a HTTP server to serve a kickstart file and a large squashfs image; technically, they may be placed elsewhere, but for simplicity I keep a single tree and make it available both via TFTP and HTTP.

Bootloader configuration

/srv/tftp/pxelinux.cfg/ol8u9
default ol8u9

label ol8u9
kernel ol8u9/vmlinuz
append initrd=ol8u9/initrd.img inst.repo=http://vmgw/ol8u9 inst.ks.sendmac inst.ks=http://vmgw/ol8u9/ks.cfg
# it will append .../images/install.img or .../LiveOS/squashfs.img

A complete working kickstart file

/srv/tftp/ol8u9/ks.cfg
#platform=x86, AMD64, or Intel EM64T
#version=OL8

# Firewall configuration
firewall --enabled --service=ssh

# Use Oracle Linux yum server repositories as installation source
repo --name="ol8_AppStream" --baseurl="https://yum.oracle.com/repo/OracleLinux/OL8/appstream/x86_64/"
repo --name="ol8_UEKR7" --baseurl="https://yum.oracle.com/repo/OracleLinux/OL8/UEKR7/x86_64/"
url --url="https://yum.oracle.com/repo/OracleLinux/OL8/baseos/latest/x86_64"

# Root password
#rootpw --iscrypted SHA512_password_hash
rootpw ...

# Use text only install
skipx
text
firstboot --disable
reboot --eject

# Keyboard layouts
keyboard --vckeymap=us --xlayouts='us'

# System language
lang en_US.UTF-8
# Note: problems with console font if using anything else

## SELinux configuration
#selinux --enforcing

## Installation logging level
#logging --level=info

# System timezone
timezone Asia/Yerevan

# Network information
network  --bootproto=dhcp --onboot=yes --hostname=test-ol8

# System bootloader configuration
bootloader --location=mbr --boot-drive=sda

## Non-administrative user
#user --name=user --homedir=/home/user --password=SHA512_password_hash --iscrypted

# Partition information
clearpart --all --initlabel --drives=sda
# NO SANE SERVER SYSTEM COULD EVER NEED MORE THAN 2G OF SWAP
part  swap --size 2047 --ondisk sda
part / --fstype ext4 --size 1 --grow --ondisk sda

# Disable kdump by default, frees up some memory
%addon com_redhat_kdump --disable
%end

services --disabled="kdump"

# Minimal install with a few convenience packages
%packages
@core
qemu-guest-agent
tmux
mc

-iwl7260-firmware
-iwl6000-firmware
-iwl2030-firmware
-iwl1000-firmware
-iwlax2xx-firmware
-iwl6000g2a-firmware
-iwl5150-firmware
-iwl3160-firmware
-iwl2000-firmware
-iwl105-firmware
-iwl100-firmware
-iwl6050-firmware
-iwl5000-firmware
-iwl135-firmware

-plymouth

-rhnsd
-rhn-setup
-python3-dnf-plugin-spacewalk
-dnf-plugin-spacewalk
-python3-rhn-client-tools
-rhn-client-tools
-rhnlib

-sssd-client
-sssd-common
-sssd-kcm

-btrfs-progs
-bcache-tools
%end

%post
mkdir /root/.ssh
echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXg9044dPzASa21RzPZAfN06/vZGAQOHGTmQcPc0fxEd6XFEJKcNwYJy0WRAY6tB1b3UcJeE7+lUjLJORrv4rs0L75qKoucJ+s1b9IegABs4qCW/A6sbanPHI3w7Lw6DYLXVCA1nXqpCnlhjlS3O6KBfbLo1jRAK10v9F0HTGWLm1lN05PT6ItL9WnQ88nrsZ/ON2bC5JyDL/CUxeV9qXIWIelFYkNoGjUM+baoMOb2N7ytuZA17qTkjZTRTQrCgJq19nu2el8/OYdUoIYDDm1ZJVQ/ahebtuobEFyTVMO2SGoL5YgKWHo8P/yCKuN3iWDcu6atwj+JjBjhrqSOxIN merlin@uc-s4m75657" > /root/.ssh/authorized_keys
chmod 0700 /root/.ssh
chmod 0640 /root/.ssh/authorized_keys
%end

More documentation

notes/linux_automatic_network_install.1714745895.txt.gz · Last modified: by Nikita Kipriyanov