
Self-host a Tor v3 hidden service.
Twenty minutes to your own .onion.
Five steps from provisioning a VPS to a live, 56-character v3 onion address reachable only through the Tor network. Tested on Debian 12 with the official Tor Project repository.
- 01
Provision
A Nordic VPS
- 02
Install
Official Tor package
- 03
Configure
Two lines in torrc
- 04
Get address
cat .../hostname
- 05
Harden
Permissions + isolation
Any Nordic bastion works. Tor does the geography.
Unlike a clearnet site, a hidden service does not really care which physical bastion it lives on — clients reach you through three Tor relays, so latency to the bastion does not affect the user experience much. Pick whichever bastion you have other workloads in, or whichever jurisdiction matches your threat model best (see /guides/nordic-jurisdictions-for-privacy-hosting/).
Sentinel tier ($5.90/mo) is plenty for a hidden service hosting a personal site, a tor-friendly SSH endpoint, or a small Mastodon onion mirror. Larger hidden services (Mastodon main instance, file-sharing, etc.) want Garrison or Ravelin for the extra RAM and disk.
Official Tor Project repository, not the distro package.
Distribution-packaged Tor is often months behind upstream and may miss security fixes. Use the Tor Project's own apt repository:
apt install -y apt-transport-https gpg curl
curl -fsSL https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc \
| gpg --dearmor -o /usr/share/keyrings/tor-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] \
https://deb.torproject.org/torproject.org bookworm main" \
> /etc/apt/sources.list.d/tor.list
apt update
apt install -y tor deb.torproject.org-keyring
Verify the daemon is alive: systemctl status tor — should report Active (running). The default config opens no inbound ports and runs Tor as a relay-only client; we will turn it into a hidden service in the next step.
Two lines in torrc. That is it.
Open /etc/tor/torrc and add:
HiddenServiceDir /var/lib/tor/my_service/
HiddenServicePort 80 127.0.0.1:80
Two things to know. (1) HiddenServiceDir is where Tor stores the service's private key (the secret that defines the .onion address). Tor creates the directory at first start; do not edit the contents. (2) HiddenServicePort maps the public port on the onion to a local port — here, port 80 on the onion goes to 127.0.0.1:80 (nginx, Apache, anything listening locally). Add more HiddenServicePort lines for additional ports (HTTPS on 443, SSH on 22, etc.).
Whatever you bind the local target to (nginx, sshd, gitea), make sure it listens on 127.0.0.1 — not on 0.0.0.0. A service bound to 0.0.0.0 is also reachable on the public IP, which defeats the hidden-service-only premise.
Restart Tor. Read the hostname file.
Restart Tor and Tor will generate the v3 key pair and the address:
systemctl restart tor
cat /var/lib/tor/my_service/hostname
# example output:
# 7f43hp...long-string...7q.onion
That 56-character base32 string ending in .onion is your hidden service address. It is derived from the Ed25519 public key in /var/lib/tor/my_service/hs_ed25519_public_key. Anyone with the address can reach the service through Tor Browser (or any Tor-aware client). Test it: open Tor Browser, paste the address, hit return — your web service should respond.
Back up the contents of /var/lib/tor/my_service/ to a safe place. Losing the keys means losing the .onion address — it cannot be recovered. Sharing the keys means anyone with them can run the same .onion from any server.
Permissions, isolation, banner-stripping. The boring but critical part.
1. Verify the service runs as user debian-tor, not root. apt install handles this on Debian/Ubuntu. Verify: ps aux | grep tor — uid should not be 0.
2. Lock the keys. chmod 700 /var/lib/tor/my_service/ — only debian-tor can read. Tor refuses to start if the directory is world-readable.
3. Strip server banners. nginx: server_tokens off; in http context. Apache: ServerTokens Prod, ServerSignature Off. Web-app: remove X-Powered-By, set Server: blank if your reverse proxy allows it. The goal is that an HTTP response from the .onion does not leak the IP or hostname.
4. Disable outbound DNS leaks. Your web app must not resolve external domain names on request, or those DNS queries leave the VPS over clearnet. Set the app to use Tor's SOCKS proxy for outbound calls (127.0.0.1:9050).
5. Set Onion-Location on your clearnet site. Add this header to your clearnet nginx config: add_header Onion-Location http://<your-onion>.onion$request_uri; — Tor Browser users now get a prompt to redirect to the onion automatically.
Questions, answered.
Eight questions a first-time hidden-service operator asks.
What is a v3 onion address and how is it different from v2?
A v3 onion address is a 56-character base32 string ending in .onion, derived from an Ed25519 public key. v2 (deprecated and disabled by Tor since 2021) used a 16-character base32 from a truncated RSA-1024 key — short, but cryptographically much weaker. v3 has a stronger key (Ed25519), better directory privacy (no enumeration of services), client authorisation support, and is the only version still operational. If you see a 16-character .onion address, it is dead.
Does a Tor hidden service leak my server IP?
A correctly configured one does not. Tor connects out from your VPS to three Tor relays (a guard, a middle, a rendezvous) and never accepts inbound connections directly on the VPS IP. The hidden service is reached only through the Tor circuit. Misconfigurations that DO leak the IP: running the service on a public port (it should be 127.0.0.1-bound), DNS leaks from the hosted web app, server-software banner-stamping the IP into outbound responses. The standard checklist below covers each.
Can my VPS provider see what is on the hidden service?
Your VPS provider sees outbound Tor traffic from your VPS — they know "this server runs Tor" but not what content is reached. They cannot see what is on the hidden service from the outside; they can see what is on the disk from the inside, like any VPS provider. NordBastion does not access customer disks, but a server you do not control with full-disk encryption is a server an operator can theoretically read. For absolute hidden-service privacy, run LUKS with a passphrase only you have — Servury packages that out of the box on owned hardware, others (NordBastion included) leave it as a customer-installable.
How do I get a vanity .onion address (e.g. starting with my brand name)?
Use mkp224o — an open-source tool that brute-forces Ed25519 key pairs until the resulting v3 address starts with a chosen prefix. A 4-character prefix is found in minutes on a modern laptop; a 7-character prefix takes a few hours; 10+ characters takes weeks to months on dedicated hardware. The resulting onion address is cryptographically valid — the brute-force only finds the key whose hashed public part happens to start with the desired characters.
How fast is a hidden service?
Slower than clearnet. Tor routes through three relays, so each round-trip adds ~300-800ms of latency. Throughput is bottlenecked by the slowest relay in the chosen circuit; expect 1-5 MB/s on average for static content, less for interactive workloads. Tor introduced "HSDir bandwidth" optimisations and HiddenServiceSingleHopMode for cases where the service-side anonymity is not required.
Should I use HiddenServiceSingleHopMode?
Only if your threat model accepts that the SERVICE side is publicly known (e.g., you have already published "this onion runs on my server in Iceland"). Single-hop mode skips the guard+middle relays on the service side and connects directly to the rendezvous, which is faster (200-400ms less latency) but does not protect the service-side IP. Clients still get full three-hop privacy on their side. For a hidden service that needs server-side anonymity, leave it disabled (the default).
Can I run a hidden service on the same VPS as my clearnet site?
Yes, and many sites do. The clearnet web server listens on the public IP at port 80/443; the Tor hidden service points to the same web server at 127.0.0.1 on the same ports. Both reach the same content. Two operational notes: (1) make sure the web server does not stamp the public IP into headers (Server, X-Real-IP, hostname banners), and (2) set the Onion-Location HTTP header on the clearnet site so Tor Browser users get auto-redirected to the onion address.
What is Vanguards / Vanguards-lite?
A Tor add-on (Vanguards) that pins the guard relay at the service side, mitigating a class of attacks where an attacker observes which guards the service rotates through and uses that to deanonymise. Vanguards-lite is built into the Tor daemon since 0.4.7 and is enabled by default for hidden services in current Tor versions — you generally do not need to do anything to benefit from it. The full Vanguards add-on is overkill for most personal hidden services and useful mainly for high-value targets.
Order a VPS and put your service on the onion.
Last reviewed · 2026-05-20 · Tested · Debian 12 · Tor 0.4.8+
Anonymous VPS hosting in 2026 — the cluster.
This guide is one spoke of a larger series. The pillar walks the three privacy layers end to end — the sibling spokes below dive into the specifics.
Three independent layers — signup, payment, network — explained, legal context included, common mistakes flagged.
Your own WireGuard tunnel — server config, peer keys, kill-switch.
What “no KYC” actually means — and what it does not.
Why Sweden, Finland, Norway and Iceland — the legal floor of each.
XMR end-to-end — wallet, transfer, confirmations, change.