ipxe_scripts/embed.ipxe

221 lines
7.7 KiB
Plaintext

#!ipxe
# I've assume IPv4 for this script, so if we need IPv6, it may need
# modifications.
# Require only verified images to boot
imgtrust --permanent
# For the "focal" part of the URL string, in case that changes in the future.
set ubuntu-variant focal
goto get_arch
#################
### This section is at the top, so it's easier to modify.
:static_ip_boot_setup
# Open all network interface devices, so we aren't restricted to just the first
ifopen
sleep 1
# Currently we just configure IP info by MAC address. So we iterate over
# MAC addresses and set the variables. To ensure we use the desired
# device, we iterate over all devices and simply find matches by
# MAC address.
set idx:int32 0
set successful f
:loop
isset ${net${idx}/mac} || goto loop_done
######################## SET STATIC IP INFO HERE #############################
# Just copy/paste an entire line to add more
#
echo Checking net${idx}
# node1.bitmessage.at
iseq ${net${idx}/mac} 40:a8:f0:31:cc:58 && set ip-dev-name eno1 && set ip-addr 93.189.28.82 && set ip-gateway 93.189.28.81 && set ip-netmask 255.255.255.240 && set ip-dns 1.1.1.1 && set successful t && goto loop_done ||
iseq ${net${idx}/mac} 40:a8:f0:31:cc:59 && set ip-dev-name eno2 && set ip-addr 93.189.28.82 && set ip-gateway 93.189.28.81 && set ip-netmask 255.255.255.240 && set ip-dns 1.1.1.1 && set successful t && goto loop_done ||
# node2.bitmessage.at
iseq ${net${idx}/mac} 28:80:23:a7:52:d0 && set ip-dev-name eno1 && set ip-addr 93.189.25.250 && set ip-gateway 93.189.25.249 && set ip-netmask 255.255.255.248 && set ip-dns 1.1.1.1 && set successful t && goto loop_done ||
iseq ${net${idx}/mac} 28:80:23:a7:52:d1 && set ip-dev-name eno2 && set ip-addr 93.189.25.250 && set ip-gateway 93.189.25.249 && set ip-netmask 255.255.255.248 && set ip-dns 1.1.1.1 && set successful t && goto loop_done ||
# node1.surda.cloud
iseq ${net${idx}/mac} d0:50:99:df:1d:49 && set ip-dev-name enp39s0 && set ip-addr 93.189.28.83 && set ip-gateway 93.189.28.81 && set ip-netmask 255.255.255.240 && set ip-dns 1.1.1.1 && set successful t && goto loop_done ||
iseq ${net${idx}/mac} d0:50:99:df:1d:4a && set ip-dev-name enp38s0 && set ip-addr 93.189.28.83 && set ip-gateway 93.189.28.81 && set ip-netmask 255.255.255.240 && set ip-dns 1.1.1.1 && set successful t && goto loop_done ||
# node3.sysdeploy.org
iseq ${net${idx}/mac} 00:25:90:a2:9f:e9 && set ip-dev-name eno2 && set ip-addr 104.251.122.45 && set ip-gateway 104.251.122.44 && set ip-netmask 255.255.255.254 && set ip-dns 1.1.1.1 && set successful t && goto loop_done ||
# if you don't know the linux interface name, use "clear ip-dev-name", then
# it will use ALL interfaces
##############################################################################
inc idx && goto loop
:loop_done
# If we have not successfully found a MAC match, then we error, because we
# also failed DHCP. So there's nothing we can do but fail.
iseq ${successful} f && goto error_handler ||
# If on the other hand we're successful, then we construct the kernel ip= line
set ip-info ${ip-addr}::${ip-gateway}:${ip-netmask}::${ip-dev-name}:off:${ip-dns}
# And setup IPXE networking.
# First, set device info
set net${idx}/ip ${ip-addr}
set net${idx}/gateway ${ip-gateway}
set net${idx}/netmask ${ip-netmask}
set net${idx}/dns ${ip-dns}
# Now we close all net devices and enable only the one we need.
# Sleep a little between, so we don't error by continuing too fast before the
# device is actually ready
sleep 1
ifclose
sleep 1
ifopen net${idx}
sleep 1
# Set settings again in case the ifdown/ifup cleared them
set net${idx}/ip ${ip-addr}
set net${idx}/gateway ${ip-gateway}
set net${idx}/netmask ${ip-netmask}
set net${idx}/dns ${ip-dns}
sleep 1
# Now we have the ip= line and the IPXE network configured, so we can
# download and boot.
goto boot_all
###
#################
:try_next_card
imgfree
ifclose
sleep 1
# If dhcp, it will go to the static boot, which already has ifopen
iseq ip-info dhcp || ifopen
iseq ip-info dhcp || sleep 1
iseq ip-info dhcp && clear ip-info && goto try_static_from_dhcp_fail || goto try_next_static_card
:try_static_from_dhcp_fail
iseq arch-info arm64 && goto static_ip_boot_arm64 ||
iseq arch-info amd64 && goto static_ip_boot_amd64 ||
goto error_handler
:try_next_static_card
isset ip-dev-name && clear ip-dev-name
isset ip-addr && clear ip-addr
isset ip-gateway && clear ip-gateway
isset ip-netmask && clear ip-netmask
isset ip-dns && clear ip-dns
isset successful && clear successful
set successful f
isset idx && inc idx || goto error_handler
goto loop
# In case we want to... log?? Or do something else.
:error_handler
echo "###########################################################"
echo "An unspecified error has occurred."
echo "The system will sleep for two minutes and then reboot."
echo "###########################################################"
sleep 60
sleep 60
reboot
# Should not occur, but just in case...
sleep 5
exit
# Get relevant CPU arch.
:get_arch
iseq ${buildarch} arm32 && goto start_arm32 ||
iseq ${buildarch} arm64 && goto start_arm64 ||
iseq ${buildarch} i386 && goto start_i386 ||
iseq ${buildarch} x86_64 && goto start_amd64 ||
goto error_handler
# Builds may be done on 32-bit, but machines will always be 64-bit.
# Keep this section just in case we want to use 32-bit machines in the future.
:start_arm32
goto start_arm64
:start_i386
goto start_amd64
# Set arch info and determine if we can use DHCP for network.
# Then either boot or goto static IP setup.
:start_arm64
set arch-info arm64
dhcp || goto static_ip_boot_arm64
sleep 1
set ip-info dhcp
goto boot_all
:start_amd64
set arch-info amd64
dhcp || goto static_ip_boot_amd64
sleep 1
set ip-info dhcp
goto boot_all
# This process should be the same for arm and x86, but I'll leave this section
# intact in case it turns out it's not the same
:static_ip_boot_arm64
goto static_ip_boot_setup
:static_ip_boot_amd64
goto static_ip_boot_setup
:boot_all
# We use HTTP because IPXE's HTTPS implementation is lacking. So we delegate
# integrity and validation to imgverify.
# Naming the squashfs download "/squashfs" is required, otherwise the boot
# kernel fails to load it in the "root=" part of the kernel cmdline.
# However, note that imgverify will fail if you refer to it as "/squashfs"
# instead of "squashfs".
# "--signer" validates against the subject common name field of the signing
# certificate. That signing cert must have both the digital signature key
# usage set and the code-signing key usage extension set.
# By default, IPXE trusts the default Mozilla global root CA list, so
# make sure you pick a common name with a FQDN you control, even if you're
# using a custom CA that you import during build.
initrd http://images.sysdeploy.org/${ubuntu-variant}/${arch-info}/initrd.cpio || goto try_next_card
imgverify --signer images.sysdeploy.org initrd.cpio http://images.sysdeploy.org/${ubuntu-variant}/${arch-info}/initrd.cpio.sig || goto error_handler
kernel http://images.sysdeploy.org/${ubuntu-variant}/${arch-info}/boot-kernel || goto try_next_card
imgverify --signer images.sysdeploy.org boot-kernel http://images.sysdeploy.org/${ubuntu-variant}/${arch-info}/boot-kernel.sig || goto error_handler
# Get accurate time so we can set the clock in kernel boot cmdline
ntp pool.ntp.org || goto error_handler
echo ip-info ${ip-info}
sleep 1
boot boot-kernel initrd=initrd.cpio rootfstype=squashfs root=/squashfs ip=${ip-info} overlayroot=tmpfs:recurse=0 systemd.clock-usec=${unixtime:int32}000000 ds=nocloud-net;s=https://cloud-init.sysdeploy.org/apiv2?uuid=${uuid}&filetype= || goto error_handler
# unixtime variable must be used with int32, because that's the only way it
# will display as decimal digits. unit32 and string both display as hex.
# Therefore this will stop working in 2038.