RTFTP is a TFTP server powered by the libguestfs project, designed to serve files directly from remote disks over NBD. It enables serving NBD-placed boot-related data—such as kernel images, initrd files, or GRUB configurations—via the TFTP protocol. This approach makes it possible to update or modify boot data (e.g., kernel upgrades or initrd rebuilds) directly from within the device that uses the filesystem itself.
This is particularly useful for managing clusters of diskless bare-metal servers or TFTP-boot capable ARM boards such as the Raspberry Pi.
RTFTP serves each connected client IP address from a unique directory inside the tftp_root, similarly to DNSMASQ’s --tftp-unique-root option.
To enable a client with IP X.X.X.X to receive files from a remote NBD disk, create a JSON file named X.X.X.X.nbd inside the tftp_root directory with the following structure:
{
"url": "nbd://<NBD server host>:<port>/<NBD share name>",
"mounts": [
{
"partition": 2,
"mountpoint": "/"
},
{
"partition": 1,
"mountpoint": "/boot"
}
],
"tftp_root": "/boot"
}url: The NBD server URL. See the official NBD URI format.mounts: An ordered list of mount instructions to build a virtual filesystem from which files are served.- Mount the 2nd partition as
/. - Mount the 1st partition as
/boot.
- Mount the 2nd partition as
tftp_root: The virtual chroot for the TFTP server. A read request forkernel.imgwill resolve to/boot/kernel.imgwithin the virtual FS.
If no directory named <tftp_root>/x.x.x.x or corresponding NBD config <tftp_root>/x.x.x.x.nbd> is found, the system attempts to read the requested file from <tftp_root>/default>. This allows all peers to be served with a single file or enables RTFTP to function as a standard TFTP server.
Additionally, RTFTP supports proactive setup of NBD connections upon the appearance of an NBD configuration file by utilizing inotify subsystem. With this approach, the remote filesystem is already up and running before the first TFTP request arrives.
TFTP root directory layout:
tftp_root/
├── 192.168.10.10/
│ └── grub/
│ └── grub.cfg
├── 192.168.10.10.nbd
└── default/
└── efi/
└── grubnetaa64.efi.signed
Contents of 192.168.10.10.nbd:
{
"url": "nbd://10.10.10.10:25000/server_root",
"mounts": [
{
"partition": 2,
"mountpoint": "/"
},
{
"partition": 1,
"mountpoint": "/boot"
}
],
"tftp_root": "/boot"
}In this example:
- The client with IP
192.168.10.10will receiveefi/grubnetaa64.efi.signedfrom the local filesystem from thetftp_root/defaultdirectory - The client with IP
192.168.10.10willgrub/grub.cfgfrom the local filesystem from a specifictftp_root/192.168.10.10directory. - Any other files will be retrieved by the client with IP
192.168.10.10from the remote NBD disk atnbd://10.10.10.10:25000/server_rootfrom inside/bootdirectory from the first partition. - Clients with any other IPs will be able to download only
efi/grubnetaa64.efi.signedfrom thetftp_root/192.168.10.10directory.
- Only Read Request (RRQ) is supported.
- If a file exists in both the local directory and the NBD-based filesystem, the local file takes precedence.
- If a file exists in both the
defaultdirectory and a client directory, the latter is downloaded. - Initial setup of the virtual NBD filesystem takes 1.5 to 3 seconds, so the first request usually need to be retried automatically by the client.
- The NBD disk is either:
- Connected proactively when config is created to avoid the first read request delay.
- Connected lazily on the first read request.
- An inactive NBD disk is automatically disconnected after a period of inactivity. This timeout is configurable via the
idle_timeoutdaemon argument. - Supported TFTP options:
- timeout
- blksize
- tsize
- windowsize
- The daemon is intended to run without root privileges. To allow RTFTP to bind to UDP port 69, one of following workarounds may be applied:
- Add CAP_NET_BIND_SERVICE capability to RTFTP:
setcap 'cap_net_bind_service=+ep' /path/to/rtftp - Start RTFTP via
authbindwith port 69 allowed for the RTFTP user:touch /etc/authbind/byport/69 && chown <rtftp_user>:<rtftp_group> /etc/authbind/byport/69
- Add CAP_NET_BIND_SERVICE capability to RTFTP: