Standing up a v3 onion service is three lines of config. Running one well, for months, under load, without leaking anything that ruins the point of it — that's a different exercise, and where most operators slip. These are my notes from operating a small v3 service for a while, and from watching larger ones fail in instructive ways.
Key Management is the Whole Game
The hs_ed25519_secret_key file in your HiddenServiceDir is the service. Whoever has it, is the service. Whoever loses it has lost the address forever — there is no recovery, because the address is derived from the key.
- Back up the
HiddenServiceDirdirectory — includinghs_ed25519_secret_key,hs_ed25519_public_key, andhostname— to at least two offline locations. GPG-encrypt the backup; the key is a plaintext seed by default. - Tight permissions: owned by the Tor user, mode 700 on the directory, 600 on the key. If anything else on the box can read it, that thing is now inside your trust boundary.
- If you ever suspect compromise, rotate. Generate a new onion, publish the transition signed by the old key, and retire the old hostname. Don't be romantic about a vanity address.
The OnionBalance project is worth a look if you need redundancy across multiple backends under a single onion address — it's the standard way to run a fault-tolerant service without duplicating keys across boxes.
Client Auth for Private Services
v3 supports client authorization: the descriptor is encrypted to a set of client public keys, so only holders of the matching private keys can even discover the service. This is the right default for anything non-public (internal tools, restricted collaborations, small-group communications).
# Generate a client keypair
openssl genpkey -algorithm x25519 -out /tmp/k.prv.pem
# extract base32 public key, add to server:
# HiddenServiceDir/authorized_clients/alice.auth
# descriptor:x25519:<base32-pub>
# client side, torrc:
ClientOnionAuthDir /var/lib/tor/onion_auth
# add entry: <onion-addr>:descriptor:x25519:<base32-priv>
The practical effect: brute-force scanning doesn't find you, and revoking access is a single-file change on the server.
Where to Host, and DDoS Realities
Home hardware vs. VPS is a threat-model decision, not a cost decision.
- Home hardware — no hosting provider to subpoena, but your residential connection has limited upstream and worse latency. Good for low-traffic services where the hosting relationship itself is part of your threat model.
- VPS — better availability, but the provider can be compelled or compromised. Choose jurisdictions thoughtfully, and assume the provider can read your disk; encrypt at rest with a key you type at boot.
Onion services are unusually exposed to cheap DDoS. An attacker can spin up clients that open introduction circuits for free, and a popular service can spend all its CPU negotiating rendezvous. The Tor Project's HiddenServiceEnableIntroDoSDefense and the proof-of-work defense (prop327) help meaningfully — enable them. They don't eliminate the problem; they make it expensive enough that casual attacks stop.
# torrc
HiddenServiceDir /var/lib/tor/mysvc/
HiddenServicePort 80 unix:/run/mysvc.sock
HiddenServiceEnableIntroDoSDefense 1
HiddenServiceEnableIntroDoSBurstPerSec 200
HiddenServiceEnableIntroDoSRatePerSec 25
HiddenServicePoWDefensesEnabled 1
Publishing Changes Safely, and Monitoring Without Leaking
Every change you push to the service is a chance to leak. Things I've learned:
- Bind the web server to a Unix socket, not 127.0.0.1, and firewall the box to block all inbound except what Tor needs. A misconfigured virtual host that's reachable on the clearnet IP will get indexed and correlated.
- Strip
Serverheaders, framework fingerprint headers, and anything that would let someone match the onion to a clearnet-accessible box with the same quirks. - Use
OnionSharefor one-off file transfers to the server rather than SCP from a residential IP to a VPS. Operational convenience is not a valid excuse for cross-identity correlation. - For monitoring, push metrics out from the box over Tor to a collector — don't scrape into it. Prometheus' remote-write with a Tor SOCKS proxy works fine. Your monitoring endpoint should never accept connections from anywhere except the onion itself.
- Aggressively disable access logs (see my piece on privacy-respecting logging). On an onion, the source IP is always loopback and the access log is purely downside risk.
The technical part of running a v3 service is the easy part. The operational discipline — the refusal to take small shortcuts — is where the anonymity actually lives. Treat every convenience that pulls you toward clearnet workflows as a question that needs a good answer, not a default.