# Run Multiple Onion Services on One Host

> Run multiple onion services from one Tor daemon: separate HiddenServiceDir blocks, per-site Nginx vhosts, and a client-authorized admin onion.

- **URL:** https://hackindex.io/blog/multiple-onion-services
- **Authors:** [Joshua](https://hackindex.io/authors/joshua.md)
- **Published:** 2026-09-12
- **Updated:** 2026-09-12

One Tor daemon can serve multiple onion services at once, each with its own address. This page runs several onions from the [hardened onion service](https://hackindex.io/blog/hardened-onion-service-ubuntu) build, maps each to its own site, and locks one address to a key with client authorization. Every service adds its own directory and its own backend port.

## Running multiple onion services from one daemon

Each service is a HiddenServiceDir block in torrc. Every option after a HiddenServiceDir line applies to that service until the next HiddenServiceDir line, so order matters. Point each service at a different loopback port, and let nginx answer that port with its own site.

## One daemon, several addresses

Add a block per service. The first is the site from the base build on port 8080. The second serves a different site on port 8081. Each block gets its own address and key. Repeat the intro DoS and proof of work lines from the base build under each block, since those settings are per service.

```
HiddenServiceDir /var/lib/tor/site/
HiddenServicePort 80 127.0.0.1:8080

HiddenServiceDir /var/lib/tor/blog/
HiddenServicePort 80 127.0.0.1:8081
```

Give the second service its own nginx server block on the matching port. Apply the same hardening as the base build: version banner off, directory listing off, and the security headers inside the block.

```nginx
server {
    listen 127.0.0.1:8081;
    server_name _;

    root /var/www/blog;
    index index.php index.html;

    server_tokens off;
    absolute_redirect off;
    port_in_redirect off;
    autoindex off;
    access_log off;
    etag off;
}
```

### The same site on several addresses

To publish one site under more than one address, point another service block at the same backend port. This helps when you rotate an address or migrate visitors from an old one. Both onions serve the exact same content. Add only the new block under the existing site block. Do not repeat the site directory, or Tor refuses to start with a duplicate directory warning.

```
HiddenServiceDir /var/lib/tor/site-mirror/
HiddenServicePort 80 127.0.0.1:8080
```

## A private admin onion with client authorization

Client authorization restricts a service to clients that hold a key. Once you enable it, the address alone no longer grants access, which suits an admin panel. Add the service like any other, then place a client key in its authorized_clients directory.

```
HiddenServiceDir /var/lib/tor/admin/
HiddenServicePort 80 127.0.0.1:8082
```

Restart Tor once so it creates the admin service and its address. Then generate an x25519 keypair. The public key goes to the service, the private key to the client. Generate it offline and move the keys by hand. The base32 tool comes from GNU coreutils, so on macOS run brew install coreutils and use gbase32, or generate the keys on the Linux server itself.

```bash
openssl genpkey -algorithm x25519 -out /tmp/k1.prv.pem
openssl pkey -in /tmp/k1.prv.pem -outform DER | tail -c 32 | base32 | sed 's/=//g' > /tmp/k1.prv.key
openssl pkey -in /tmp/k1.prv.pem -pubout -outform DER | tail -c 32 | base32 | sed 's/=//g' > /tmp/k1.pub.key
```

Write the public key into the service as a `.auth` file. The format is `descriptor:x25519:` followed by the key, one line only. Fix the owner and restart Tor to activate the restriction.

```bash
sudo mkdir -p /var/lib/tor/admin/authorized_clients
echo "descriptor:x25519:$(cat /tmp/k1.pub.key)" | sudo tee /var/lib/tor/admin/authorized_clients/client.auth
sudo chown -R debian-tor:debian-tor /var/lib/tor/admin
sudo systemctl restart tor
```

With the key in place, the service rejects anyone without it. Confirm this from a client that has no key yet. Set ONION_ADDRESS to the admin hostname from `/var/lib/tor/admin/hostname` on the server. Tor Browser shows an Onionsite requires authentication prompt instead.

```bash
ONION_ADDRESS=<paste the admin hostname from the server>
torsocks curl -I http://$ONION_ADDRESS/
# torsocks: General SOCKS server failure (in socks5_recv_connect_reply() at socks5.c:527)
```

On the client, point Tor at a directory for private auth keys, then drop the private key there. The file name ends in `.auth_private`, and the line starts with the admin address without the `.onion` suffix.

```
ClientOnionAuthDir /var/lib/tor/onion_auth
```

```bash
ONION_ADDRESS=<paste the admin hostname from the server>
sudo mkdir -p /var/lib/tor/onion_auth
echo "${ONION_ADDRESS%.onion}:descriptor:x25519:$(cat /tmp/k1.prv.key)" | sudo tee /var/lib/tor/onion_auth/admin.auth_private
sudo chown -R debian-tor:debian-tor /var/lib/tor/onion_auth
sudo chmod 700 /var/lib/tor/onion_auth
sudo systemctl restart tor
```

> [!WARNING]
> Revoke a client by deleting its `.auth` file on the service and restarting Tor. The change takes effect only after the restart. A client that already fetched the descriptor may keep a working connection until it expires, up to a few hours. Keep each auth file to a single line, since Tor ignores a malformed file.

## Scaling beyond one host

One daemon on one box has a ceiling. To spread an address across several backend instances for load or redundancy, Onionbalance publishes a combined descriptor that points at multiple instances. That sits outside this build, but it is the next step when a single host is not enough.

Give any of these addresses a readable prefix with [mkp224o](https://hackindex.io/blog/vanity-onion-address-mkp224o), and revisit the full lockdown in the [hardened onion service](https://hackindex.io/blog/hardened-onion-service-ubuntu) guide.

## References

- [Tor client authorization](https://community.torproject.org/onion-services/advanced/client-auth/) - Restricting a v3 onion service to clients that hold a key.
- [Tor Project onion services](https://community.torproject.org/onion-services/) - Configuring one or more services in torrc.
- [Onionbalance](https://onionbalance.readthedocs.io/) - Load balancing and redundancy across onion backends.
