Directory Setup
- Set up the files and directories:
mkdir -p tor-site/keys tor-site/html tor-site/logs
touch tor-site/torrc
- Set permissions:
chmod 700 tor-site/keys chmod 600 tor-site/logs sudo chown root:root tor-site/keys tor-site/logs
Content Setup
Add the files for your website into the tor-site/html folder:
example:
<!DOCTYPE html>
<html>
<body>
<h1>Hello from the Onion Router!</h1>
<p>This site is hosted inside Docker.</p>
</body>
</html>
Docker Setup
[[Install Docker]]
Docker Compose File
compose.yaml
services:
nginx:
container_name: nginx
image: nginx
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
volumes:
- ./html:/usr/share/nginx/html:ro
- ./logs:/var/log/nginx
networks:
- tor_network
tor:
container_name: tor
volumes:
- ./torrc:/etc/tor/torrc:ro
- ./keys:/var/lib/tor/hidden_service/
image: alpine:latest
entrypoint: sh -c "apk add --no-cache tor && tor -f /etc/tor/torrc"
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
networks:
- tor_network
depends_on:
- nginx
networks:
tor_network:
nginxis the name of your web server container - this is important for thetorrcfile.:rosets the volume to read onlynetworks: tor_networkmeans all the traffic stays inside the tor networksecurity_opt: - no-new-privileges:trueprevents the user from running as root throughsetuidorsetgidcap_drop: -Allremoves all default Linux capabilities granted to a containercap_add: - NET_BIND_SERVICEwill allow tor to work with only the necessary capabilitiesnetworksensures that all traffic stays inside the docker network with a custom bridgetor_networkto access the tor relays See Docker Permissions
Create torrc:
# Standard Tor config
DataDirectory /var/lib/tor
# Define the Hidden Service
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80 nginx:80
- note: the name
nginxshould be the same as you name your web server container in thecompose.yaml(see [[#Docker Setup]]).
Notes:
- Did you know you can make a custom tor site name? See the Named Tor Site.
- The docker service setup: Dockhand Portainer
services:
nginx:
container_name: nginx
image: nginx
volumes:
- /home/mechanicus/code/tor-site/html:/usr/share/nginx/html:ro
- /home/mechanicus/code/tor-site/logs:/var/log/nginx
networks:
- tor_network
deploy:
mode: replicated
replicas: 1
labels:
- "com.centurylinklabs.watchtower.enable=true"
- "label=shepherd.autodeploy=true"
tor:
container_name: tor
volumes:
- /home/mechanicus/code/tor-site/torrc:/etc/tor/torrc:ro
- /home/mechanicus/code/tor-site/keys:/var/lib/tor/hidden_service/
image: alpine:latest
entrypoint: sh -c "apk add --no-cache tor && tor -f /etc/tor/torrc"
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
networks:
- tor_network
depends_on:
- nginx
deploy:
mode: replicated
replicas: 1
labels:
- "com.centurylinklabs.watchtower.enable=true"
- "label=shepherd.autodeploy=true"
networks:
tor_network: