# nobodd-tftpd

A read-only TFTP server capable of reading FAT boot partitions from within image files or devices. Intended to be paired with a block-device service (e.g. NBD) for netbooting Raspberry Pis.

## Synopsis

    usage: nobodd-tftpd [-h] [--version] [--listen ADDR] [--port PORT]
                        [--board SERIAL,FILENAME[,PART[,IP]]]

## Options

-h, --help

  Show the help message and exit

--version

  Show program’s version number and exit

--board SERIAL,FILENAME[,PART[,IP]]

  Can be specified multiple times to define boards which are to be served boot images over TFTP; if PART is omitted the default is 1; if IP is omitted the IP address will not be checked

--listen ADDR

  The address on which to listen for connections (default: “::” for all addresses)

--port PORT

  The port on which to listen for connections (default: “tftp” which is port 69)

## Configuration

nobodd-tftpd can be configured via the command line, or from several configuration files. These are structured as INI-style files with bracketed `[sections]` containing `key=value` lines, and optionally #-prefixed comments. The configuration files which are read, and the order they are consulted is as follows:

1. `/etc/nobodd/nobodd.conf`

2. `/usr/local/etc/nobodd/nobodd.conf`

3. `$XDG_CONFIG_HOME/nobodd/nobodd.conf` (where `$XDG_CONFIG_HOME` defaults to `~/.config` if unset)

Later files override settings from files earlier in this order.

The configuration file may contain a `[tftp]` section which may contain the following values:

listen

  This is equivalent to the `--listen` parameter and specifies the address(es) on which the server will listen for incoming TFTP connections.

port

  This is equivalent to the `--port` parameter and specifies the UDP port on which the server will listen for incoming TFTP connections. Please note that only the initial TFTP packet will arrive on this port. Each “connection” is allocated its own ephemeral port on the server and all subsequent packets will use this ephemeral port.

includedir

  If this is specified, it provides the name of a directory which will be scanned for files matching the pattern `*.conf`. Any files found matching will be read as additional configuration files, in sorted filename order.

For example:

    [tftp]
    listen = 192.168.0.0/16
    port = tftp
    includedir = /etc/nobodd/conf.d

For each image the TFTP server is expected to serve to a Raspberry Pi, a `[board:SERIAL]` section should be defined. Here, “SERIAL” should be replaced by the serial number of the Raspberry Pi. The serial number can be found in the output of `cat /proc/cpuinfo` at runtime. For example:

    $ grep ^Serial /proc/cpuinfo
    Serial          : 100000001234abcd

If the serial number starts with 10000000 (as in the example above), exclude the initial one and all leading zeros. So the above Pi has a serial number of 1234abcd (in hexadecimal). Within the section the following values are valid:

image

  Specifies the full path to the operating system image to serve to the specified Pi, presumably prepared with nobodd-prep.

partition

  Optionally specifies the number of the boot partition. If this is not specified it defaults to 1.

ip

  Optionally limits serving any files from this image unless the IP address of the client matches. If this is not specified, any IP address may retrieve files from this share.

For example:

    [board:1234abcd]
    image = /srv/images/ubuntu-24.04-server.img
    partition = 1
    ip = 192.168.0.5

In practice, what this means is that requests from a client with the IP address “192.168.0.5”, for files under the path “1234abcd/”, will be served from the FAT file-system on partition 1 of the image stored at `/srv/images/ubuntu-24.04-server.img`.

Such definitions can be produced by nobodd-prep when it is provided with the `nobodd-prep --serial` option.

Boards may also be defined on the command-line with the `--board` option. These definitions will augment (and override, where the serial number is identical) those definitions provided by the configuration files.

## Systemd/Inetd Usage

The server may inherit its listening socket from a managing process. In the case of inetd(8) where the listening socket is traditionally passed as stdin (fd 0), pass “stdin” as the value of `--listen` (or the `listen` option within the `[tftp]` section of the configuration file).

In the case of systemd(1), where the listening socket(s) are passed via the environment, specify “systemd” as the value of `--listen` (or the `listen` option within the `[tftp]` section of the configuration file) and the service will expect to find a single socket passed in `LISTEN_FDS`. This will happen implicitly if the service is declared as socket-activated. However, the service must not use `Accept=yes` as the TFTP protocol is connection-less. The example units provided in the source code demonstrate using socket-activation with the server.

In both cases, the service manager sets the port that the service will listen on, so the `--port` option (and the `port` option in the `[tftp]` section of the configuration file) is silently ignored.

## See Also

nobodd-sh, nobodd-prep, nbd-server(1)

## Bugs

Please report bugs at: https://github.com/waveform80/nobodd/issues