ℹ Archived: This project is no longer maintained.
The updated repo is available here: kaczmar2/tftp-hpa-server
Docker Hub: https://hub.docker.com/r/kaczmar2/tftp-hpa
A minimal, secure TFTP server based on debian:bookworm-slim
and tftpd-hpa
.
# Clone or create the project directory
mkdir -p ~/docker/tftp-server && cd ~/docker/tftp-server
# Download docker-compose.yml
curl -O https://raw.githubusercontent.com/kaczmar2/tftp-hpa/main/docker-compose.yml
# Create .env file for configuration (optional)
curl -O https://raw.githubusercontent.com/kaczmar2/tftp-hpa/main/.env.example
cp .env.example .env
# Edit .env to set TZ and TFTP_ROOT if needed
# Create Docker bind mount directory
sudo mkdir -p /srv/docker/tftp
# Pull and start
docker compose up -d
# Check status
docker compose ps
docker logs tftp-server
docker run -d \
--name tftp-server \
--network host \
--restart unless-stopped \
-e TZ=America/Denver \
-v /srv/docker/tftp:/srv/tftp \
-v /etc/localtime:/etc/localtime:ro \
kaczmar2/tftp-hpa
services:
tftp:
container_name: tftp-server
image: kaczmar2/tftp-hpa
restart: unless-stopped
network_mode: host
environment:
- TZ=${TZ:-UTC} # Use .env file or default to UTC
volumes:
- ${TFTP_ROOT:-/srv/docker/tftp}:/srv/tftp
- /etc/localtime:/etc/localtime:ro
/srv/docker/tftp/ # Host directory (mapped to container)
├── file1.txt # File to serve via TFTP
├── file2.bin # File to serve via TFTP
└── subdirectory/ # Subdirectories are supported
└── nested-file.txt
It is useful to test your TFTP server with a TFTP client; you may simply use the tftp-hpa package for this purpose:
# Install TFTP client
sudo apt install tftp-hpa
Test file download:
cd /tmp
uname -a | sudo tee /srv/docker/tftp/test
tftp localhost
tftp> get test
tftp> quit
diff test /srv/docker/tftp/test
(nothing, they are identical)
# Real-time logs (includes TFTP requests and responses)
docker logs -f tftp-server
# Check for TFTP requests (RRQ = Read Request)
docker logs tftp-server | grep RRQ
# Check for file not found errors (NAK = Negative Acknowledgment)
docker logs tftp-server | grep NAK
Log format:
<29>
- RRQ (Read Request) messages<30>
- NAK (Error) messages like "File not found"- Timestamps use container timezone (configurable via TZ environment variable)
# Add files to serve (use actual host directory)
cp myfile.txt /srv/docker/tftp/
# Check what files are available
ls -la /srv/docker/tftp/
# Set proper permissions (readable by all)
chmod 644 /srv/docker/tftp/*
This container requires network_mode: host
because:
- TFTP uses dynamic ports - Data transfers use random ephemeral ports
- Port mapping doesn't work - Docker can't map unknown future ports
- Host networking is standard - Most TFTP Docker images use this approach
Ensure UDP port 69 is accessible.
The container supports customizing TFTP daemon behavior via the TFTP_ARGS
environment variable. You can pass any valid in.tftpd
options while keeping the current defaults as the base.
# Start container with --create flag to enable uploads
docker run -e TFTP_ARGS="--foreground --secure --create --verbosity 4 --user tftp" kaczmar2/tftp-hpa
Add to your .env
file:
# Enable write access with custom settings
TFTP_ARGS="-foreground --secure --create --verbosity 4 --user tftp"
See the tftpd man page for all available options.
When customizing TFTP_ARGS
, note these restrictions:
- Required options: Always include
--foreground --user tftp
for proper container operation and security - Conflicting options: Don't use
--listen
as it conflicts with--foreground
(required for containers) - Security: Avoid changing
--user
fromtftp
as this breaks the container's security model - Directory: The TFTP root directory is fixed to
/srv/tftp
and cannot be changed via arguments
Note: Setting up host directory permissions for TFTP uploads is beyond the scope of this README, as requirements vary by environment.
For general guidance when using --create
: the container process needs write access to the mounted directory. This typically involves setting appropriate permissions on the host directory before starting the container.