Install a TFTP server on Fedora 16+

I tend to need to use TFTP to boot various embedded ARM systems. This is my short for-my-own-consumption guide on how to get that up and running on recent Fedora versions (2012).

Install and configure the server (Fedora 22 and later)

dnf install -y tftp-server tftp
firewall-cmd --permanent --add-service=tftp
firewall-cmd --reload
systemctl enable tftp.service
systemctl start tftp.service

This currently installs the HPA TFTP server as a systemd service.

If you want to e.g. change the root directory for the TFTP server you can edit /usr/lib/systemd/system/tftp.service

Install and configure the server (old style, Fedora 21 and earlier)

yum install -y tftp-server tftp

edit: /etc/xinet.d/tftp

disable = no

Execute configuration:

/sbin/chkconfig tftp on
systemctl enable xinetd.service
systemctl start xinetd.service

Older way of doing the same thing (pre Fedora 16):

/sbin/chkconfig tftp on
/sbin/chkconfig xinetd on
/sbin/service xinetd on

Set up the boot dir to be read/writeble

Since the server by default will serve binaries from /var/lib/tftpboot I usually just make this globally readable for all user so I can recompile and write new kernels (uImage files) there:

chmod a+w /var/lib/tftpboot

Open the firewall

Fedora does not automatically disable the firewall for services that you install and configure (not always very helpful...) Current approach:

dnf install -y firewall-config

Edit "services" for "permanent" and "runtime" to enable/open up service "tftp" on the local network (Fedora Workstation). Beware of the different zones!

Set up the firewall config to let TFTP through on the FedoraWorkstation or whatever the default zone is, and do it on the interface you plan to use.

This should be enough for TFTP to get through, and you should be able to test it, see below.

There may be some bug with TFTP preset (kernel issue). Then just open UDP on port 69 manually.

Older low-level approaches

In some older versions just edit /etc/sysconfig/iptables and open port 69 (TFTP) for UDP.

I am sure the graphical client for firewall configuration can be used for this too. The resulting rule will look something like this:

-A INPUT -m state --state NEW -m udp -p udp --dport 69 -j ACCEPT

Then kick the Firewall with:

/etc/init.d/iptables restart

Test

Copy some file to /var/lib/tftpboot

Try to fetch it from localhost:

tftp localhost
get foo.txt

Try to fetch it from some other host by using the IP number. If it works, you're up and running.

Using a crossed ethernet-cable

When I do development on the road or on a computer connect to a wireless network where I do not have any local 192.168.1.x network, I avoid the hassle of using a local network for the machine by simply using a crossed ethernet-cable from the ethernet port on my computer, and setting up a local link.

Also doing DHCP/BOOTP

Sometimes you want to assign clients a local IP number and serve them the kernel over TFTP right after that. A simplified version is to use BOOTP that just assigns an IP number and then serves the file using TFTP.

To do this, first install the ISC DHCP server package:

dnf -y install dhcp-server

Edit /etc/dhcp/dhcpd.conf, if you want it to simply give a static IP number and a file to a certain ethernet hardware address do the following:

subnet 169.254.1.0 netmask 255.255.255.0 {
    option subnet-mask 255.255.255.0;
    range dynamic-bootp 169.254.1.10 169.254.1.100;
    host tg784n {
        hardware ethernet xx:xx:xx:xx:xx:xx;
        default-lease-time 200000;
        next-server 169.254.1.1;
        filename "/zImage";
    }
}

This tells the following to the DHCP server: we are managing the link-local IP address range in 169.254.1.0. Someone with the ethernet hardware address xx:xx:xx:xx:xx:xx will appear, give them an IP number from the pool in 169.254.1.10 thru 169.254.1.100 and the tell them to get the file /zImage from the server at 169.254.1.1. This will be done using TFTP so you need the TFTP server up and running as well.

Then fire up the DHCP server:

ifup <MY-ETHERNET-INTERFACE>
systemctl enable dhcpd.service
systemctl start dhcpd.service

You may have to bring the statically assigned DHCP interface up and restart DHCP every time you reboot the client.