.. _ipxe-install: Install Clear Linux over the network with iPXE ################################################ This guide describes how to install Clear Linux\* using :abbr:`PXE (Pre-boot Execution Environment)`. PXE is an industry standard that describes client-server interaction with network-boot software and uses the DHCP and TFTP protocols. This guide shows one method of using the PXE environment to install |CL|. The PXE extension called `iPXE`_ adds support for additional protocols such as HTTP, :abbr:`iSCSI (Internet Small Computer Systems Interface)`, :abbr:`AoE (ATA over Ethernet\*)`, and :abbr:`FCoE (Fiber Channel over Ethernet\*)`. iPXE enables network booting on computers with no built-in PXE support. To install |CL| through iPXE, you must create a PXE client. Figure 1 depicts the flow of information between a PXE server and a PXE client. .. figure:: ./figures/network-boot-flow.png :alt: PXE information flow Figure 1: PXE information flow. .. caution:: The |CL| image that boots through the PXE process automatically erases all data and partitions on the PXE client system and creates 3 new partitions to install onto. Prerequisites ************* Before booting with iPXE, make the following preparations. Connect the PXE server and PXE clients to a switch on a private network, as shown in Figure 2. .. figure:: ./figures/network-boot-setup.png :alt: Network topology Figure 2: Network topology. Your PXE client must have a boot order where the network boot option is prioritized before the disk boot option. Your PXE server must have: * Ethernet/LAN boot option. * At least two network adapters. * Connection to a public network. * Secure boot option disabled. .. note:: You must disable the secure boot option in the BIOS because the UEFI binaries used to boot |CL| are not signed. Configuration ************* To set up |CL| using iPXE automatically, use the :file:`configure-ipxe.sh` script included with :abbr:`ICIS (Ister Cloud Init Service)`. For additional instructions on the script, refer to the guide on the `ICIS GitHub repository`_. To set up |CL| manually, perform the steps below. #. Define the variables used for iPXE boot configuration. .. code-block:: console ipxe_app_name=ipxe ipxe_port=50000 web_root=/var/www ipxe_root=$web_root/$ipxe_app_name 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=16 #. Log in and get root privilege. .. code-block:: bash sudo -s #. Add the `pxe-server` bundle to your |CL| system. The bundle contains all files needed to run a PXE server. .. code-block:: bash sudo swupd bundle-add pxe-server #. Download the latest network-bootable release of |CL| and extract the files. .. code-block:: bash sudo mkdir -p $ipxe_root sudo curl -o /tmp/clear-pxe.tar.xz \ https://download.clearlinux.org/current/clear-$(curl \ https://download.clearlinux.org/latest)-pxe.tar.xz sudo tar -xJf /tmp/clear-pxe.tar.xz -C $ipxe_root sudo ln -sf $(ls $ipxe_root | grep 'org.clearlinux.*') $ipxe_root/linux .. note:: Ensure that the initial ramdisk file is named :file:`initrd` and the kernel file is named :file:`linux`, which is a symbolic link to the actual kernel file. #. Create an iPXE boot script with the following contents. During an iPXE boot, the iPXE boot script directs the PXE client to download the files to boot and install |CL|. Use the names previously given to the initial ramdisk and kernel files. .. code-block:: console sudo cat > $ipxe_root/ipxe_boot_script.ipxe << EOF sudo!ipxe kernel linux quiet init=/usr/lib/systemd/systemd-bootchart \ initcall_debug tsc=reliable no_timer_check noreplace-smp rw \ initrd=initrd initrd initrd boot EOF #. The `pxe-server` bundle contains a lightweight web-server known as `nginx`. Create a configuration file for `nginx` to serve |CL| to PXE clients with the following contents: .. code-block:: console sudo mkdir -p /etc/nginx/conf.d sudo cat > /etc/nginx/conf.d/$ipxe_app_name.conf << EOF server { listen $ipxe_port; server_name localhost; location /$ipxe_app_name/ { root $web_root; autoindex on; } } EOF sudo cp /usr/share/nginx/conf/nginx.conf.example /etc/nginx/nginx.conf .. note:: Create a separate `nginx` configuration file to serve network-bootable images on a non-standard port number. This action saves existing `nginx` configurations. #. Start `nginx` and enable the startup on boot option. .. code-block:: bash sudo systemctl start nginx sudo systemctl enable nginx #. The `pxe-server` bundle contains a lightweight DNS server which conflicts with the DNS stub listener provided in `systemd-resolved`. Disable the DNS stub listener and temporarily stop `systemd-resolved`. .. code-block:: console sudo mkdir -p /etc/systemd sudo cat > /etc/systemd/resolved.conf << EOF [Resolve] DNSStubListener=no EOF sudo systemctl stop systemd-resolved #. Assign a static IP address to the network adapter for the private network and restart `systemd-networkd` with the following commands: .. code-block:: console sudo mkdir -p /etc/systemd/network sudo cat > /etc/systemd/network/70-internal-static.network << EOF [Match] Name=$internal_iface [Network] DHCP=no Address=$pxe_internal_ip/$pxe_subnet_bitmask EOF sudo systemctl restart systemd-networkd #. Configure :abbr:`NAT (Network Address Translation)` to route traffic from the private network to the public network. This action makes the PXE server act as a router. To make these changes persistent during reboots, save the changes to the firewall with the following commands: .. code-block:: bash sudo iptables -t nat -F POSTROUTING sudo iptables -t nat -A POSTROUTING -o $external_iface -j MASQUERADE sudo systemctl enable iptables-save.service sudo systemctl restart iptables-save.service sudo systemctl enable iptables-restore.service sudo systemctl restart iptables-restore.service .. note:: The firewall masks packets to make them appear as coming from the PXE server and hides PXE clients from the public network. #. Configure the kernel to forward network packets to different interfaces. Otherwise, NAT will not work. .. code-block:: bash sudo mkdir -p /etc/sysctl.d sudo echo net.ipv4.ip_forward=1 > /etc/sysctl.d/80-nat-forwarding.conf sudo echo 1 > /proc/sys/net/ipv4/ip_forward #. The `pxe-server` bundle contains iPXE firmware images that allow computers without an iPXE implementation to perform an iPXE boot. Create a TFTP hosting directory and populate the directory with the iPXE firmware images with the following commands: .. code-block:: bash sudo mkdir -p $tftp_root sudo ln -sf /usr/share/ipxe/undionly.kpxe $tftp_root/undionly.kpxe #. The `pxe-server` bundle contains a lightweight TFTP, DNS, and DHCP server known as `dnsmasq`. Create a configuration file for `dnsmasq` to listen on a dedicated IP address for those functions. PXE clients on the private network will use this IP address. .. code-block:: console sudo cat > /etc/dnsmasq.conf << EOF listen-address=$pxe_internal_ip EOF #. Add the options to serve iPXE firmware images to PXE clients over TFTP to the `dnsmasq` configuration file. .. code-block:: console sudo cat >> /etc/dnsmasq.conf << EOF enable-tftp tftp-root=$tftp_root EOF #. Add the options to host a DHCP server for PXE clients to the `dnsmasq` configuration file. .. code-block:: console sudo cat >> /etc/dnsmasq.conf << EOF dhcp-leasefile=/var/db/dnsmasq.leases dhcp-authoritative dhcp-option=option:router,$pxe_internal_ip dhcp-option=option:dns-server,$pxe_internal_ip dhcp-match=set:pxeclient,60,PXEClient* dhcp-range=tag:pxeclient,$pxe_subnet.2,$pxe_subnet.253,$pxe_subnet_mask_ip,15m dhcp-range=tag:!pxeclient,$pxe_subnet.2,$pxe_subnet.253,$pxe_subnet_mask_ip,6h dhcp-match=set:ipxeboot,175 dhcp-boot=tag:ipxeboot,http://$pxe_internal_ip:$ipxe_port/$ipxe_app_name/ipxe_boot_script.ipxe dhcp-boot=tag:!ipxeboot,undionly.kpxe,$pxe_internal_ip EOF The configuration provides the following important functions: * Directs PXE clients without an iPXE implementation to the TFTP server to acquire architecture-specific iPXE firmware images that allow them to perform an iPXE boot. * Activates only on the network adapter that 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 pool is for network boot and one pool is used after boot. Each pool has their own lease times. #. Create a file for `dnsmasq` to record the IP addresses it provides to PXE clients. .. code-block:: bash sudo mkdir -p /var/db sudo touch /var/db/dnsmasq.leases #. Start `dnsmasq` and enable startup on boot. .. code-block:: bash sudo systemctl enable dnsmasq sudo systemctl restart dnsmasq #. Start `systemd-resolved`. .. code-block:: bash sudo systemctl start systemd-resolved .. note:: `systemd-resolved` dynamically updates the list of DNS servers for the private network if you use the `dnsmasq` DNS server. The setup creates a pass-through DNS server that relies on the DNS servers listed in :file:`/etc/resolv.conf`. #. Power on the PXE client and watch the client boot and install |CL|. After booting, |CL| automatically partitions the hard drive, installs itself, updates to the latest version, and reboots. **Congratulations!** You have successfully installed and configured a PXE server that enables PXE clients to boot and install |CL| over the network. .. _iPXE: http://ipxe.org/ .. _ICIS GitHub repository: https://github.com/clearlinux/ister-cloud-init-svc