Skip to content

Onionsite Checklist


This is a quick and not yet complete checklist intended to help Onion Service operators to setup and maintain their sites, and goes beyond the setup guide and the advanced settings.

This is still being written, and progress is tracked at tpo/onion-services/onion-support#30.

HTTPS support

HTTPS for Onion Services is not a strict requirement, but consider some of the benefits for having HTTPS.

If you do setup HTTPS, please make it the default (i.e, redirect HTTP requests to HTTPS).

Service Discovery

Service discovery has to do with indicating to clients that a regular site has an .onion counterpart.


There are a number of proposals for Service Discovery, but as of December 2023 the recommended way is to deploy the Onion-Location HTTP header or tag.

When present, clients such as Tor Browser and Brave automatically parses this header and shows the ".onion available" icon at the address bar, and may automatically redirect to the onionsite depending on a config setting.

Please note that not all high-traffic sites use this header: some operators are concerned that it increases the HTTP response size (an hence reduce performance) for everyone in benefit of only a reduced number of Tor-enabled users.

There's also a way to offer this header only for Tor users, by adding a rule in your frontend proxies to check if requests are coming from a known public Tor Exit node. This reduces HTTP response size for everyone except Tor users, at the expense of some more server-side logic (and processing time). The up-to-date list can be fetched by a number of ways (and it changes very often, so you'll need a scheduled task to keep your rule updated).

So in summary, there are basically three options for Onion-Location:

  1. Setup Onion-Location normally.

  2. Setup in a way that your frontend proxies only present it when requests comes from the "Tor country" (i.e, from IPs in the public exit node list).

  3. Do not set it up -- mostly due to performance concerns.

Recommendation is to start with option 1 (at least during the initial public release phase) and then check whether you really have a performance issue related to this small response size increase.


Another approach -- and that may be no conflicting with Onion-Location, is to setup Alt-Svc headers pointing to the Onion Service, as documented here. As with Onion-Location, this header may also be set only for client connections coming from the "Tor country".

Although the Alt-Svc approach is a very interesting (and transparent) way to announce Onion Services, right now Tor Browser does not offers the same user experience as with Onion-Location, such as indicating whether a given resource was fetched through the Alt-Svc .onion address or through the regular resource URL. So even if your users would be benefiting from Onion Service connections announced via a Alt-Svc header, they would not be aware of that, and may even believe the contrary, i.e, that their connection is happening through the regular site.

Recommendation is to prioritize Onion-Location instead of Alt-Svc right now (as of December 2023), due to the user experience difference.

Load balancing/failover

For load balancing and redundancy, it's possible to run many tor daemon instances in parallel to act as a Onion Service load balancing/failover layer.

Right now there are two approaches.

Parallel tor instances

This is the simpler approach, consisting in running multiple tor daemon instances in parallel in different servers.

  • Advantages:
    • Simpler to set up (just replicate what you already have).
    • Works well with the Proof Of Work anti-DoS defense (PoW).
  • Disadvantages:
    • Every tor server needs to have a copy of the .onion private key, so if one server is compromised then your service is compromised.
    • This is not "full" load balancing, acting mostly as a simple failover, and depends a lot in the timing you start each of the tor daemons.

Using Onionbalance

Onionbalance provides load-balancing and redundancy for Tor hidden services by distributing requests to multiple backend Tor instances.

  • Advantages:
  • Fully implements load balancing/failover.
  • Provides better isolation of the main .onion keys, reducing the attack surface.
  • Disadvantages:
  • Harder to setup.
  • As of December 2023, it does not support the Proof Of Work anti-DoS defense (PoW), but this is being planned.

Which one to go?

It depends. Onionbalance usually is the best candidate, except if you plan to deploy PoW.

If you prefer PoW over the other advantages offered by Onionbalance, I would say use the simpler method instead.

You can also switch anytime from one approach to the other, without disrupting the service.

As for the number of nodes, that will depend mostly on load/requests.


The are two complimentary approaches to monitoring:

  1. From the "outside" of your infrastructure, i.e, the monitoring tool can be set anywhere on the Internet, as long as the Tor network can be reached.
  2. From the "inside", i.e, the monitoring tools are installed in the same local network (or server) where your Onion Services are running.

From the "outside"

The quickest way to monitor from the outside is to use Onionprobe, maybe as a full monitoring node.

From the "inside"

There are a few handy ways to monitor from the inside:

  1. Analyzing tor daemon and the HTTP proxy logs using tools such as Logstash.
  2. Using the MetricsPort option which exports data using Prometheus.


This approach produces lots of useful data (maybe even more than you need) but need to be set with care, so we quote here the C tor daemon manual page:

MetricsPort [address:]port [format]
    WARNING: Before enabling this, it is important to understand that
    exposing tor metrics publicly is dangerous to the Tor network users. Please
    take extra precaution and care when opening this port. Set a very strict access
    policy with MetricsPortPolicy and consider using your operating systems
    firewall features for defense in depth.

    We recommend, for the prometheus format, that the only address that
    can access this port should be the Prometheus server itself. Remember that the
    connection is unencrypted (HTTP) hence consider using a tool like stunnel to
    secure the link from this port to the server.

    If set, open this port to listen for an HTTP GET request to
    "/metrics". Upon a request, the collected metrics in the the tor instance are
    formatted for the given format and then sent back. If this is set,
    MetricsPortPolicy must be defined else every request will be rejected.

    Supported format is "prometheus" which is also the default if not
    set. The Prometheus data model can be found here:

    The tor metrics are constantly collected and they solely consists of
    counters. Thus, asking for those metrics is very lightweight on the tor
    process. (Default: None)

    As an example, here only will be allowed to connect:

        MetricsPortPolicy accept

