After weeks of stupid grinding I got it working!
Let me try to explain how to get it working:
( 192.168.2.221
is the IP address of my server running the Nginx HTTP server)
- Create a folder structure like:
my_network_boot
my_network_boot/configs/butane
my_network_boot/files/grub2
my_network_boot/files/hosts/grub2
my_network_boot/files/images
my_network_boot/nginx/conf.d
- Create some files:
my_network_boot/nginx/conf.d/default.conf
:
server {
listen 80;
listen [::]:80;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 0;
include /etc/nginx/mime.types;
default_type application/octet-stream;
error_log /var/log/nginx/error.log notice;
access_log /var/log/nginx/access.log main;
gzip on;
gzip_disable "msie6";
include /config/nginx/site-confs/*;
}
my_network_boot/nginx/html
as a soft link to the files
directory:
ln -s files nginx/html
my_network_boot/compose.yaml
:
---
services:
nginx:
container_name: netboot_nginx
image: nginx:1.27.4-alpine3.21
network_mode: host
ports:
- 80:80
volumes:
- type: bind
source: "${PWD}/nginx/conf.d"
target: "/etc/nginx/conf.d"
read_only: true
- type: bind
source: "${PWD}/nginx/html"
target: "/etc/nginx/html"
read_only: true
restart: unless-stopped
my_network_boot/get_files.sh
:
#!/usr/bin/env bash
#Define source directory of the Scrtipt
SOURCE_DIR=$(realpath "$(dirname -- "${BASH_SOURCE[0]}")")
# openSUSE Leap Micro 6.1
# https://cdn.opensuse.org/download/distribution/leap-micro/6.1/appliances/
# https://documentation.suse.com/sle-micro/6.1/html/Micro-deployment-pxe/index.html
echo "\n########## openSUSE-Leap-Micro 6.1"
mkdir -p ${SOURCE_DIR}/files/images/openSUSE-Leap-Micro/6.1
wget -O ${SOURCE_DIR}/files/images/openSUSE-Leap-Micro/6.1/openSUSE-Leap-Micro.x86_64-Default-SelfInstall.install.tar -nc https://cdn.opensuse.org/download/distribution/leap-micro/6.1/appliances/openSUSE-Leap-Micro.x86_64-Default-SelfInstall.install.tar
tar xvf ${SOURCE_DIR}/files/images/openSUSE-Leap-Micro/6.1/openSUSE-Leap-Micro.x86_64-Default-SelfInstall.install.tar -C ${SOURCE_DIR}/files/images/openSUSE-Leap-Micro/6.1 --overwrite
my_network_boot/configs/butane/your_hostname.bu.yaml
:
variant: fcos
version: 1.4.0
passwd:
users:
- name: root
ssh_authorized_keys:
- "ssh-rsa AAAAB3NzaC.......b3Z5TXQ== your_comment"
password_hash: $6$sxfGOnw5tPck1LoS$N.YsNpCFM1MnbmAUGqmmZt/wy.42ugI7K1ZcGBfp4XdufTXxst1.I0u297hCWf.CKWxNwQ9joSgdh7KU96VKH1
- name: yourUsername
ssh_authorized_keys:
- "ssh-rsa AAAAB3NzaC.......b3Z5TXQ== your_comment"
password_hash: $6$sxfGOn........U96VKH
home_dir: /home/yourUsername
groups:
- wheel
shell: /bin/bash
storage:
disks:
- device: "/dev/disk/by-id/wwn-0x50014ee21264eceb"
wipe_table: true
partitions:
- number: 1
size_mib: 0
label: opt
filesystems:
- path: /home
device: "/dev/disk/by-id/wwn-0x5002538d40db1ab0-part3"
format: btrfs
wipe_filesystem: false
with_mount_unit: true
mount_options:
- "subvol=/@/home"
files:
- path: /etc/NetworkManager/system-connections/enp1s0.nmconnection
mode: 0600
contents:
inline: |
[connection]
id=enp1s0
uuid=b5344841-0f14-4406-b699-c9d70cc198f9
type=ethernet
autoconnect-priority=-100
autoconnect-retries=1
interface-name=enp1s0
multi-connect=1
[ethernet]
[ipv4]
address1=192.168.0.5/23
dns=192.168.0.1;
gateway=192.168.0.1
may-fail=false
method=manual
[ipv6]
method=disabled
[proxy]
systemd:
units:
- name: sshd.service
enabled: true
- name: cockpit.socket
enabled: true
my_network_boot/files/hosts/grub2/a8:a1:59:1d:ca:c0
with a file name with the MAC address of the to be network booted device:
(Change the example IP address 192.168.2.221
in the file)
(Change your_hostname.ign
)
# opensuse leap micro 6.1
set default="opensuse-leap-micro-6-1"
set timeout=30
if [ x"${feature_menuentry_id}" = xy ]; then
menuentry_id_option="--id"
else
menuentry_id_option=""
fi
menuentry "Boot from Hard Disk" --class os --unrestricted $menuentry_id_option 'boot-from-hard-disk' {
exit
}
menuentry "Install openSUSE Leap Micro" --class os --unrestricted $menuentry_id_option 'opensuse-leap-micro-6-1' {
echo Loading kernel...
linux ($root)/images/openSUSE-Leap-Micro/6.1/pxeboot.openSUSE-Leap-Micro.x86_64-6.1.kernel rd.kiwi.oem.installdevice=/dev/disk/by-id/wwn-0x5002538d40db1ab0 rd.kiwi.install.pass.bootparam rd.kiwi.install.pxe rd.kiwi.install.image=http://192.168.2.221/images/openSUSE-Leap-Micro/6.1/openSUSE-Leap-Micro.x86_64-6.1.xz ignition.config.url=http://192.168.2.221/hosts/your_hostname.ign
echo Loading initrd...
initrd ($root)/images/openSUSE-Leap-Micro/6.1/pxeboot.openSUSE-Leap-Micro.x86_64-6.1.initrd
}
my_network_boot/files/grub2/grub.cfg
if [ -s /hosts/grub2/${net_default_mac} ]; then
source /hosts/grub2/${net_default_mac}
fi
- Create the Grub2 netboot directories with
grub2-mknetdir
:
grub2-mknetdir(1) — grub2-common
cd files
sudo grub2-mknetdir --net-directory=./ --subdir=grub2
cd ..
- Fix the owner:
sudo chown yourUsername:yourUserngroup -R files
- Create the Grub2 images with
grub2-mkimage
grub2-mkimage(1) — grub2-common
(Change the example IP address 192.168.2.221
in the command)
cd files
sudo grub2-mkimage -O x86_64-efi --output grub2/x86_64-efi/core.efi --prefix '(http,192.168.2.221)/grub2' btrfs tftp normal ls echo minicmd halt net reboot http linux bsd zfs video efi_gop efi_uga efifwsetup efinet efitextmode
cd ..
- Start the container using Docker or Podman:
podman compose up -d --build
Logs can be checked with:
podman logs -f netboot_nginx
- Confige your already existing DHCP server, in this case it’s a config for ISC DHCP on an OPNsense,
/usr/local/etc/dhcpd.opnsense.d/http-network-boot.conf
:
(Change the example IP address 192.168.2.221
in the file)
class "httpclients" {
option vendor-class-identifier "HTTPClient";
match if substring (option vendor-class-identifier, 0, 10) = "HTTPClient";
filename "http://192.168.2.221/grub2/x86_64-efi/core.efi";
}
- Generate the ignition config out of the butane config:
(use podman
or docker
)
podman run --interactive --rm quay.io/coreos/butane:release --pretty --strict < configs/butane/your_hostname.bu.yaml > files/hosts/your_hostname.ign
- Now you can boot your device via
UEFI HTTP IPv4
- Pray!
