How to install ZorinOS 16 over the network
In case of lacking any form of external media device such as a USB, CD-ROM, hard drive, etc., it's still possible to install ZorinOS 16 over the network using another computer as an TFTP server. This guide attempts to provide straight forward step-by-step instructions to run a TFTP server from which to load the ZorinOS 16 ISO.
There are multiple ways to set this up. Different resources found online may differ from the instructions listed here. In addition, the exact files to be used vary from one distribution to another. Keep all of this in mind when comparing this guide with other resources.
Requirements
-
A separate computer running on the same local network. This guide will assume that it runs Debian 12; other flavors of Linux should work the same but the package names and/or configuration files may be different. If you don't have Linux you can follow along from within a virtual machine, as long as it has access to the local network.
-
A TFTP server, to serve the bootloader over the network.
-
A DHCP server with proxy capabilities, to specify the path to the bootloader that is served by the TFTP server.
-
A HTTP server to serve the ISO image file.
-
ZorinOS 16 ISO file.
The TFTP and DHCP servers are provided by the same package, dnsmasq
. The HTTP server will be provided by Python's http.server
module since it's already installed by default in most Linux distributions, but any other software will do.
Install Dependencies
Let's get started with the basics, installing all the necessary software to setup our servers.
sudo apt install pxelinux syslinux dnsmasq
Configure dnsmasq
Despite the name, dnsmasq
can do more than providing a DNS server, which in fact is one thing that we do not need for this. The first step will be to disable this.
Before making any changes to configuration files it's a good idea to make a backup copy of the original. Now let's edit it with the following options. Please read the comments for details on what each line does:
sudo cp /etc/dnsmasq.conf /etc/dnsmasq.conf.bak
sudo nano /etc/dnsmasq.conf /etc/dnsmasq.conf
# Disables DNS server
port=0
# Enables the TFTP server
enable-tftp
# Specifies the path for the files served by the TFTP server.
tftp-root=/srv/tftp
# After the initial connection with the TFTP server, a random port will be
# selected by the OS for all subsequent exchanges. Specifying a range of
# ports here will allow to narrow the list of random ports to be used,
# making it easier to create predictable firewall traffic rules. The ports
# must be under 1025 (unless running as root) and not in use.
tftp-port-range=7000,7100
# The local network range to listen for DHCP requests. Adjust this to point
# to your own address range as needed. The proxy option will prevent the
# DHCP server from attempting to provide IP addresses to other devices on
# the network. Instead it will provide details about the location of the
# PXE server.
dhcp-range=192.168.1.0,proxy
# Bootloader to use for BIOS powered devices.
pxe-service=x86PC,"PXELINUX (BIOS)",bios/pxelinux
# Bootloader to use for UEFI powered devices.
pxe-service=x86-64_EFI,"PXELINUX (EFI)",efi64/syslinux.efi
# Useful for debugging and seeing the traffic generated.
log-queries
log-facility=/var/log/dnsmasq.log
We need to create the directory where the TFTP server will be serving files from, as specified in the configuration above.
sudo mkdir /srv/tftp/
Inside this directory we want to create another two directories, containing the files required by BIOS and UEFI powered systems, respectively.
sudo mkdir -p /srv/tftp/{bios,efi64}
And restart the dnsmasq
service.
sudo systemctl restart dnsmasq.service
Place the bootloader files into the TFTP root
We need a bootloader, among other things. These files will be served by the TFTP server, which we got from the packages that we installed earlier. All we need to do is place them inside the TFTP server root as defined in the dnsmasq.conf
file:
sudo cp /usr/lib/syslinux/modules/bios/{ldlinux,vesamenu,libcom32,libutil}.c32 /usr/lib/PXELINUX/pxelinux.0 /srv/tftp/bios
And repeat the process for the UEFI files:
sudo cp /usr/lib/syslinux/modules/efi64/ldlinux.e64 /usr/lib/syslinux/modules/efi64/{vesamenu,libcom32,libutil}.c32 /usr/lib/SYSLINUX.EFI/efi64/syslinux.efi /srv/tftp/efi64
Create the GRUB menu options
Next, we need to create the define the GRUB menu options. For that we need to create a directory called pxelinux.cfg
with a single file, default
. This file will have a very bare menu with a single option for ZorinOS, but it'll do. It will have the following contents:
UI vesamenu.c32
LABEL zorin 16 core network boot
MENU LABEL ZORIN 16.3 CORE
KERNEL ::boot/casper/vmlinuz
INITRD ::boot/casper/initrd.lz4
APPEND root=/dev/ram0 ramdisk_size=1048576 ip=dhcp netboot=url url=192.168.1.10/Zorin-OS-16.3-Core-64-bit.iso
The KERNEL
and INITRD
lines define the files served by the TFTP server, that are used to boot over the network. The ::
serves as a placeholder for the root directory as defined in dnsmasq.conf
. This means that we need have to have a boot
directory containing these temporary bootloader and kernel files, which we'll create next.
The APPEND
line defines additional parameters for the kernel. Here we specify how to boot and where to load the actual live ISO file. Make sure the IP address points to the right server. It may work with domain names as well but I haven't tried it.
In order to use this file regardless of whether the client machine runs on BIOS or UEFI, we can create symbolic links to it in either of the respective folders we created earlier.
sudo ln -s /srv/tftp/pxelinux.cfg /srv/tftp/bios/pxelinux.cfg
sudo ln -s /srv/tftp/pxelinux.cfg /srv/tftp/efi64/pxelinux.cfg
Extract the ISO files
As per the previous step, we need to provide the files to initialize the OS over the network. We can get these from the ZorinOS ISO by mounting it somewhere in the file system temporarily, and then copying the relevant files to our TFTP root.
sudo mkdir /mnt/zorin16
sudo mount -o loop -t iso9660 ~/Downloads/Zorin-OS-16.3-Core-64-bit.iso /mnt/zorin16
And copy the files to our TFTP root folder.
sudo mkdir /srv/tftp/boot
sudo cp -r /mnt/zorin16/* /srv/tftp/boot/
At this point, we should have the following file structure for our TFTP server:
/srv/tftp
├── bios
│ ├── ldlinux.c32
│ ├── libcom32.c32
│ ├── libutil.c32
│ ├── pxelinux.0
│ ├── pxelinux.cfg -> /srv/tftp/pxelinux.cfg
│ └── vesamenu.c32
├── boot
│ ├── boot
│ ├── casper
│ ├── dists
│ ├── efi
│ ├── isolinux
│ ├── md5sum.txt
│ ├── pool
│ └── README.diskdefines
├── efi64
│ ├── ldlinux.e64
│ ├── libcom32.c32
│ ├── libutil.c32
│ ├── pxelinux.cfg -> /srv/tftp/pxelinux.cfg
│ ├── syslinux.efi
│ └── vesamenu.c32
└── pxelinux.cfg
└── default
Make Firewall Rules
Since you need to access files over the network we may need to create a few rules for the server firewall. These rules allow incoming traffic for the DCHP server (67), the initial connection to the TFTP server (69) and subsequent connections, as specified by the tftp-port-range
option in dnsmasq.conf
(in this example I chose a range between ports 7000 to 7100), the PXE server (4011) and HTTP server (80).
sudo ufw allow 67/udp
sudo ufw allow 69/udp
sudo ufw allow 4011/udp
sudo ufw allow 7000:7100/udp
sudo ufw allow 80/tcp
Run the HTTP server
Finally, start the HTTP server:
sudo python3 -m pip http.server 80 -d ~/Downloads
The -d
or --directory
option should point to the folder that contains the ISO file. In this example I'm using the Downloads folder, and also specifying the port which should be set to 80.
Start the target machine
Now, you're ready to start the target machine and choose the network book option. After a bit it will load the bootloader files and show the prompt that we created, with a single option for ZorinOS 16. Upon selecting this with Enter, it will load the iso file over HTTP and start up the live version of ZorinOS.