- Dockerfile 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| .forgejo/workflows | ||
| .dockerignore | ||
| .gitattributes | ||
| .gitignore | ||
| CLAUDE.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
| SECURITY.md | ||
| torrc | ||
Tor SOCKS Proxy
A lightweight Docker image (Alpine Linux + Tor) that provides a Tor SOCKS5 proxy and DNS-over-Tor resolver, without Tor relay/exit functionality. The image is rebuilt weekly to pick up Tor and Alpine security updates automatically.
This is a drop-in replacement for PeterDaveHello/tor-socks-proxy, from which it is derived (GPLv3). Same ports, same torrc path, same data directory, same tor user UID — just swap the image name.
AI Disclosure
This container was adapted from upstream by Claude AI and reviewed by me.
Differences from upstream
- Built from stable Alpine repos (no
@edge) and rebuilt weekly, so Tor stays current. Upstream's build broke whenobfs4proxywas removed from Alpine edge, leaving itslatestimage stuck on an old Tor. obfs4proxyreplaced with its maintained successor lyrebird./usr/bin/obfs4proxyis a symlink tolyrebird, so existing bridge configs keep working.- Healthcheck fixed: it now queries
https://check.torproject.org/api/ipthrough the proxy and requires"IsTor":true(the old Facebook onion URL no longer works). It runs every 5 minutes instead of every 30 seconds. - Version-pinned image tags (
tor-{VER}-alpine-{VER}) in addition tolatest. - Multi-arch:
linux/amd64,linux/arm64(Raspberry Pi 3/4/5 on a 64-bit OS) andlinux/arm/v7(32-bit Raspberry Pi OS) under the same tags.
Quick Start
Docker Compose
services:
tor-socks-proxy:
container_name: tor-socks-proxy
image: thefizi/tor-socks-proxy:latest
ports:
- "127.0.0.1:9150:9150/tcp" # SOCKS5 proxy
- "127.0.0.1:8853:8853/udp" # DNS over Tor (optional)
restart: unless-stopped
Docker CLI
docker run -d --restart=unless-stopped --name tor-socks-proxy \
-p 127.0.0.1:9150:9150/tcp \
thefizi/tor-socks-proxy:latest
Binding to 127.0.0.1 keeps the proxy local to the host. Only change this if you deliberately want to expose it to your LAN — SOCKS5 itself is unauthenticated and unencrypted.
Ports 9050/9150 on the host may already be in use if you run another Tor client such as Tor Browser; change the host-side port if so.
Using the Proxy
curl --socks5-hostname 127.0.0.1:9150 https://check.torproject.org/api/ip
Use --socks5-hostname (or a socks5h:// proxy URL) so that DNS resolution happens through Tor. With plain socks5:// your client resolves names locally, which leaks DNS and makes .onion addresses fail with NXDOMAIN.
DNS over Tor
Tor's DNSPort listens on 8853/udp inside the container. Publish it to whatever host port you want, e.g. port 53:
docker run -d --restart=unless-stopped --name tor-socks-proxy \
-p 127.0.0.1:9150:9150/tcp \
-p 127.0.0.1:53:8853/udp \
thefizi/tor-socks-proxy:latest
Note that upstream's example docker-compose.yml mapped 8853:53/udp, which points at the wrong container port and never worked.
Custom Configuration
Mount your own torrc over the default:
volumes:
- ./torrc:/etc/tor/torrc:ro
The default torrc:
HardwareAccel 1
Log notice stdout
DNSPort 0.0.0.0:8853
SocksPort 0.0.0.0:9150
DataDirectory /var/lib/tor
Bridges (obfs4)
UseBridges 1
ClientTransportPlugin obfs4 exec /usr/bin/lyrebird
Bridge obfs4 <ip>:<port> <fingerprint> cert=<cert> iat-mode=0
Get bridges from https://bridges.torproject.org/.
IP Renewal
Tor rotates circuits for new connections roughly every 10 minutes. To force a fresh identity, restart the container:
docker restart tor-socks-proxy
Image Details
| Component | Details |
|---|---|
| Base image | alpine:3.24 |
| Platforms | linux/amd64, linux/arm64, linux/arm/v7 |
| Packages | tor, lyrebird, curl |
| Runs as | tor user (uid 100, gid 101, non-root) |
| SOCKS proxy | 9150/tcp |
| DNS | 8853/udp |
| Healthcheck | Every 5 min via curl --socks5-hostname against Tor Project's API; requires Docker Engine 25+ for the fast startup interval |
Supported Platforms
Every tag is a multi-arch image. Docker pulls the variant that matches your host automatically, so the same image: line works everywhere.
| Platform | Typical hardware |
|---|---|
linux/amd64 |
x86_64 servers, desktops, VMs |
linux/arm64 |
Raspberry Pi 3, 4, 5 and Zero 2 W on a 64-bit OS; other ARMv8 boards; Apple Silicon (via Docker Desktop) |
linux/arm/v7 |
Raspberry Pi 2, 3, 4 and Zero 2 W on 32-bit Raspberry Pi OS; other ARMv7 boards |
linux/arm/v6 (original Raspberry Pi 1 and Pi Zero/Zero W) is not built.
To check which variant you got: docker image inspect --format '{{.Architecture}}{{if .Variant}}/{{.Variant}}{{end}}' thefizi/tor-socks-proxy:latest.
All variants are built from the same Alpine base snapshot in the same CI run, so a given version tag carries the same Tor and Alpine versions on every platform. The ARM images are built under QEMU emulation rather than on native hardware.
Image Tags
| Tag | Description |
|---|---|
latest |
Most recent build from main branch |
tor-{VER}-alpine-{VER} |
Pinned to specific Tor and Alpine versions |
Available from:
- Docker Hub:
thefizi/tor-socks-proxy - Forgejo:
git.pickysysadmin.ca/eric/tor-socks-proxy
Credits
Based on PeterDaveHello/tor-socks-proxy by Peter Dave Hello, licensed under GPLv3. This project is also licensed under GPLv3.
Support the Tor Project by running a relay or donating.