How many admins does it take to roll out 150 client PCs in one morning?
The honest answer for most mid-sized companies: too many.
If people are walking from machine to machine with USB sticks, the approach is fundamentally wrong and inefficient. What is missing are clear concepts, monitoring, automation, and scalability. In that order.
Without automation, scaling turns into exploding personnel costs.
Without monitoring, automation becomes a force multiplier for mistakes.
Without clear concepts, monitoring ends up measuring the wrong things.
This lines up with a timeless quote from Kristian Köhntopp’s talk “Go away, or I will replace you with a very small shell script”:1
If an admin logs into a system to check something, your monitoring is broken. If an admin logs into a system to change something, your automation is broken.
This article covers mass client rollout using PXE/FAI, specifically for Debian GNU/Linux. The resulting gains in time and scalability are not just a technical topic. They reflect organizational maturity.
As always: your mileage may vary. This is not a complete guide. Some technical aspects are only outlined at a high level. Preseed is another deployment option,2 but not covered here. And before the usual objection from the Windows side: yes, Windows has deployment tools as well. Most are image-based, difficult to integrate into modern GitOps workflows, and come with additional infrastructure and licensing complexity.
Part I: Scope and prerequisites
The technical setup assumes a few basic conditions.
Dedicated rollout VLAN
This assumes a network segmented into VLANs.3 This is not a recommendation. It is standard practice. Printers, webcams, production systems, and test systems must be separated at the network level. Access and routing need to be controlled at the gateways.4
An FAI server5 and its clients belong in a dedicated rollout VLAN. These are typically new or still unknown systems. This setup prevents unintended PXE boots later in production and provides space for proper testing before rollout.
Existing DHCP and DNS servers
This also assumes an existing DHCP server in the rollout VLAN. That avoids having to configure exceptions for DHCP snooping on switches.6 Surprisingly, not all supposedly professional firewall systems allow proper configuration of DHCP options:7
- DHCP Option 66 next-server
- DHCP Option 67 filename
The same applies to DNS. For clients to reach something like http://fai.internal, DNS must be provided via DHCP Options 6 and 15.
64-bit Debian and UEFI only
A current 64-bit Debian stable with UEFI boot is used as the standard. This keeps legacy exceptions low and reduces overall complexity. The same applies to disk layout: GPT, an EFI system partition, and a single ext4 partition for everything. This setup covers most systems from the past 10 to 15 years. However exceptions may exist.
Transport protocols and TLS
As shown later in the boot chain, several transport protocols are involved. A combination of TFTP, HTTP, and NFS8 is typical for PXE/FAI setups. This improves performance and reduces load when many clients connect at the same time.
TLS is intentionally not used here, based on two considerations. First, the rollout happens in an isolated internal VLAN under full control. Second, skipping encryption reduces complexity and overhead. If the security context changes, TLS and custom certificates can be added later.
The post-install script
What happens after a fully automated rollout? A client starts its lifecycle in the rollout VLAN and moves into a production segment once installation completes.
The post-install script is essential. It handles package adjustments, configures remote access via SSH public keys,9 and prepares the system for automation tools such as Ansible. The real value becomes clear when systems register themselves via REST APIs in monitoring, asset management, and ticketing systems.
Part II: The FAI server
Now to the central component: the FAI server. It typically runs as a VM on a Proxmox host. Hardware requirements are minimal:
- 2 to 4 vCPUs
- 2 to 4 GB RAM
- about 30 GB storage for typical Debian rollouts
- a network interface in the rollout VLAN
The base system is Debian stable. Required packages are available in the standard repository:
# apt install -y fai-server fai-setup-storage apache2 php-fpm tftpd-hpa ipxe
After installation, run fai-install to prepare the server. The system can operate fully offline, but should be up to date before a rollout.
Proxmox test environment with one FAI server and one virtual client
FAI configuration and class model
Installing the required packages does not make the FAI server ready for use. The key part is the directory-based configuration. The central directory is /srv/fai/config. This is where the desired target state is defined across several subdirectories and classes:
- class/ - definition of deployment classes
- disk_config/ - partitioning and filesystems
- package_config/ - packages to install
- files/ - files copied into the target system
- scripts/ - installation and post-install scripts
A few words on the FAI class model. A class is assigned to a client during the boot process. A client can have multiple classes at the same time. The final configuration is the result of how those classes combine.
For example, the DEFAULT class defines a minimal base system that applies to all clients, regardless of their role. A system only becomes a workstation once it is also part of the WORKSTATION class, which adds a graphical interface and the required applications. Another class, such as TERMINAL, sets up a minimal graphical environment with autologin and a browser running in kiosk mode.14
Example DEFAULT class in /config/package_config/DEFAULT:
PACKAGES install
ca-certificates
locales
sudo
openssh-server
curl
mc
The result is a deterministically reproducible system whose state is fully defined by its classes.
Part III: Fully automated rollout
Now to the operational side. With new systems, this often means unpacking and setting up many machines in a suitable space. With existing systems, it is simpler. You walk through the company and rely on proper switch management and network documentation.
Prepare BIOS/UEFI
Ideally, systems are standardized and preconfigured for PXE. In practice, you often need to adjust BIOS/UEFI settings:
- Enable PXE15
- Enable UEFI or disable legacy boot16
- Disable Secure Boot if necessary (recommended)17
- Adjust boot order (PXE first, then disk)
This is the only manual step. With basic instructions, it can be handled by support staff or even users.
The boot chain
When a client starts in PXE mode, it receives all required network information via DHCP. This includes the boot server and the network boot program. Typical examples are ipxe.efi for UEFI or undionly.kpxe for legacy BIOS. Details vary by hardware, but the overall process remains the same.
Simplified, the boot chain works as follows:
- PXE is initialized by firmware (BIOS/UEFI)
- Boot information is provided via DHCP
- The iPXE network boot program is loaded via TFTP
- iPXE loads kernel and initrd via HTTP
- The root filesystem is provided via NFS
From there, the actual OS installation begins. The result is a consistent, reproducible system ready for production.
PXE booting client in test environment
Part IV: Optimizations
Rolling out hundreds or thousands of clients requires additional tuning.
Web server
The web server becomes a bottleneck under heavy parallel load if left at default settings. Adjusting worker and KeepAlive settings usually helps. In more advanced setups, load-balancing proxies distribute traffic across multiple servers.18
Collect MAC addresses
MAC addresses of new systems are often unknown at first boot but needed for firewall configuration.19 A simple PHP script on the FAI server can collect them during boot by calling:
http://fai.internal/fai/start.php?mac=XXXXXXXX
The script writes the address to a file. The request should not be chained.
Naming and inventory
There are three common approaches:
Same idea as MAC collection. A PHP script returns a hostname with an incrementing index, for example
PC-005. The script reads a counter from a file, increments it, and writes it back, using file locking for concurrent access.20The post-install script can call REST APIs (via curl) of systems like GLPI,21 iTop,22 or Snipe-IT23 to retrieve assigned hostnames and apply them using
hostnamectl.If Ansible is already in use, it can take over. FAI provides the base state, Ansible handles further configuration.24
Versioning
FAI configuration and scripts can be stored in a Git repository and managed as part of a GitOps workflow.25
PXE booted minimal system in test environment
Conclusion
The real problem in mass rollouts is rarely technical. It is the maturity of the organization.
What is the point of a fully automated deployment in minutes if all systems still need to be manually added to inventory afterward? This brings us back to the basics: clear concepts, monitoring, automation, and scalability. In that order.
With a fully automated PXE/FAI rollout, deploying 150 client PCs in one morning is no longer a heroic effort. It becomes a predictable, scalable, and deterministic process.
The good news: this level of maturity does not require large budgets. And stories about admin heroics are usually a sign of low maturity.
Best regards,
Tomas Jakobs
https://media.ccc.de/v/froscon2015-1500-go_away_or_i_will_replace_you_with_a_very_little_shell_script ↩︎
https://bsi.bund.de/SharedDocs/Downloads/DE/BSI/Grundschutz/IT-GS-Kompendium_Einzel_PDFs_2023/09_NET_Netze_und_Kommunikation/NET_1_1_Netzarchitektur_und_design_Edition_2023.pdf ↩︎
https://en.wikipedia.org/wiki/Trivial_File_Transfer_Protocol ↩︎
https://en.wikipedia.org/wiki/Preboot_Execution_Environment ↩︎
https://blog.jakobs.systems/micro/20210314-snipe-it-heise/ ↩︎
https://blog.jakobs.systems/micro/20230208-heuristik-des-tages/ ↩︎