MetricsPortPolicy policy,policy,...
    Set an entrance policy for the MetricsPort, to limit who can access
    it. The policies have the same form as exit policies below, except that port
    specifiers are ignored. For multiple entries, this line can be used multiple
    times. It is a reject all by default policy. (Default: None)

    Please, keep in mind here that if the server collecting metrics on
    the MetricsPort is behind a NAT, then everything behind it can access it. This
    is similar for the case of allowing localhost, every users on the server will
    be able to access it. Again, strongly consider using a tool like stunnel to
    secure the link or to strengthen access control.

Abuse protections

First, check the Onion service DoS guidelines page for an overview and initial steps to protect your service.

  • If you want to use the Proof of Work (PoW) protection:
  • Start doing the stress test only after configuring PoW:

    • This will make sure your stress tests won't hurt the Tor network.

    • This will also test the service with the protections already in place.

  • One suggestion is to start with higher values for HiddenServicePoWQueueRate and HiddenServicePoWQueueBurst configuration params.

  • Then fine tune if according to your expected/actual load.

  • Load can be generated by whatever tool, as long as it's being proxied through Tor. Example: continuously spawning many instances of torsocks wget http://your.onion.

  • Try to load the onionsite with Tor Browser while your service is under the simulated load.

  • This is an example project showing how PoW limits DoS: onion-pow-example.

  • There are additional DoS mitigation options if you need, but PoW is a good start.

  • Besides the previous recommendations, you can also control the number of introduction points (HiddenServiceNumIntroductionPoints) and check whether this improve performance and alleviate load.

Operational security

  • Keep an encrypted backup of the .onion keys.

  • Also make sure to secure all servers hosting the .onion keys: if these keys are compromised, your Onion Service is compromised as well, forever, and you would need to generate a new set of keys/address. So general operational security applies here.

  • You may also want to setup encrypted storage (and swap) in the servers, depending on your risk policy.

  • Since it's an Onion Service, you may have very strict access policies to the servers running tor instances. Besides what you need in order to have console access, you can keep the server behind strict firewall policy for incoming connections. The tor daemon don't need to accept any incoming TCP connection from the outside (especially if you use the MetricsPort). It just need to have enough outbound internet access to connect to the Tor Network. In this sense, we usually say that an Onion Service server is actually an special kind of Tor client.

  • If the tor process and the frontend HTTP proxy are in the same machine, consider using UNIX sockets to connect both instead of TCP (HiddenServicePort tor option), so you don't have local TCP port opened.

  • Riseup's Onion Services Best Practices guide is a bit outdated but still has some useful tips on securing your Onion Service.

  • Make sure the clocks are synchronized in all systems :)


Single Hop Onion Service

For public-facing sites that aren't concerned in keeping the Onion Service location secret, it is possible to reduce the number of hops to gain some performance. Don't enable this if you want to keep the location of your Onion Service secret.

This operation mode is called "Single Hop Onion Services" and it's controlled by two settings that need to be enabled. The tor(1) manual page portion explaining how they work is quoted below:


HiddenServiceSingleHopMode 0|1
    Experimental - Non Anonymous Hidden Services on a tor
    instance in HiddenServiceSingleHopMode make one-hop (direct) circuits
    between the onion service server, and the introduction and rendezvous
    points. (Onion service descriptors are still posted using 3-hop paths,
    to avoid onion service directories blocking the service.) This option
    makes every hidden service instance hosted by a tor instance a Single
    Onion Service. One-hop circuits make Single Onion servers easily
    locatable, but clients remain location-anonymous. However, the fact that
    a client is accessing a Single Onion rather than a Hidden Service may be
    statistically distinguishable.

    WARNING: Once a hidden service directory has been used by a
    tor instance in HiddenServiceSingleHopMode, it can NEVER be used again
    for a hidden service.  It is best practice to create a new hidden
    service directory, key, and address for each new Single Onion Service
    and Hidden Service. It is not possible to run Single Onion Services and
    Hidden Services from the same tor instance: they should be run on
    different servers with different IP addresses.

    HiddenServiceSingleHopMode requires
    HiddenServiceNonAnonymousMode to be set to 1. Since a Single Onion
    service is non-anonymous, you can not configure a SOCKSPort on a tor
    instance that is running in HiddenServiceSingleHopMode. Can not be
    changed while tor is running. (Default: 0)

HiddenServiceNonAnonymousMode 0|1
    Makes hidden services non-anonymous on this tor instance.
    Allows the non-anonymous HiddenServiceSingleHopMode. Enables direct
    connections in the server-side hidden service protocol. If you are using
    this option, you need to disable all client-side services on your Tor
    instance, including setting SOCKSPort to "0". Can not be changed while
    tor is running. (Default: 0)

In summary, these settings control whether all Onion Services in a given tor daemon instance should use the "Single Hop" mode. If they're enabled, users will still connect to the Onion Service at a "rendezvous point" using the usual three hops (which we could call as a "3 hop Tor circuit"), but the Onion Service will connect to the rendezvous using only a single hop, hence "Single Hop Onion Service".