Tor relays are volunteer-run servers that route encrypted traffic through the Tor network. A middle relay (also called a non-exit relay) only passes traffic between other relays: it never connects to websites on behalf of users, so your server's IP address does not appear as the source of anyone's traffic. In this tutorial you will install Tor from the Tor Project's repository on Ubuntu 24.04, configure a middle relay with sensible bandwidth limits, keep it updated automatically and verify that it has joined the network.

Prerequisites

To follow this tutorial you need:

  • A server running Ubuntu 24.04 LTS with a public IPv4 address, for example a CubePath VPS. The relay should stay online for months: relays that come and go are of little use to the network.
  • A non-root user with sudo privileges.
  • Bandwidth to spare. The Tor Project recommends at least 16 Mbit/s in both directions and at least 100 GB of outbound traffic per month. Relays below 40 Mbit/s need at least 512 MB of RAM; faster ones need 1 GB or more.
  • Permission to run a relay under your provider's acceptable use policy. Middle relays rarely generate abuse complaints, but read the policy before you start.

Step 1 - Adding the Tor Project repository

Ubuntu's own tor package lags behind upstream releases, and relays should run a current, supported Tor version. The Tor Project publishes signed packages for Ubuntu at deb.torproject.org.

Install the tools needed to fetch the signing key:

sudo apt update
sudo apt install curl gpg

Download the Tor Project's archive signing key and store it as a keyring:

curl -fsSL https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --dearmor | sudo tee /usr/share/keyrings/deb.torproject.org-keyring.gpg > /dev/null

The keyring is stored in /usr/share/keyrings/ rather than /etc/apt/keyrings/ because the deb.torproject.org-keyring package you will install next updates that exact file when the Tor Project rotates its key.

Add the repository for Ubuntu 24.04 (noble):

echo "deb [signed-by=/usr/share/keyrings/deb.torproject.org-keyring.gpg] https://deb.torproject.org/torproject.org noble main" | sudo tee /etc/apt/sources.list.d/tor.list

Step 2 - Installing Tor

Refresh the package index and install Tor together with the keyring package:

sudo apt update
sudo apt install tor deb.torproject.org-keyring

Confirm that the package comes from the Tor Project repository:

apt policy tor
tor:
  Installed: 0.4.8.x-1~noble+1
  Candidate: 0.4.8.x-1~noble+1
  Version table:
 *** 0.4.8.x-1~noble+1 500
        500 https://deb.torproject.org/torproject.org noble/main amd64 Packages

On Debian-based systems Tor runs as the tor@default systemd unit; tor.service is only a wrapper that starts it. Check that it is running:

sudo systemctl status tor@default --no-pager
● [email protected] - Anonymizing overlay network for TCP
     Loaded: loaded (/usr/lib/systemd/system/[email protected]; enabled-runtime; preset: enabled)
     Active: active (running)

At this point Tor runs as a local client only. The next step turns it into a relay.

Step 3 - Configuring the relay

Tor reads its configuration from /etc/tor/torrc. The default file contains only commented examples, so it is easiest to replace it. Make a backup first:

sudo cp /etc/tor/torrc /etc/tor/torrc.orig
sudo nano /etc/tor/torrc

Replace the contents with the following, adjusting the nickname, contact address and bandwidth values:

## Relay identity
Nickname your_nickname
ContactInfo your_name <admin AT example DOT com>

## Relay port (TCP)
ORPort 9001

## Middle relay only: never act as an exit
ExitRelay 0
ExitPolicy reject *:*
SocksPort 0

## Bandwidth: average rate and allowed burst
RelayBandwidthRate 20 MBytes
RelayBandwidthBurst 40 MBytes

## Optional monthly traffic cap (counts each direction separately)
#AccountingStart month 1 00:00
#AccountingMax 1 TBytes

## Local control port for monitoring with nyx
ControlPort 127.0.0.1:9051
CookieAuthentication 1

What each setting does:

  • Nickname: a public name for your relay, 1 to 19 letters and digits, no spaces.
  • ContactInfo: a public address the Tor Project and other operators can use to reach you. Obfuscate it as shown to reduce spam, but keep it reachable.
  • ORPort 9001: the TCP port other relays connect to. Any port works as long as it is reachable from the Internet; 443 helps clients behind restrictive firewalls if nothing else listens on it.
  • ExitRelay 0 and ExitPolicy reject *:*: make sure the relay never becomes an exit.
  • SocksPort 0: disables the local client proxy, which a dedicated relay does not need.
  • RelayBandwidthRate and RelayBandwidthBurst: cap the traffic Tor relays, in bytes per second (MBytes, not megabits). 20 MBytes is about 160 Mbit/s.
  • AccountingMax and AccountingStart: uncomment them if your plan has a monthly traffic quota. When the limit is reached, Tor hibernates until the next period.
  • ControlPort and CookieAuthentication: expose a control port on localhost only, used by the nyx monitor in Step 6.

