Cobbler (v3.3.7) Ubuntu Deployment Guide
This guide assumes that you have a Fedora 34 server or workstation system configured to run Cobbler v3.3.7 similarly to the Cobbler v3.3.7 Beginner’s guide.
Table of Contents
- Objective
- Cobbler Server Prep
- Ubuntu 20.04 PXE Deployment
- Ubuntu 22.04 PXE Deployment
- Ubuntu 24.04 PXE Deployment
- Tips & Troubleshooting
Objective
Starting where the Beginner’s guide left off, further configure the Cobbler v3.3.7 server to deploy the latest 3 releases of Ubuntu Server LTS (Ubuntu 20.04, 22.04, 24.04) via PXE network boot, using the same system and network environment. This guide assumes that you still have selinux
and firewalld
configured and enabled as described in the Beginner’s guide.
Caveats
-
Until the release of Ubuntu 20.04, Canonical used the same debian-installer from Debian, including the “preseed” autoinstallation model; starting with Ubuntu 20.04, Canonical switched to using their in-house
cloud-init
solution.-
Ubuntu did offer compatability/support with the debian-installer/preseed autoinstallation model in the Ubuntu 20.04 Legacy release.
-
This guide only provides procedures for deploying Ubuntu systems using
cloud-init
.
-
Cobbler Server Prep
Cobbler v3.3.7 does not come with a sample template for the cloud-init
autoinstall files, so create that before getting started, as well as some Cobbler sync-triggers to correct the bootloader configurations for compatability with cloud-init
.
Dependencies
Create the cloud-init
autoinstall template with the following contents and save it to /var/lib/cobbler/templates/cloud-init_user-data
:
Cobbler Templates and Snippets are actually Python Cheetah templates, so be careful editing the files, especially the cheetah code preceded buy
#
#cloud-config
autoinstall:
version: 1
apt:
# even set to no/false, geoip lookup still happens
#geoip: no
preserve_sources_list: true
primary:
- arches: [amd64, i386]
uri: http://$http_server/cblr/links/$distro
# uri: http://us.archive.ubuntu.com/ubuntu
- arches: [default]
# uri: http://$http_server/cblr/links/$distro
uri: http://ports.ubuntu.com/ubuntu-ports
fallback: offline-install
identity:
$SNIPPET('cloud-init_hostname')
password: $default_password_crypted
realname: ubuntu
username: ubuntu
kernel:
package: linux-generic
keyboard:
layout: us
toggle: null
variant: ''
locale: en_US.UTF-8
$SNIPPET('cloud-init_network')
ssh:
allow-pw: true
install-server: true
storage:
layout:
name: lvm
sizing-policy: all
package_update: false
package_upgrade: false
late-commands:
## Figure out if we're automating OS installation for a system or a profile
#if $getVar('system_name','') != ''
#set $what = "system"
#else
#set $what = "profile"
#end if
- wget -O /target/tmp/autoinstall-user-data.yaml http://$http_server/cblr/svc/op/autoinstall/$what/$name
- chroot /target /bin/bash -s ssh-keygen -t rsa -b 2048 -m ssh2 -N "" -f /root/.ssh/id_rsa
# - rm /target/etc/apt/apt.conf.d/99needrestart # This prompt will prevent the apt command from completing
the
fallback: offline
option under the apt configuration will use the live CD (.iso file) as the source to install Ubuntu from if there is an issue connecting to a remote repo mirror, and was only introduced as of Ubuntu 22.04 release.
The above autoinstall template calls for 2 Cobbler snippets; create them with the following contents, in the file system location noted above the code-block:
/var/lib/cobbler/snippets/cloud-init_hostname
## start of cobbler network_config generated code
#if $getVar("system_name","") != ""
#if $hostname != ""
hostname: $hostname
#else
#set $myhostname = $getVar('name','').replace("_","-")
hostname: $myhostname
#end if
#else
## profile based install so just provide one interface for starters
#set $myhostname = $getVar('hostname',$getVar('name','cobbler')).replace("_","-")
hostname: $myhostname
#end if
/var/lib/cobbler/snippets/cloud-init_network
## start of cobbler network_config generated code
#if $getVar("system_name","") != ""
network:
ethernets:
#set ikeys = $interfaces.keys()
#import re
#for $iname in $ikeys
#set $idata = $interfaces[$iname]
## Ignore BMC interface
#if $idata["interface_type"].lower() == "bmc"
#continue
#end if
#end for
#for $iname in $ikeys
#set $idata = $interfaces[$iname]
#set $mac = $idata["mac_address"]
#set $static = $idata["static"]
#set $ip = $idata["ip_address"]
#set $netmask = $idata["netmask"]
#set $type = $idata["interface_type"]
## Ignore BMC interface
#if $type == "bmc"
#continue
#end if
#if $iname != "default":
#if $mac != "":
$iname:
match:
macaddress: $mac
#if $static == True:
#if $ip != "":
#if $netmask != "":
#set $mask = sum([bin(int(x)).count('1') for x in $netmask.split('.')])
dhcp4: false
addresses:
- $ip/$mask
#else
dhcp4: false
addresses:
- $ip/24
#end if
#end if
#if $gateway != "":
gateway4: $gateway
#end if
#if $name_servers and $name_servers[0] != "":
nameservers:
addresses:
#for $dns in $name_servers
- $dns
#end for
#end if
#else
dhcp4: true
#end if
#else
$iname:
#if $static == True:
#if $ip != "":
#if $netmask != "":
#set $mask = sum([bin(int(x)).count('1') for x in $netmask.split('.')])
dhcp4: false
addresses:
- $ip/$mask
#else
dhcp4: false
addresses:
- $ip/24
#end if
#end if
#if $gateway != "":
gateway4: $gateway
#end if
#if $name_servers and $name_servers[0] != "":
nameservers:
addresses:
#for $dns in $name_servers
- $dns
#end for
#end if
#else
dhcp4: true
#end if
#end if
#else
#if $mac != "":
$iname:
match:
macaddress: $mac
#if $static == True:
#if $ip != "":
#if $netmask != "":
#set $mask = sum([bin(int(x)).count('1') for x in $netmask.split('.')])
dhcp4: false
addresses:
- $ip/$mask
#else
dhcp4: false
addresses:
- $ip/24
#end if
#end if
#if $gateway != "":
gateway4: $gateway
#end if
#if $name_servers and $name_servers[0] != "":
nameservers:
addresses:
#for $dns in $name_servers
- $dns
#end for
#end if
#else
dhcp4: true
#end if
#else
$iname:
#if $static == True:
#if $ip != "":
#if $netmask != "":
#set $mask = sum([bin(int(x)).count('1') for x in $netmask.split('.')])
dhcp4: false
addresses:
- $ip/$mask
#else
dhcp4: false
addresses:
- $ip/24
#end if
#end if
#if $gateway != "":
gateway4: $gateway
#end if
#if $name_servers and $name_servers[0] != "":
nameservers:
addresses:
#for $dns in $name_servers
- $dns
#end for
#end if
#else
dhcp4: true
#end if
#end if
#end if
#end for
version: 2
#else
## profile based install so use DHCP
network:
ethernets:
eth0:
dhcp4: true
version: 2
#end if
This section should resemble the netplan network configuration standard to Ubuntu once generated.
Create 2 Cobbler sync-triggers to correct the GRUB and PXELINUX boot configurations to support Ubuntu cloud-init
installations, which will run each time the cobbler sync
action is performed:
/var/lib/cobbler/triggers/sync/post/fix-ubuntu-profiles-GRUB_PXE.sh
#!/bin/bash
for PROFILE in $(cobbler profile list); do
DIST=$(cobbler profile report --name $PROFILE | grep ^Distribution | awk {' print $3 '});
VER=$(cobbler distro report --name $DIST | grep "OS Version" | awk {' print $4 '});
[[ ($VER == "focal" || $VER == "jammy" || $VER == "noble") ]] || continue;
sed -i "s,auto-install/enable=true priority=critical netcfg/choose_interface=auto url=http://10.0.0.10/cblr/svc/op/autoinstall/profile/${PROFILE} hostname=.* domain=local.lan suite=${VER},," /var/lib/tftpboot/grub/x86_64_menu_items.cfg;
sed -i "s,auto-install/enable=true priority=critical netcfg/choose_interface=auto url=http://10.0.0.10/cblr/svc/op/autoinstall/profile/${PROFILE} hostname=.* domain=local.lan suite=${VER},," /var/lib/tftpboot/pxelinux.cfg/default;
DIST="" && VER="";
done
/var/lib/cobbler/triggers/sync/post/fix-ubuntu-systems-GRUB_PXE.sh
#!/bin/bash
for SYSTEM in $(cobbler system list); do
PROFILE=$(cobbler system report --name $SYSTEM | grep ^Profile | awk {' print $3 '})
DIST=$(cobbler profile report --name $PROFILE | grep ^Distribution | awk {' print $3 '});
VER=$(cobbler distro report --name $DIST | grep "OS Version" | awk {' print $4 '});
[[ ($VER == "focal" || $VER == "jammy" || $VER == "noble") ]] || continue;
MAC=$(cobbler system report --name $SYSTEM | grep "MAC Addr" | awk {' print $4 '})
sed -i "s,auto-install/enable=true priority=critical netcfg/choose_interface=auto url=http://10.0.0.10/cblr/svc/op/autoinstall/system/${SYSTEM} hostname=.* domain=local.lan suite=${VER},," /var/lib/tftpboot/grub/system/$MAC;
MAC=$(echo $MAC | sed 's,:,-,g');
sed -i "s,auto-install/enable=true priority=critical netcfg/choose_interface=auto url=http://10.0.0.10/cblr/svc/op/autoinstall/profile/${PROFILE} hostname=.* domain=local.lan suite=${VER},," /var/lib/tftpboot/pxelinux.cfg/01-$MAC;
PROFILE="" && DIST="" && VER="" && MAC="";
done
Mark the above 2 Cobbler sync-triggers as executable
chmod u+x /var/lib/cobbler/triggers/sync/post/fix-ubuntu-profiles-GRUB_PXE.sh
chmod u+x /var/lib/cobbler/triggers/sync/post/fix-ubuntu-systems-GRUB_PXE.sh
Download the latest 3 releases of Ubuntu Server LTS
cd ~/Downloads && wget https://releases.ubuntu.com/24.04/ubuntu-24.04.1-live-server-amd64.iso
cd ~/Downloads && wget https://releases.ubuntu.com/22.04/ubuntu-22.04.5-live-server-amd64.iso
cd ~/Downloads && wget https://releases.ubuntu.com/20.04/ubuntu-20.04.6-live-server-amd64.iso
Ubuntu 20.04 PXE Deployment
Mount the Ubuntu 20.04 live server installer and import to Cobbler, then copy the installation media to the public HTTP share
[ -d /mnt/Ubuntu] || mkdir /mnt/Ubuntu
mount -t iso9660 -o loop,ro ~/Downloads/ubuntu-20.04.6-live-server-amd64.iso /mnt/Ubuntu
cobbler import --name Ubuntu20 --path /mnt/Ubuntu
mkdir -p /var/www/cobbler/pub/cloud-init/Ubuntu20
cp ~/Downloads/ubuntu-20.04.6-live-server-amd64.iso /var/www/cobbler/pub/cloud-init/Ubuntu20/.
the PXE Client will not install Ubuntu from the local mirror @
/var/www/cobbler/distro_mirror
, and since thefallback: ofline-install
option was not available for Ubuntu 20.04cloud-init
, this distro REQUIRES AN INTERNET CONNECTION to install, as detailed in this guide.
Edit the kernel options for the new Cobbler Distro to install Ubuntu automatically by default:
cobbler distro edit --name Ubuntu20-casper-x86_64 --kernel-options 'root=/dev/ram0 ramdisk_size=1500000 ip=dhcp url=http://10.0.0.10/cblr/pub/cloud-init/Ubuntu20/ubuntu-20.04.6-live-server-amd64.iso autoinstall cloud-config-url=http://10.0.0.10/cblr/svc/op/autoinstall/profile/Ubuntu20-casper-x86_64'
alternatively, use the following kernel-options to install Ubuntu MANUALLY via PXE network boot
cobbler distro edit --name Ubuntu20-casper-x86_64 --kernel-options 'root=/dev/ram0 ramdisk_size=1500000 ip=dhcp url=http://10.0.0.10/cblr/pub/cloud-init/Ubuntu20/ubuntu-20.04.6-live-server-amd64.iso cloud-config-url=/dev/null'
More info on these configs in the Tips & Troubleshooting section below.
create a new autoinstall (cloud-init
) template from the cloud-init_user_data
file created above, and configure it as the autoinstallation template for the Ubuntu 20.04 Cobbler PROFILE
sed ':a;N;$!ba;s, uri: http://\$http_server/cblr/links/\$distro\n# uri: http://us.archive.ubuntu.com/ubuntu,# uri: http://\$http_server/cblr/links/\$distro\n uri: http://us.archive.ubuntu.com/ubuntu,' /var/lib/cobbler/templates/cloud-init_user-data | tee /var/lib/cobbler/templates/Ubuntu20_cloud-init_user-data
cobbler profile edit --name Ubuntu20-casper-x86_64 --autoinstall Ubuntu20_cloud-init_user-data
Create a new Cobbler System to install Ubuntu 20.04 automatically based on the system’s (PXE client’s) MAC address, replacing the “aa:bb:cc:dd:ee:ff” with the MAC address of your PXE client, and being sure not to use a duplicate MAC or IP addresse of any other Cobbler System as well as setting the kernel-options to match the Cobbler System’s name:
NAME="Ubuntu20-auto" && cobbler system add --name $NAME --profile Ubuntu20-casper-x86_64 --kernel-options "root=/dev/ram0 ramdisk_size=1500000 ip=dhcp url=http://10.0.0.10/cblr/pub/cloud-init/Ubuntu20/ubuntu-20.04.6-live-server-amd64.iso autoinstall cloud-config-url=http://10.0.0.10/cblr/svc/op/autoinstall/system/$NAME" --mac-address "aa:bb:cc:dd:ee:ff" --static true --ip-address "10.0.0.20" --netmask "255.255.255.0" --gateway "10.0.0.1" --name-servers "10.0.0.1 1.1.1.1 10.0.0.10" --hostname "Ubuntu20" --netboot-enabled true && NAME=""
Alternatively, configure the Cobbler System kernel-options to run as a MANUAL installation:
cobbler system add --name Ubuntu20 --profile Ubuntu20-casper-x86_64 --kernel-options 'root=/dev/ram0 ramdisk_size=1500000 ip=dhcp url=http://10.0.0.10/cblr/pub/cloud-init/Ubuntu20/ubuntu-20.04.6-live-server-amd64.iso autoinstall cloud-config-url=/dev/null' --mac-address "aa:bb:cc:dd:ee:ff"
Restart and sync up Cobbler
systemctl restart cobblerd && sleep 10
cobbler sync
The PXE Client VM can now be powered on, and should automatically boot to PXE and install Ubuntu 20.04 to the VM HDD using the “Ubuntu20_cloud-init_user-data” preseed template created above.
Ubuntu 22.04 PXE Deployment
Take similar steps as above to import and automatically deploy Ubuntu 22.04 LTS Server over PXE, using the original cloud-init_user-data
autoinstall template created above.
[ -d /mnt/Ubuntu ] || mkdir /mnt/Ubuntu
mount -t iso9660 -o loop,ro /home/fedora/Downloads/ubuntu-22.04.5-live-server-amd64.iso /mnt/Ubuntu
cobbler import --name Ubuntu22 --path /mnt/Ubuntu
mkdir -p /var/www/cobbler/pub/cloud-init/Ubuntu22
cp ~/Downloads/ubuntu-22.04.5-live-server-amd64.iso /var/www/cobbler/pub/cloud-init/Ubuntu22/.
cobbler distro edit --name Ubuntu22-casper-x86_64 --kernel-options 'root=/dev/ram0 ramdisk_size=1500000 ip=dhcp url=http://10.0.0.10/cblr/pub/cloud-init/Ubuntu22/ubuntu-22.04.5-live-server-amd64.iso autoinstall cloud-config-url=http://10.0.0.10/cblr/svc/op/autoinstall/profile/Ubuntu22-casper-x86_64'
cobbler profile edit --name Ubuntu22-casper-x86_64 --autoinstall cloud-init_user-data
NAME="Ubuntu22-auto" && cobbler system add --name $NAME --profile Ubuntu22-casper-x86_64 --kernel-options "root=/dev/ram0 ramdisk_size=1500000 ip=dhcp url=http://10.0.0.10/cblr/pub/cloud-init/Ubuntu22/ubuntu-22.04.5-live-server-amd64.iso autoinstall cloud-config-url=http://10.0.0.10/cblr/svc/op/autoinstall/system/$NAME" --mac-address "aa:bb:cc:dd:ee:ff" --static true --ip-address "10.0.0.22" --netmask "255.255.255.0" --gateway "10.0.0.1" --name-servers "10.0.0.1 1.1.1.1 10.0.0.10" --hostname "Ubuntu22" --netboot-enabled true && NAME=""
systemctl restart cobblerd && sleep 10
cobbler sync
Again, the PXE Client is not installing via the local repo @
/var/www/cobbler/distro_mirror
, but now that thefallback: offline-install
option is available with Ubuntu 22.04cloud-init
, the installer will NOT require and internet connection to install, instead installing using the live server installer (.iso file) available on Cobbler’s public HTTP share.
Ubuntu 24.04 PXE Deployment
First, modify /var/lib/cobbler/distro_signatures.json
to suppport Ubuntu 24.04 (which is not included with Cobbler at the time of writing) by pasting the following code block immediately following the Ubuntu 22 jammy
signature definition:
"noble": {
"signatures": [
"dists",
".disk"
],
"version_file": "Release|info",
"version_file_regex": "Suite: noble|Ubuntu 24.04",
"kernel_arch": "linux-headers-(.*)\\.deb",
"kernel_arch_regex": null,
"supported_arches": [
"i386",
"amd64"
],
"supported_repo_breeds": [
"apt"
],
"kernel_file": "(linux|vmlinuz(.*))",
"initrd_file": "initrd($|.gz$|.lz$)",
"isolinux_ok": false,
"default_autoinstall": "",
"kernel_options": "",
"kernel_options_post": "",
"template_files": "",
"boot_files": [],
"boot_loaders": {}
},
With this modification made, be careful not to use the
cobbler signature update
command on the Cobbler server, which will remove any user-defined signatures.
Sync up Cobbler in order to apply the changes
systemctl restart cobblerd && sleep 10
cobbler sync
Take similar steps as above to import and automatically deploy Ubuntu 24.04 LTS Server over PXE
[ -d /mnt/Ubuntu ] || mkdir /mnt/Ubuntu
mount -t iso9660 -o loop,ro /home/fedora/Downloads/ubuntu-24.04.1-live-server-amd64.iso /mnt/Ubuntu
cobbler import --name Ubuntu24 --path /mnt/Ubuntu
mkdir -p /var/www/cobbler/pub/cloud-init/Ubuntu24
cp ~/Downloads/ubuntu-24.04.1-live-server-amd64.iso /var/www/cobbler/pub/cloud-init/Ubuntu24/.
cobbler distro edit --name Ubuntu24-casper-x86_64 --kernel-options 'root=/dev/ram0 ramdisk_size=1500000 ip=dhcp url=http://10.0.0.10/cblr/pub/cloud-init/Ubuntu24/ubuntu-24.04.1-live-server-amd64.iso autoinstall cloud-config-url=http://10.0.0.10/cblr/svc/op/autoinstall/profile/Ubuntu24-casper-x86_64'
cobbler profile edit --name Ubuntu24-casper-x86_64 --autoinstall cloud-init_user-data
NAME="Ubuntu24-auto" && cobbler system add --name $NAME --profile Ubuntu24-casper-x86_64 --kernel-options "root=/dev/ram0 ramdisk_size=1500000 ip=dhcp url=http://10.0.0.10/cblr/pub/cloud-init/Ubuntu24/ubuntu-24.04.1-live-server-amd64.iso autoinstall cloud-config-url=http://10.0.0.10/cblr/svc/op/autoinstall/system/$NAME" --mac-address "aa:bb:cc:dd:ee:ff" --static true --ip-address "10.0.0.24" --netmask "255.255.255.0" --gateway "10.0.0.1" --name-servers "10.0.0.1 1.1.1.1 10.0.0.10" --hostname "Ubuntu24" --netboot-enabled true && NAME=""
systemctl restart cobblerd && sleep 10
cobbler sync
Again, if using the
fallback: offline-install
option in thecloud-init
template for this System, the PXE Client will use the .iso file hosted by Cobbler as the source for installation.
Tips & Troubleshooting
-
The Cobbler 3.3.7 Beginner’s Guide Tips & Troubleshooting section contains some basic recommendations and limitations of Cobbler which will not be repeated here.
-
More info on
cloud-init
-
The
kernel-options
used above were based off of Ubuntu’s official docs -
Additional references:
-
https://louwrentius.com/understanding-the-ubuntu-2004-lts-server-autoinstaller.html
-
https://cdimage.ubuntu.com/ubuntu-legacy-server/releases/20.04/release/
-
https://cloudinit.readthedocs.io/en/latest/howto/disable_cloud_init.html
-
https://vinfrastructure.it/2024/03/how-to-disable-cloud-init-on-ubuntu-server/
-
https://discourse.ubuntu.com/t/netbooting-the-live-server-installer/14510
-
https://discourse.ubuntu.com/t/ubuntu-22-04-pxe-uefi-netboot-desktop-installation/27841
-
https://askubuntu.com/questions/1406685/22-04-jammy-pxe-booting-help
-
https://www.molnar-peter.hu/en/ubuntu-jammy-netinstall-pxe.html
-
https://cloudinit.readthedocs.io/en/latest/howto/run_cloud_init_locally.html
-
These all seem pretty legacy, no mention of recent releases or cloud-init
Enjoy Reading This Article?
Here are some more articles you might like to read next: