diff --git a/source/network_boot.rst b/source/network_boot.rst index 38ab6da0..c3346702 100644 --- a/source/network_boot.rst +++ b/source/network_boot.rst @@ -17,8 +17,8 @@ built-in PXE support. This guide covers how to perform an iPXE boot using network address translation (NAT). -Preparations -============ +Prerequisites +============= Before performing an iPXE boot, verify the following preparations have been made: @@ -55,44 +55,34 @@ Figure 2 depicts the information flow that the configuration script enables. Figure 2: PXE information flow -Step 1 ------- +#. Define variables that are used to parameterize the configuration of an iPXE boot. -Define variables that are used to parameterize the configuration of an iPXE -boot. + .. code-block:: console -.. code-block:: console + web_root=/var/www + ipxe_root=$web_root/ipxe + tftp_root=/srv/tftp - web_root=/var/www - ipxe_root=$web_root/ipxe - tftp_root=/srv/tftp + external_iface=eno1 + internal_iface=eno2 + pxe_subnet=192.168.1 + pxe_internal_ip=$pxe_subnet.1 + pxe_subnet_mask_ip=255.255.255.0 + pxe_subnet_bitmask=24 - external_iface=eno1 - internal_iface=eno2 - pxe_subnet=192.168.1 - pxe_internal_ip=$pxe_subnet.1 - pxe_subnet_mask_ip=255.255.255.0 - pxe_subnet_bitmask=24 +#. Add the ``pxe-server`` bundle to your system. This has all of the software + needed run a PXE server. -Step 2 ------- + .. code-block:: console -Add the ``pxe-server`` bundle to your system. This has all of the software -needed run a PXE server. + swupd bundle-add pxe-server -.. code-block:: console +#. Create an iPXE hosting directory, download the latest network-bootable release + of the Clear Linux* Project for Intel® Architecture, and extract the files. + Ensure that the initial ramdisk file is named ``initrd`` and the kernel file is + named ``linux``, which is a symbolic link to the actual kernel file. - swupd bundle-add pxe-server - -Step 3 ------- - -Create an iPXE hosting directory, download the latest network-bootable release -of the Clear Linux* Project for Intel® Architecture, and extract the files. -Ensure that the initial ramdisk file is named ``initrd`` and the kernel file is -named ``linux``, which is a symbolic link to the actual kernel file. - -.. code-block:: console + .. code-block:: console rm -rf $ipxe_root mkdir -p $ipxe_root @@ -100,14 +90,11 @@ named ``linux``, which is a symbolic link to the actual kernel file. tar -xJf /tmp/clear-pxe.tar.xz -C $ipxe_root ln -sf $(ls $ipxe_root | grep 'org.clearlinux.*') $ipxe_root/linux -Step 4 ------- +#. Create an iPXE boot script. The iPXE boot script is used during an iPXE boot + to direct the PXE client to the files for network booting the latest + release. Use the same names you gave to the initial ramdisk and kernel files. -Create an iPXE boot script. The iPXE boot script is used during an iPXE boot -to direct the PXE client to the files for network booting the latest -release. Use the same names you gave to the initial ramdisk and kernel files. - -.. code-block:: console + .. code-block:: console cat > $ipxe_root/ipxe_boot_script.txt << EOF #!ipxe @@ -116,326 +103,284 @@ release. Use the same names you gave to the initial ramdisk and kernel files. boot EOF -Step 5 -------- +#. The ``pxe-server`` bundle comes with a lightweight web server known as + ``nginx``. Create a configuration file for ``nginx`` to serve the latest release + to PXE clients. -The ``pxe-server`` bundle comes with a lightweight web server known as -``nginx``. Create a configuration file for ``nginx`` to serve the latest release -to PXE clients. + .. code-block:: console -.. code-block:: console - - mkdir -p /etc/nginx - cat > /etc/nginx/nginx.conf << EOF - server { - listen 80; - server_name localhost; - location / { - root $ipxe_root; - autoindex on; + mkdir -p /etc/nginx + cat > /etc/nginx/nginx.conf << EOF + server { + listen 80; + server_name localhost; + location / { + root $ipxe_root; + autoindex on; + } } - } - EOF + EOF -Step 6 -------- +#. Start ``nginx`` and enable startup on boot. -Start ``nginx`` and enable startup on boot. + .. code-block:: console -.. code-block:: console + systemctl start nginx + systemctl enable nginx - systemctl start nginx - systemctl enable nginx +#. The ``pxe-server`` bundle comes with iPXE firmware images which allow computers + without an iPXE implementation to perform an iPXE boot. Create a TFTP hosting + directory and populate it with the iPXE firmware images. -Step 7 ------- + .. code-block:: console -The ``pxe-server`` bundle comes with iPXE firmware images which allow computers -without an iPXE implementation to perform an iPXE boot. Create a TFTP hosting -directory and populate it with the iPXE firmware images. + rm -rf $tftp_root + mkdir -p $tftp_root + ln -sf /usr/share/ipxe/ipxe-x86_64.efi $tftp_root/ipxe-x86_64.efi + ln -sf /usr/share/ipxe/undionly.kpxe $tftp_root/undionly.kpxe -.. code-block:: console +#. The ``pxe-server`` bundle comes with a lightweight TFTP server known as + ``dnsmasq``. Create a configuration file for ``dnsmasq`` to serve iPXE firmware + images to PXE clients over TFTP. - rm -rf $tftp_root - mkdir -p $tftp_root - ln -sf /usr/share/ipxe/ipxe-x86_64.efi $tftp_root/ipxe-x86_64.efi - ln -sf /usr/share/ipxe/undionly.kpxe $tftp_root/undionly.kpxe + .. code-block:: console -Step 8 ------- + cat > /etc/dnsmasq.conf << EOF + enable-tftp + tftp-root=$tftp_root + EOF -The ``pxe-server`` bundle comes with a lightweight TFTP server known as -``dnsmasq``. Create a configuration file for ``dnsmasq`` to serve iPXE firmware -images to PXE clients over TFTP. +#. Enable ``dnsmasq`` to start automatically on boot. -.. code-block:: console + .. code-block:: console - cat > /etc/dnsmasq.conf << EOF - enable-tftp - tftp-root=$tftp_root - EOF + systemctl enable dnsmasq -Step 9 ------- + .. note:: -Enable ``dnsmasq`` to start automatically on boot. + At this point in the configuration process, ``dnsmasq`` is only + being enabled to start automatically on boot and not started because its DNS + server conflicts with the DNS stub listener offered by ``systemd-resolved``. -.. code-block:: console +#. The ``pxe-server`` bundle comes with a lightweight DNS server known as + ``dnsmasq``. Set ``dnsmasq`` to listen on a dedicated IP address. PXE clients + on the private network will then use this IP address for DNS resolution. + Disable the DNS stub listener included with ``systemd-resolved`` to avoid a + conflict with the DNS server offered by ``dnsmasq``. - systemctl enable dnsmasq + .. code-block:: console -.. note:: + mkdir -p /etc/systemd + cat > /etc/systemd/resolved.conf << EOF + [Resolve] + DNSStubListener=no + EOF - At this point in the configuration process, ``dnsmasq`` is only - being enabled to start automatically on boot and not started because its DNS - server conflicts with the DNS stub listener offered by ``systemd-resolved``. + cat >> /etc/dnsmasq.conf << EOF + listen-address=$pxe_internal_ip + EOF -Step 10 -------- + .. note:: -The ``pxe-server`` bundle comes with a lightweight DNS server known as -``dnsmasq``. Set ``dnsmasq`` to listen on a dedicated IP address. PXE clients -on the private network will then use this IP address for DNS resolution. -Disable the DNS stub listener included with ``systemd-resolved`` to avoid a -conflict with the DNS server offered by ``dnsmasq``. + ``dnsmasq`` is a lightweight implementation of a DNS server, a DHCP server, + and a TFTP server. For the purposes of this guide, the DHCP server included + with ``dnsmasq`` is not being used. -.. code-block:: console + .. note:: - mkdir -p /etc/systemd - cat > /etc/systemd/resolved.conf << EOF - [Resolve] - DNSStubListener=no - EOF + Using DNS server provided by ``dnsmasq`` allows ``systemd-resolved`` to + dynamically update the list of DNS servers for the private network from the + public network. In effect, this creates a pass-through DNS server which + relies on DNS servers listed in ``/etc/resolv.conf``. - cat >> /etc/dnsmasq.conf << EOF - listen-address=$pxe_internal_ip - EOF +#. Start ``dnsmasq`` and avoid conflicts with ``systemd-resolved``. -.. note:: + .. code-block:: console - ``dnsmasq`` is a lightweight implementation of a DNS server, a DHCP server, - and a TFTP server. For the purposes of this guide, the DHCP server included - with ``dnsmasq`` is not being used. + systemctl stop systemd-resolved + systemctl restart dnsmasq + systemctl start systemd-resolved -.. note:: +#. Assign a static IP address to the network adapter for the private network. - Using DNS server provided by ``dnsmasq`` allows ``systemd-resolved`` to - dynamically update the list of DNS servers for the private network from the - public network. In effect, this creates a pass-through DNS server which - relies on DNS servers listed in ``/etc/resolv.conf``. + .. code-block:: console -Step 11 -------- + mkdir -p /etc/systemd/network -Start ``dnsmasq`` and avoid conflicts with ``systemd-resolved``. + ln -sf /dev/null /etc/systemd/network/80-dhcp.network -.. code-block:: console + cat > /etc/systemd/network/80-external-dynamic.network << EOF + [Match] + Name=$external_iface + [Network] + DHCP=yes + EOF - systemctl stop systemd-resolved - systemctl restart dnsmasq - systemctl start systemd-resolved + cat > /etc/systemd/network/80-internal-static.network << EOF + [Match] + Name=$internal_iface + [Network] + DHCP=no + Address=$pxe_internal_ip/$pxe_subnet_bitmask + EOF -Step 12 ------- + systemctl restart systemd-networkd -Assign a static IP address to the network adapter for the private network. + .. note:: -.. code-block:: console + By default, ``systemd-networkd`` uses DHCP for all network adapters. This + functionality needs disabled prior to assigning a static IP address. As a + consequence, this also disables DHCP functionality for the network adapter + connected to the public network. This network adapter needs to have this + functionality explicitly re-enabled. - mkdir -p /etc/systemd/network +#. The ``pxe-server`` bundle comes with a full implementation of a DHCP server + compliant to the specifications defined by the Internet Systems Consortium + (ISC), known as ``dhcpd``. Configure ``dhcpd`` to dynamically allocate IP + addresses to PXE clients on the private network. The following configuration + provides the following important functions: - ln -sf /dev/null /etc/systemd/network/80-dhcp.network + * Enables ``dhcpd`` to be iPXE-aware with `iPXE-specific options`_ + * Directs PXE clients without an iPXE implementation to the TFTP server for + acquiring architecture-specific iPXE firmware images to allow them to perform + an iPXE boot + * Is only active on the network adapter which has an IP address on the defined + subnet + * Directs PXE clients to the DNS server + * Directs PXE clients to the PXE server for routing via NAT + * Divides the private network into two pools of IP addresses, one for network + booting and another for usage after boot; each with their own lease times - cat > /etc/systemd/network/80-external-dynamic.network << EOF - [Match] - Name=$external_iface - [Network] - DHCP=yes - EOF + .. code-block:: console - cat > /etc/systemd/network/80-internal-static.network << EOF - [Match] - Name=$internal_iface - [Network] - DHCP=no - Address=$pxe_internal_ip/$pxe_subnet_bitmask - EOF + cat > /etc/dhcpd.conf << EOF + option space ipxe; + option ipxe-encap-opts code 175 = encapsulate ipxe; + option ipxe.priority code 1 = signed integer 8; + option ipxe.keep-san code 8 = unsigned integer 8; + option ipxe.skip-san-boot code 9 = unsigned integer 8; + option ipxe.syslogs code 85 = string; + option ipxe.cert code 91 = string; + option ipxe.privkey code 92 = string; + option ipxe.crosscert code 93 = string; + option ipxe.no-pxedhcp code 176 = unsigned integer 8; + option ipxe.bus-id code 177 = string; + option ipxe.bios-drive code 189 = unsigned integer 8; + option ipxe.username code 190 = string; + option ipxe.password code 191 = string; + option ipxe.reverse-username code 192 = string; + option ipxe.reverse-password code 193 = string; + option ipxe.version code 235 = string; + option iscsi-initiator-iqn code 203 = string; + option ipxe.pxeext code 16 = unsigned integer 8; + option ipxe.iscsi code 17 = unsigned integer 8; + option ipxe.aoe code 18 = unsigned integer 8; + option ipxe.http code 19 = unsigned integer 8; + option ipxe.https code 20 = unsigned integer 8; + option ipxe.tftp code 21 = unsigned integer 8; + option ipxe.ftp code 22 = unsigned integer 8; + option ipxe.dns code 23 = unsigned integer 8; + option ipxe.bzimage code 24 = unsigned integer 8; + option ipxe.multiboot code 25 = unsigned integer 8; + option ipxe.slam code 26 = unsigned integer 8; + option ipxe.srp code 27 = unsigned integer 8; + option ipxe.nbi code 32 = unsigned integer 8; + option ipxe.pxe code 33 = unsigned integer 8; + option ipxe.elf code 34 = unsigned integer 8; + option ipxe.comboot code 35 = unsigned integer 8; + option ipxe.efi code 36 = unsigned integer 8; + option ipxe.fcoe code 37 = unsigned integer 8; + option ipxe.vlan code 38 = unsigned integer 8; + option ipxe.menu code 39 = unsigned integer 8; + option ipxe.sdi code 40 = unsigned integer 8; + option ipxe.nfs code 41 = unsigned integer 8; - systemctl restart systemd-networkd + class "PXE-Chainload" { + match if substring(option vendor-class-identifier, 0, 9) = "PXEClient"; -.. note:: - - By default, ``systemd-networkd`` uses DHCP for all network adapters. This - functionality needs disabled prior to assigning a static IP address. As a - consequence, this also disables DHCP functionality for the network adapter - connected to the public network. This network adapter needs to have this - functionality explicitly re-enabled. - -Step 13 -------- - -The ``pxe-server`` bundle comes with a full implementation of a DHCP server -compliant to the specifications defined by the Internet Systems Consortium -(ISC), known as ``dhcpd``. Configure ``dhcpd`` to dynamically allocate IP -addresses to PXE clients on the private network. The following configuration -provides the following important functions: - -* Enables ``dhcpd`` to be iPXE-aware with `iPXE-specific options`_ -* Directs PXE clients without an iPXE implementation to the TFTP server for - acquiring architecture-specific iPXE firmware images to allow them to perform - an iPXE boot -* Is only active on the network adapter which has an IP address on the defined - subnet -* Directs PXE clients to the DNS server -* Directs PXE clients to the PXE server for routing via NAT -* Divides the private network into two pools of IP addresses, one for network - booting and another for usage after boot; each with their own lease times - -.. code-block:: console - - cat > /etc/dhcpd.conf << EOF - option space ipxe; - option ipxe-encap-opts code 175 = encapsulate ipxe; - option ipxe.priority code 1 = signed integer 8; - option ipxe.keep-san code 8 = unsigned integer 8; - option ipxe.skip-san-boot code 9 = unsigned integer 8; - option ipxe.syslogs code 85 = string; - option ipxe.cert code 91 = string; - option ipxe.privkey code 92 = string; - option ipxe.crosscert code 93 = string; - option ipxe.no-pxedhcp code 176 = unsigned integer 8; - option ipxe.bus-id code 177 = string; - option ipxe.bios-drive code 189 = unsigned integer 8; - option ipxe.username code 190 = string; - option ipxe.password code 191 = string; - option ipxe.reverse-username code 192 = string; - option ipxe.reverse-password code 193 = string; - option ipxe.version code 235 = string; - option iscsi-initiator-iqn code 203 = string; - option ipxe.pxeext code 16 = unsigned integer 8; - option ipxe.iscsi code 17 = unsigned integer 8; - option ipxe.aoe code 18 = unsigned integer 8; - option ipxe.http code 19 = unsigned integer 8; - option ipxe.https code 20 = unsigned integer 8; - option ipxe.tftp code 21 = unsigned integer 8; - option ipxe.ftp code 22 = unsigned integer 8; - option ipxe.dns code 23 = unsigned integer 8; - option ipxe.bzimage code 24 = unsigned integer 8; - option ipxe.multiboot code 25 = unsigned integer 8; - option ipxe.slam code 26 = unsigned integer 8; - option ipxe.srp code 27 = unsigned integer 8; - option ipxe.nbi code 32 = unsigned integer 8; - option ipxe.pxe code 33 = unsigned integer 8; - option ipxe.elf code 34 = unsigned integer 8; - option ipxe.comboot code 35 = unsigned integer 8; - option ipxe.efi code 36 = unsigned integer 8; - option ipxe.fcoe code 37 = unsigned integer 8; - option ipxe.vlan code 38 = unsigned integer 8; - option ipxe.menu code 39 = unsigned integer 8; - option ipxe.sdi code 40 = unsigned integer 8; - option ipxe.nfs code 41 = unsigned integer 8; - - class "PXE-Chainload" { - match if substring(option vendor-class-identifier, 0, 9) = "PXEClient"; - - next-server $pxe_internal_ip; - if exists user-class and option user-class = "iPXE" { - filename "http://$pxe_internal_ip/ipxe_boot_script.txt"; - } - elsif substring(option vendor-class-identifier, 0, 20) = "PXEClient:Arch:00007" or substring(option vendor-class-identifier, 0, 20) = "PXEClient:Arch:00008" or substring(option vendor-class-identifier, 0, 20) = "PXEClient:Arch:00009" { - filename "ipxe-x86_64.efi"; - } - elsif substring(option vendor-class-identifier, 0, 20) = "PXEClient:Arch:00000" { - filename "undionly.kpxe"; - } - } - - subnet $pxe_subnet.0 netmask $pxe_subnet_mask_ip { - authoritative; - option routers $pxe_internal_ip; - option domain-name-servers $pxe_internal_ip; - - pool { - allow members of "PXE-Chainload"; - range $pxe_subnet.128 $pxe_subnet.253; - default-lease-time 600; - max-lease-time 3600; + next-server $pxe_internal_ip; + if exists user-class and option user-class = "iPXE" { + filename "http://$pxe_internal_ip/ipxe_boot_script.txt"; + } + elsif substring(option vendor-class-identifier, 0, 20) = "PXEClient:Arch:00007" or substring(option vendor-class-identifier, 0, 20) = "PXEClient:Arch:00008" or substring(option vendor-class-identifier, 0, 20) = "PXEClient:Arch:00009" { + filename "ipxe-x86_64.efi"; + } + elsif substring(option vendor-class-identifier, 0, 20) = "PXEClient:Arch:00000" { + filename "undionly.kpxe"; + } } - pool { - deny members of "PXE-Chainload"; - range $pxe_subnet.2 $pxe_subnet.127; - default-lease-time 3600; - max-lease-time 21600; + subnet $pxe_subnet.0 netmask $pxe_subnet_mask_ip { + authoritative; + option routers $pxe_internal_ip; + option domain-name-servers $pxe_internal_ip; + + pool { + allow members of "PXE-Chainload"; + range $pxe_subnet.128 $pxe_subnet.253; + default-lease-time 600; + max-lease-time 3600; + } + + pool { + deny members of "PXE-Chainload"; + range $pxe_subnet.2 $pxe_subnet.127; + default-lease-time 3600; + max-lease-time 21600; + } } - } - EOF + EOF -.. note:: + .. note:: - There are three providers of a DHCP server on the system at this point: - ``systemd-networkd``, ``dnsmasq``, and ``dhcpd``. ``dhcpd`` is used because it - is maintained by ISC and is more flexible for iPXE booting. + There are three providers of a DHCP server on the system at this point: + ``systemd-networkd``, ``dnsmasq``, and ``dhcpd``. ``dhcpd`` is used because it + is maintained by ISC and is more flexible for iPXE booting. -Step 14 -------- +#. Create a file where ``dhcpd`` can record the IP addresses that it hands out to + PXE clients. -Create a file where ``dhcpd`` can record the IP addresses that it hands out to -PXE clients. + .. code-block:: console -.. code-block:: console + mkdir -p /var/db + touch /var/db/dhcpd.leases - mkdir -p /var/db - touch /var/db/dhcpd.leases +#. Start ``dhcpd`` and enable startup on boot. -Step 15 -------- + .. code-block:: console -Start ``dhcpd`` and enable startup on boot. + systemctl enable dhcp4 + systemctl restart dhcp4 -.. code-block:: console +#. Configure NAT so that traffic from the private network can be routed to the + public network. This effectively turns the PXE server into a router. - systemctl enable dhcp4 - systemctl restart dhcp4 + .. code-block:: console -Step 16 -------- + iptables -t nat -F POSTROUTING + iptables -t nat -A POSTROUTING -o $external_iface -j MASQUERADE + systemctl enable iptables-save.service + systemctl restart iptables-save.service + systemctl enable iptables-restore.service + systemctl restart iptables-restore.service -Configure NAT so that traffic from the private network can be routed to the -public network. This effectively turns the PXE server into a router. + .. note:: -.. code-block:: console + The firewall MASQUERADEs, or translates, packets to make them appear as if + they are coming from the PXE server. This hides the PXE clients from the + public network. - iptables -t nat -F POSTROUTING - iptables -t nat -A POSTROUTING -o $external_iface -j MASQUERADE - systemctl enable iptables-save.service - systemctl restart iptables-save.service - systemctl enable iptables-restore.service - systemctl restart iptables-restore.service +#. Tell the Linux kernel to forward network packets on to different interfaces. + Otherwise, NAT will not work. -.. note:: + .. code-block:: console - The firewall MASQUERADEs, or translates, packets to make them appear as if - they are coming from the PXE server. This hides the PXE clients from the - public network. + mkdir -p /etc/sysctl.d + echo net.ipv4.ip_forward=1 > /etc/sysctl.d/80-nat-forwarding.conf + echo 1 > /proc/sys/net/ipv4/ip_forward -Step 17 -------- - -Tell the Linux kernel to forward network packets on to different interfaces. -Otherwise, NAT will not work. - -.. code-block:: console - - mkdir -p /etc/sysctl.d - echo net.ipv4.ip_forward=1 > /etc/sysctl.d/80-nat-forwarding.conf - echo 1 > /proc/sys/net/ipv4/ip_forward - -Step 18 -------- - -Power on the PXE client and watch it boot the latest release of the Clear Linux* -Project for Intel® Architecture. +#. Power on the PXE client and watch it boot the latest release of the Clear Linux* + Project for Intel® Architecture. .. _iPXE: http://ipxe.org/