Check the configuration before restarting. Run it as the debian-tor user so file permissions match the service:

sudo -u debian-tor tor --verify-config -f /etc/tor/torrc
Configuration was valid

Step 4 - Opening the ORPort in the firewall

Other relays must be able to reach your ORPort. Allow it in UFW:

sudo ufw allow 9001/tcp
sudo ufw status
To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
9001/tcp                   ALLOW       Anywhere

If UFW is not active yet, allow SSH first with sudo ufw allow OpenSSH and then run sudo ufw enable. Do not open port 9051: the control port is bound to 127.0.0.1 and must stay private.

Step 5 - Starting the relay and checking reachability

Restart Tor to apply the new configuration:

sudo systemctl restart tor@default

Follow the log while Tor bootstraps and tests its own ports:

sudo journalctl -u tor@default -f

Within a minute or two you should see lines similar to these:

Bootstrapped 100% (done): Done
Now checking whether IPv4 ORPort 203.0.113.10:9001 is reachable... (this may take up to 20 minutes -- look for log messages indicating success)
Self-testing indicates your ORPort 203.0.113.10:9001 is reachable from the outside. Excellent. Publishing server descriptor.

Press Ctrl+C to stop following the log. The line Publishing server descriptor means your relay has announced itself to the directory authorities.

Show your relay's fingerprint, which identifies it in the network:

sudo cat /var/lib/tor/fingerprint
your_nickname 1A2B3C4D5E6F7A8B9C0D1E2F3A4B5C6D7E8F9A0B

Step 6 - Monitoring the relay with nyx

nyx is a terminal monitor for Tor that shows bandwidth, connections, flags and log events in real time. Install it:

sudo apt install nyx

Run it as the debian-tor user so it can read the control port's authentication cookie:

sudo -u debian-tor nyx

The first screen shows a live bandwidth graph and recent events. Use the arrow keys to switch between pages and q to quit.

Step 7 - Finding your relay on Tor Metrics

About one to three hours after publishing its descriptor, your relay appears on the public relay search at https://metrics.torproject.org/rs.html. Search for your nickname or fingerprint.

What to expect over the following weeks:

  • First days: the relay has the Running and Valid flags but carries little traffic. The network measures new relays before trusting them with load.
  • After roughly a week: bandwidth usage grows as measurements come in.
  • After about eight days of stable uptime: fast and stable relays receive the Guard flag and start acting as entry nodes for clients. Traffic can drop briefly at that point, which is normal.

Restarting often or changing the relay's IP address resets much of this progress, so leave it running.

Step 8 - Keeping Tor updated automatically

Relays running outdated Tor versions are eventually rejected by the network. Ubuntu's unattended-upgrades only installs security updates from Ubuntu's own archives by default, so add the Tor Project origin.

Make sure the package is installed:

sudo apt install unattended-upgrades

Create a small configuration file for the Tor repository:

sudo nano /etc/apt/apt.conf.d/51unattended-upgrades-tor
Unattended-Upgrade::Origins-Pattern {
    "origin=TorProject";
};

Check that APT picked up the new setting:

apt-config dump | grep TorProject
Unattended-Upgrade::Origins-Pattern:: "origin=TorProject";

You can then run sudo unattended-upgrade --dry-run --debug to see which packages would be upgraded on the next run.

Tor restarts automatically after an upgrade.

Troubleshooting

The log says the ORPort is not reachable. Check that UFW allows the port with sudo ufw status, that no other firewall in front of the server blocks it, and that Tor is listening with sudo ss -tlnp | grep 9001. Test from another machine with nc -zv your_server_ip 9001.

The relay does not appear on Tor Metrics after several hours. Look for Publishing server descriptor in sudo journalctl -u tor@default. If it is missing, the reachability test has not passed yet. Also make sure the server clock is correct with timedatectl, since Tor rejects consensus documents when the clock is far off.

The relay goes quiet in the middle of the month. If you enabled AccountingMax, the log shows Hibernation messages once the quota is used up. Raise the limit or lower RelayBandwidthRate so traffic spreads across the whole period.

Tor fails to start after editing torrc. Run sudo -u debian-tor tor --verify-config -f /etc/tor/torrc, which prints the line with the error, and read sudo journalctl -u tor@default -n 50.

Conclusion

Your server now runs a Tor middle relay from the official repository, with capped bandwidth, local monitoring through nyx and automatic updates. Next, you can subscribe to the tor-relays mailing list to follow operator announcements, add IPv6 to the relay with a second ORPort line using your IPv6 address in brackets, or run a bridge instead of a public relay if you want to help users in countries that block Tor.