Publish any HTTP service as a persistent Tor v3 onion service. Tor + Caddy gateway, no app changes.
119
Publish any HTTP service as a persistent Tor Onion Service — without changing the application.
OnionForge is a Docker-native gateway that gives your existing containers persistent Tor v3 .onion addresses. One container runs Tor and Caddy and routes each onion hostname to an HTTP/HTTPS upstream on your Docker network, or to an external site.
Your applications don't install Tor, change their Dockerfile or code, publish ports, or know Tor exists.
docker-compose.yml:
services:
backend:
image: my-backend # your existing app, unchanged
expose:
- "8000"
onionforge:
image: emon5122/onionforge:latest
restart: unless-stopped
volumes:
- onionforge-data:/var/lib/tor # onion identities: keep this volume!
- ./onionforge.yml:/etc/onionforge/onionforge.yml:ro
volumes:
onionforge-data:
onionforge.yml:
services:
backend:
prefix: myapp # optional vanity prefix
target: http://backend:8000
docker compose up -d
docker compose logs onionforge
Services:
backend
Onion: http://myappq4x…7yd.onion
Target: http://backend:8000
==================================================
OnionForge is ready
==================================================
Open the address in Tor Browser. No ports: are needed anywhere.
onion-vanity-address. You can give several alternative prefixes. Long searches (hours to days) run as one combined background search for all waiting services, at low priority and with a live time estimate. Each service is published automatically when its key is found.http://backend:8000 resolve through Docker DNS, and backends need no published ports.Location redirect rewriting.SIGHUP without restarting Tor. ┌───────────── OnionForge container ─────────────┐
api….onion ──┤ ├──▶ backend:8000
web….onion ──┤ Tor ──▶ Caddy (127.0.0.1:8080, by Host) ├──▶ frontend:3000
ext….onion ──┤ ├──▶ https://example.com
└────────────────────────────────────────────────┘
services:
api:
prefix: api # optional, a-z and 2-7, max 10 chars; or a list [api, web]
target: http://backend:8000 # http:// or https://, optional base path
company:
target: https://company.example
rewrite_redirects: true # rewrite Location headers to the onion
internal:
target: https://backend:8443
tls:
ca_file: /etc/onionforge/ca.pem
vanity:
background: auto # long prefixes don't block startup
threads: 0 # CPU threads for the search (0 = all)
security: # all false by default
allow_private_targets: false
allow_loopback_targets: false
allow_link_local_targets: false
See the full configuration reference.
| Base | debian:trixie-slim |
| Contents | Tor (Debian package), Caddy 2 (official binary), onion-vanity-address, onionforge |
| Entrypoint | onionforge run |
| Volume | /var/lib/tor: onion identities and Tor state (back it up like credentials) |
| Config | /etc/onionforge/onionforge.yml |
| Exposed ports | none: the services are reachable only through Tor |
| Runs as | starts as root to fix volume ownership, then drops to onionforge (uid 10001) |
| Health check | built in (onionforge healthcheck) |
docker compose exec onionforge onionforge list # addresses and status
docker compose kill -s HUP onionforge # reload onionforge.yml
docker run --rm -v ./onionforge.yml:/etc/onionforge/onionforge.yml:ro \
emon5122/onionforge validate # validate a config
latest: the most recent releaseX.Y.Z, X.Y: specific releases (changelog)Backups, troubleshooting, security model and more: https://github.com/emon5122/onionforge
Content type
Image
Digest
sha256:4010835b7…
Size
50.9 MB
Last updated
3 days ago
docker pull emon5122/onionforge