Docker and Podman
The all-in-one image contains Tidefetch, the embedded web UI and Alpine's aria2 package. It runs as UID/GID 1000 and needs two writable volumes and a password.
ghcr.io/thre4dripper/tidefetch:latest # GitHub Container Registry
ijlalahmad/tidefetch:latest # Docker Hub mirror
Images are built for linux/amd64 and linux/arm64, and Docker picks the right one. Every release adds tags such as 0.1.0 and 0.1 next to latest. Use latest to try it out and a release tag for anything you rely on.
docker run
docker run -d \
--name tidefetch \
--restart unless-stopped \
--security-opt no-new-privileges \
--cap-drop ALL \
-p 8210:8210 \
-p 6881:6881 \
-p 6881:6881/udp \
-e TIDEFETCH_PASSWORD='replace-this-password' \
-e TZ='Etc/UTC' \
-v /srv/tidefetch/config:/config \
-v /srv/downloads:/downloads \
ghcr.io/thre4dripper/tidefetch:latest
Open http://<server-ip>:8210 and sign in with the password. The container runs tidefetch serve -host 0.0.0.0 -port 8210 -dir /downloads, which refuses to start without a password because it listens on all interfaces.
Docker Compose
A minimal standalone file:
services:
tidefetch:
image: ghcr.io/thre4dripper/tidefetch:latest
container_name: tidefetch
restart: unless-stopped
environment:
TIDEFETCH_PASSWORD: replace-this-password
TZ: Etc/UTC
ports:
- "8210:8210" # web UI
- "6881:6881" # BitTorrent peers, optional
- "6881:6881/udp" # DHT and UDP trackers, optional
volumes:
- /srv/tidefetch/config:/config
- /srv/downloads:/downloads
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
docker compose up -d
docker compose logs -f --tail=100 tidefetch
Keep the password out of the file
Use a Compose secret and TIDEFETCH_PASSWORD_FILE instead of a plain environment value:
services:
tidefetch:
environment:
TIDEFETCH_PASSWORD_FILE: /run/secrets/web_password
secrets:
- web_password
secrets:
web_password:
file: ./secrets/web_password
mkdir -p secrets && umask 077
openssl rand -base64 36 > secrets/web_password
docker compose up -d
The repository's packaging/docker/docker-compose.secrets.yml is this overlay. Apply it with -f docker-compose.yml -f docker-compose.secrets.yml.
Build from source instead
git clone https://github.com/Thre4dripper/tidefetch.git
cd tidefetch/packaging/docker
cp .env.example .env && chmod 600 .env # set TIDEFETCH_PASSWORD in .env
docker compose up -d --build
Volumes and permissions
| Mount | Holds |
|---|---|
/config |
config.json (settings, RPC secret, password hash), history.json, the aria2 session and DHT tables |
/downloads |
Finished files, plus .aria2 control files for downloads in progress |
Both are required. Without /config, the queue, history and password reset on every restart. Data and persistence lists every file.
For bind mounts, hand the directories to UID/GID 1000 first:
sudo mkdir -p /srv/tidefetch/config /srv/downloads
sudo chown -R 1000:1000 /srv/tidefetch/config /srv/downloads
sudo chmod 700 /srv/tidefetch/config
On SELinux hosts append :Z to both bind mounts. With rootless Podman, use podman unshare chown -R 1000:1000 <path> when direct ownership does not map.
Ports
| Port | Required | Purpose |
|---|---|---|
8210/tcp |
Yes | Web UI and HTTP API |
6881/tcp |
No | Incoming BitTorrent peers |
6881/udp |
No | DHT and UDP trackers |
aria2's RPC listener stays on loopback inside the container. Never publish port 6800.
Behind a reverse proxy
When Caddy, Nginx or Traefik also runs in Docker, put both on a shared network and stop publishing 8210 on the host:
docker network create proxy
services:
tidefetch:
networks: [proxy]
# no "ports:" entry for 8210
networks:
proxy:
external: true
Proxy to http://tidefetch:8210. See Reverse proxy and TLS.
Everyday operations
docker compose ps # status and health
docker compose logs -f tidefetch # logs
docker compose restart tidefetch # graceful restart
docker compose pull && docker compose up -d # upgrade
docker compose down # stop; volumes stay
docker exec tidefetch tidefetch doctor # diagnostics inside the container
The image has a health check that requests / every 30 seconds:
docker inspect --format '{{json .State.Health}}' tidefetch
Stop with docker compose stop rather than docker kill, so aria2 flushes its session first.
Backup and restore
Stop the service for a consistent copy of /config:
docker compose stop tidefetch
sudo tar -C /srv/tidefetch -czf "tidefetch-config-$(date +%F).tar.gz" config
docker compose start tidefetch
Restore into a stopped service and fix ownership:
docker compose down
sudo mv /srv/tidefetch/config /srv/tidefetch/config.old
sudo mkdir /srv/tidefetch/config
sudo tar -C /srv/tidefetch/config -xzf tidefetch-config-2026-01-31.tar.gz --strip-components=1
sudo chown -R 1000:1000 /srv/tidefetch/config
docker compose up -d
Podman
podman run -d --name tidefetch --replace \
-p 8210:8210 \
-e TIDEFETCH_PASSWORD='replace-this-password' \
-v tidefetch-config:/config:Z \
-v /srv/downloads:/downloads:Z \
ghcr.io/thre4dripper/tidefetch:latest
Use Quadlet or podman generate systemd for a service that starts at boot.