Home How to host a tor hidden service
Post
Cancel

How to host a tor hidden service

You can access this very same blog as a hidden service at http://simondtms5x6kbjqgbugm7hqiyvmb4iqijizbpuznvk4invyytw4fjqd.onion

Hosting a website as a hidden service via the tor network is easy. With my setup you can host arbitrary webservices on the tor network just like you would do on the clearnet.

I use docker compose with Onimages and nginx proxy manager to easily manage multiple websites.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
configs:
  torrc:
    content: |
      RunAsDaemon 0
      HiddenServiceDir   /var/lib/tor/onion
      HiddenServicePort   80 npm:80

services:
  tor:
    image: ghcr.io/simonhaas/images/tor:latest
    volumes:
      - ./data/tor:/var/lib/tor
    configs:
      - source: torrc
        target: /etc/tor/torrc
    restart: unless-stopped
    entrypoint: "/usr/bin/tor -f /etc/tor/torrc"
    command: ''

  npm:
    image: jc21/nginx-proxy-manager
    restart: unless-stopped
    ports:
      - 100.107.87.40:82:81 # for access to the admin page via my tailnet
    volumes:
      - ./data/npm:/data
      - ./data/letsencrypt:/etc/letsencrypt

  homepage:
    image: ghcr.io/simonhaas/simonhaas.github.io/homepage:main
    restart: unless-stopped

  blog:
    image: ghcr.io/simonhaas/blog:main
    restart: unless-stopped

  tallycounter:
    image: ghcr.io/simonhaas/tallycounter/tallycounter:master
    restart: unless-stopped

  clock:
    image: ghcr.io/simonhaas/clock:main
    restart: unless-stopped

The first time tor runs it generates a .onion address for you.

1
docker compose exec -ti tor cat /var/lib/tor/hidden_service/npm/hostname

There will be two more files:

  • hs_ed25519_public_key
  • hs_ed25519_secret_key

Noticed how the tor service is stateless? It does not use any volumes. To prevent generating a new address everytime the container starts you can export the secret key and add it as the environment variable NPM_TOR_SERVICE_KEY.

1
docker compose exec -ti tor cat /var/lib/tor/hidden_service/npm/hs_ed25519_secret_key | base64

Now you can add Proxy Hosts inside nginx proxy manager just like you would on the clearnet.

  • domain name: your .onion address
  • scheme: http
  • forward host: nginx
  • port: 80

For my blog I use the same proxy host but have added a Custom location

  • location: /blog
  • scheme: http
  • forward host: blog
  • port: 80

vanity addresses

Vanity addresses can be generated with mkp224o

1
docker run --rm -it -v ./keys:/keys ghcr.io/cathugger/mkp224o:master -d /keys simon

This will generate .onion address starting with simon and save them in the ./keys folder. To use a generated address for your hidden service, just convert a secret key to base64 and add it as the respective environment variable to your tor service.

onion-location

If you are visiting this blog on its clearnet address via the tor browser you might have noticed a banner advertising the .onion version.

This post is licensed under CC BY 4.0 by the author.