This is TOR installation on Debian distro.
104
A tiny container that runs Tor — the privacy network.
By default it works as a SOCKS5 proxy on port 9050. With a single environment variable (TOR_RELAY=1) the same container also becomes a Tor relay (ORPort 9001 + DirPort 9030) — it can run as client and relay at the same time.
It's built on Debian trixie-slim with Tor from the official Debian repositories, keeps the image small (~90 MB) and easy to audit. Tor runs as PID 1, so the container shuts down gracefully on SIGTERM (no SIGKILL after timeout).
When the container starts, the Tor circuit bootstrap process begins. From start to an established connection it can take a few minutes — longer on the very first boot, faster afterwards when
/var/lib/toris persisted. Please be patient during this time.
9050, reachable from other machines on your network (SocksPort 0.0.0.0:9050).TOR_RELAY=1): participates in the Tor network by routing traffic for other users, via the ORPort (9001) and the directory service DirPort (9030), with configurable nickname, contact info and bandwidth limits.torrc is generated at every start by a small entrypoint script, so there is nothing to edit inside the container.The image is published on Docker Hub as eduardoenemark/tor.
Create a docker-compose.yml:
version: '3.8'
services:
tor:
image: docker.io/eduardoenemark/tor:1.1
container_name: tor
restart: always
stop_grace_period: 5s
ports:
- "0.0.0.0:9050:9050/tcp" # SOCKS5 proxy
volumes:
- "~/.cache/log/tor:/var/log/tor"
- "~/.cache/data/tor:/var/lib/tor"
deploy:
resources:
limits:
cpus: 1
memory: 512m
Then run:
podman-compose up -d --build
podman run --name tor --restart always --stop-timeout 5 \
--publish 0.0.0.0:9050:9050/tcp \
--volume ~/.cache/log/tor:/var/log/tor \
--volume ~/.cache/data/tor:/var/lib/tor \
--cpus 1 --memory 512m \
docker.io/eduardoenemark/tor:1.1
Add TOR_RELAY=1 (and optionally a nickname / contact info / bandwidth limits):
version: '3.8'
services:
tor:
image: docker.io/eduardoenemark/tor:1.1
container_name: tor
restart: always
stop_grace_period: 5s
environment:
- TOR_RELAY=1
- TOR_NICKNAME=myrelay # 1-19 chars, [a-zA-Z0-9]
- [email protected] # recommended for relays
# - TOR_ADDRESS=203.0.113.10 # only behind NAT with port forwarding (see below)
- TOR_BANDWIDTH_RATE=5242880 # bytes/s (see note below)
- TOR_BANDWIDTH_BURST=10485760 # bytes/s
ports:
- "0.0.0.0:9050:9050/tcp" # SOCKS5 (your own traffic)
- "0.0.0.0:9001:9001/tcp" # ORPort — relay traffic
- "0.0.0.0:9030:9030/tcp" # DirPort — directory service
volumes:
- "~/.cache/log/tor:/var/log/tor"
- "~/.cache/data/tor:/var/lib/tor"
deploy:
resources:
limits:
cpus: 1
memory: 512m # Tor Project recommends >=512 MB for relays <40 Mbit/s
git clone https://github.com/eduardoenemark/containers-tor.git
cd containers-tor
./build.sh # builds localhost/tor:<version> (name/version parsed from OCI labels)
./start.sh # client mode (compose.yaml)
./start.sh relay # relay mode (compose-relay.yaml)
./stop.sh
| Port | Mode | Description |
|---|---|---|
9050/tcp | always | SOCKS5 proxy port (SocksPort 0.0.0.0:9050) |
9001/tcp | relay only | ORPort — other Tor nodes connect here to route circuits through your relay |
9030/tcp | relay only | DirPort — directory service that serves node/consensus information. Since Tor 0.4.6.1-alpha non-authoritative relays no longer advertise this port in the consensus (modern clients fetch directory documents through the ORPort), but it still listens and answers — useful for inspection/replication of node info |
| Variable | Default | Description |
|---|---|---|
TOR_SOCKET_PORT | 9050 | SOCKS5 port (client mode) |
TOR_RELAY | 0 | Set to 1 to enable relay mode |
TOR_ADDRESS | (empty → Tor guesses) | Address other Tor nodes connect to (relay mode). Behind NAT with port forwarding, set it to the public IP the router forwards 9001/9030 to |
TOR_OR_PORT | 9001 | Relay ORPort |
TOR_DIR_PORT | 9030 | Relay DirPort |
TOR_NICKNAME | (empty → Unnamed) | Relay identity: 1–19 chars, [a-zA-Z0-9] only |
TOR_CONTACT_INFO | (empty) | How the Tor Project can contact you about the relay (strongly recommended) |
TOR_BANDWIDTH_RATE | 5242880 | Sustained bandwidth limit for relay traffic, bytes/s (≈ 40 Mbit/s) |
TOR_BANDWIDTH_BURST | 10485760 | Burst bandwidth limit, bytes/s (≈ 84 Mbit/s) |
Bandwidth units: Tor measures
BandwidthRate/BandwidthBurstin bytes per second, not bits. The defaults above are 5 / 10 MiB/s (≈ 40 / 84 Mbit/s). If your line is smaller, lower the values — e.g. to cap a home relay at 5 Mbit/s sustained use625000. Bandwidth limits are strongly recommended for any relay: they protect your connection from being saturated by relay traffic.
| Path in container | Suggested host path | Purpose |
|---|---|---|
/var/log/tor | ~/.cache/log/tor | Tor logs (notices.log + stdout) |
/var/lib/tor | ~/.cache/data/tor | Tor state: identity key, geoip, circuit state. Persisting it makes the second and later bootstraps much faster, and for a relay this is where the long-term identity key lives — keep the volume if you want to keep your relay's identity |
torrc is generatedAt every start, /usr/local/bin/tor-entrypoint.sh regenerates /etc/tor/torrc from the environment variables above and then execs Tor as PID 1. There is no static config file in the image: all configuration happens through environment variables, and manual edits inside the container are overwritten on restart.
Point any application at the proxy:
localhost (on the same machine) or the host's IP on your network9050# Your exit IP is now a Tor exit node, not your own IP:
curl --socks5-hostname localhost:9050 https://api.ipify.org
# Official check:
curl --socks5-hostname localhost:9050 https://check.torproject.org/api/ip
# → {"IsTor":true}
Browsers, curl, git and most tools support SOCKS5 directly (e.g. git config --global http.proxy socks5h://127.0.0.1:9050). If you need a plain HTTP forward proxy instead, see the companion image eduardoenemark/tor-proxy (Tor + Privoxy on port 55455).
In relay mode Tor keeps working as your SOCKS5 client at the same time — you can route your own traffic through your own relay.
Reachability: for your relay to carry other nodes' traffic it must be reachable from the Internet — a public IP, or port forwarding for 9001 (and optionally 9030) on your router. By default Tor guesses the address to advertise; behind NAT with port forwarding, set TOR_ADDRESS to the public IP the router forwards to, so other relays can actually connect (e.g. TOR_ADDRESS=203.0.113.10). Inside containers without a directly reachable address (e.g. rootless Podman with slirp4netns), bootstrap still works for your own circuits — but other nodes cannot route through the relay until it has a reachable address.
Checklist for a public relay:
TOR_NICKNAME set (unique, memorable)TOR_CONTACT_INFO set — so the Tor Project can reach you if there are issues with your relay/var/lib/tor — that's where the relay identity key livescurl http://localhost:9030/tor/status → OK Tor version=...notice level goes to stdout (podman logs tor / docker logs tor) and to /var/log/tor/notices.log (persisted in the volume).Bootstrapped 100% (done) — that's when the proxy is ready.podman ps / docker ps shows the container as healthy once bootstrap completes (a 10 minute start period covers slow first boots).notices.log is rotated to notices.log.1 (previous generations kept up to .3), so the current file only contains this run's log.podman-compose if you use the compose files)9050 free on the host (and 9001/9030 in relay mode)no-new-privileges plus all capabilities dropped except CHOWN, SETUID and SETGID — the minimum set (the entrypoint chowns the persistent volumes at startup, and Tor drops from root to its unprivileged user). Tor itself runs as the debian-tor user after startup. If you run without these restrictions (plain docker run/podman run) everything still works; the caps are only needed for the hardened setup.notice level) and read the Tor Project's relay guidance before publishing one.Bootstrapped 100% (done) in the logs.SocksPort 0.0.0.0:9050 (a bare SocksPort 9050 binds to loopback only inside the container and silently breaks published ports).Problem bootstrapping warnings. If Tor cannot determine its own address you'll see Unable to find IPv4 address for ORPort; set TOR_ADDRESS explicitly (see Reachability above).containers-tor/
├── Containerfile # debian trixie-slim + tor, OCI labels, entrypoint
├── tor-entrypoint.sh # generates /etc/tor/torrc from env vars, execs Tor (PID 1)
├── compose.yaml # client mode
├── compose-relay.yaml # relay mode (TOR_RELAY=1 + ORPort/DirPort)
├── build.sh # builds localhost/tor:<version> (name/version from OCI labels)
├── start.sh [client|relay]
└── stop.sh
This project is licensed under the GPL-3.0.
Content type
Image
Digest
sha256:f82d66abf…
Size
32.1 MB
Last updated
17 days ago
docker pull eduardoenemark/tor:1.1