If you just want to run it now on Linux, follow these steps.
cd /opt
sudo mkdir -p /opt/ctftp
cd /opt/ctftp
# Download static Linux binary
sudo curl -L -o ctftp-static-linux \
https://github.com/seifzadeh/ctftp/releases/download/0.0.1/ctftp-static-linux
# Make it executable
sudo chmod +x ctftp-static-linux
# Root directory for TFTP files
sudo mkdir -p /srv/tftp
# Log directory for ctftp
sudo mkdir -p /var/log/ctftp
# Optional: dedicated user (recommended)
sudo useradd -r -s /usr/sbin/nologin ctftp || true
sudo chown -R ctftp:ctftp /srv/tftp /var/log/ctftp /opt/ctftp
Create /opt/ctftp/ctftp.conf:
# Root directory for TFTP files
root_dir=/srv/tftp
# Log directory (central log file)
log_dir=/var/log/ctftp
# One or more listeners (comma-separated)
# Standard TFTP port 69 on all interfaces
listeners=0.0.0.0:69
# Optional UDP event target (host:port)
event_udp=
# Optional HTTP event URL (plain HTTP)
event_http_url=
# Timeout and retries
timeout_sec=3
max_retries=5
# Log level: error, info, debug
log_level=info
Place one test file in /srv/tftp, for example:
echo "hello from ctftp" | sudo tee /srv/tftp/test.txt
sudo chown ctftp:ctftp /srv/tftp/test.txt
cd /opt/ctftp
sudo -u ctftp ./ctftp-static-linux ./ctftp.conf
Now, from another machine (or the same one), you can test with any TFTP client, for example:
tftp <server-ip> 69
tftp> get test.txt
If everything is correct, you should receive test.txt from /srv/tftp.
To run ctftp as a background service on a systemd-based Linux distribution:
Create /etc/systemd/system/ctftp.service with:
[Unit]
Description=ctftp - Multi-threaded TFTP server
After=network.target
[Service]
Type=simple
User=ctftp
Group=ctftp
WorkingDirectory=/opt/ctftp
ExecStart=/opt/ctftp/ctftp-static-linux /opt/ctftp/ctftp.conf
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Make sure the paths match your actual installation (
/opt/ctftp, config file path, and binary name).
sudo systemctl daemon-reload
sudo systemctl enable ctftp
sudo systemctl start ctftp
sudo systemctl status ctftp
If everything goes well, ctftp should be running in the background and listening on the configured port(s).
The main log file is written under log_dir (from your config), usually:
sudo tail -f /var/log/ctftp/ctftp.log
Example log lines:
[2025-12-02T10:15:42] [INFO] ctftp starting with config: /opt/ctftp/ctftp.conf
[2025-12-02T10:15:42] [INFO] Starting listener on 0.0.0.0:69
[2025-12-02T10:16:01] [INFO] RRQ from 192.168.10.50:40000 file="test.txt" mode="octet"
[2025-12-02T10:16:02] [INFO] EVENT type=0 client=192.168.10.50:40000 file="test.txt" bytes=16 status=ok msg=transfer_complete
For each requested file, ctftp appends a line to a sidecar log file in root_dir with the same name plus .log:
/srv/tftp/test.txt
/srv/tftp/test.txt.log
View it with:
sudo cat /srv/tftp/test.txt.log
Example content:
2025-12-02T10:16:01;2025-12-02T10:16:02;192.168.10.50;40000;16;ok;transfer_complete
This makes it easy to audit which clients have downloaded which files and when.
ctftp uses a simple key/value configuration file (usually ctftp.conf).
Common options:
root_dir โ directory from which TFTP files are served.log_dir โ directory for the central ctftp.log.listeners โ comma-separated list of IP:port pairs, for example:
0.0.0.0:69192.168.10.10:69,192.168.10.11:1069event_udp โ optional UDP target for JSON events, e.g. 127.0.0.1:9999.event_http_url โ optional HTTP URL for JSON events over POST.timeout_sec โ timeout when waiting for ACK.max_retries โ max retransmission attempts per block.log_level โ error, info, or debug.For more detailed documentation, see the main project README in the repository.
If you find ctftp useful:
Thanks for using ctftp!