$ xmrhost-cli docs show --topic=run-non-exit-tor-relay
[$ ] doc: run-non-exit-tor-relay
// Run a non-exit Tor relay on a XMRHost VPS — torrc, bandwidth tuning, MyFamily, abuse handling
// published=2026-04-29 · updated=2026-04-29 · diff=advanced · read=22min · tags=[tor, relay, guard, middle, bandwidth]
// ABSTRACT
abstract
Procedure for bringing up a public, non-exit, non-bridge Tor relay on an offshore XMRHost VPS. Covers the upstream-procurement conversation (transit allowance, abuse-handling expectations), the torrc shape for a middle/guard relay, RelayBandwidthRate tuning that stays inside the VPS bandwidth quota, the MyFamily declaration when an operator runs more than one relay, the four-week consensus-weight ramp-up curve, and the post-launch checks that catch the most common misconfigurations (clock skew, ORPort unreachable, descriptor never published).
Scope and assumptions
This is the operational walk-through for running a non-exit Tor relay (middle or guard role, NOT exit, NOT bridge) on a XMRHost VPS. The non-exit role is the operationally cheapest contribution to the Tor network: the relay handles inter-hop traffic only, never originates or terminates traffic toward the public internet, and therefore never appears as the source IP of any user-visible action. Abuse complaints to the upstream are therefore rare to nonexistent, in contrast to exit relays. [Tor Project — Tor relay operator guide, role taxonomy]
Baseline assumptions:
- Debian 12 (bookworm) on a XMRHost VPS in Iceland, Romania, or Switzerland — these jurisdictions have known operator-friendly precedent for running relays. [Iceland Höfundalög §11; Romania Law 8/1996 — operator-side liability scope]
- The brand’s
hardened-by-defaultbaseline is in place. Seeharden-sshdandkernel-hardening-checklist. - The VPS plan includes ≥ 5 TB/month of egress (10 TB/month preferred). A 2 TB plan is wasted on a Tor relay — it’ll hit the cap in week one and either throttle or get billed for overage.
- The upstream provider has been told the box will run a non-exit Tor relay. If they say no, do not run one anyway. The procurement conversation is in step 1.
This doc does NOT cover bridge relays (a different config, a different threat model — bridges are kept off the public consensus to be useful to censored users) or exit relays (a different config, a much bigger legal-and-abuse-handling surface — see the elective doc exit-relay-considerations if you’re seriously considering operating one).
Step 1 — the procurement conversation with upstream
Before installing Tor, confirm with the VPS provider in writing that running a relay is acceptable. The acceptable-use policy of every offshore-friendly host known to the brand permits non-exit relays explicitly, but the wording differs and you want a paper trail. The five questions to ask, in plain language:
- “Is running a non-exit, non-bridge Tor relay (middle or guard role) acceptable on this VPS?”
- “What is the egress bandwidth cap, and at what cap does throttling or overage billing kick in?”
- “Does the AUP allow inbound connections on a non-standard port (e.g. 9001 or 443/9050) to the relay’s ORPort?”
- “If an abuse complaint arrives at upstream’s NOC referencing the relay’s IP, what is upstream’s intake process — is it forwarded to the customer, or handled by upstream first?”
- “Is reverse DNS configurable to a string of the customer’s choice (so the relay can be operationally identified as
tor-relay.example.invalidrather thanvps-12345.upstream.invalid)?”
XMRHost’s listed offshore providers all answer “yes / generous quota / yes / forwarded to customer / yes” to those five. If the provider you’re using answers differently, reconsider before launch.
Once confirmed, set the reverse DNS via the provider’s panel to a name that resolves the relay back to the operator (the brand convention: tor-relay-<region>-<n>.<your-domain>).
Step 2 — install Tor from the upstream repo
Same upstream-repo install as [provision-tor-hidden-service] step 1, repeated here so this doc is self-contained:
apt update
apt install -y apt-transport-https gnupg ca-certificates wget
wget -qO- https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc \
| gpg --dearmor > /usr/share/keyrings/tor.gpg
cat > /etc/apt/sources.list.d/tor.list <<'EOF'
deb [signed-by=/usr/share/keyrings/tor.gpg] https://deb.torproject.org/torproject.org bookworm main
deb-src [signed-by=/usr/share/keyrings/tor.gpg] https://deb.torproject.org/torproject.org bookworm main
EOF
apt update
apt install -y tor deb.torproject.org-keyring tor-geoipdb
Confirm:
Tor version 0.4.8.13.
If the version starts with 0.4.7 or earlier, the upstream repo line was misconfigured.
Step 3 — the canonical relay torrc
The relay torrc is materially different from a hidden-service torrc — different sections, mostly different directives. This is the brand’s middle-relay shape; turn one knob (ExitRelay 1) and it becomes an exit relay, do NOT do that without reading the exit-relay considerations doc first.
# /etc/tor/torrc — middle/guard relay (non-exit, non-bridge).
# Replace <YOUR-CONTACT-EMAIL>, <YOUR-NICKNAME>, <YOUR-FAMILY-FP> below.
# ---------- identity / contact ---------------------------------------------
# Nickname: 1-19 alphanumeric chars, displayed in consensus + visualisations.
# Brand convention: `<region><n>cypher` e.g. `is01cypher`, `ro02cypher`.
Nickname is01cypher
# Contact email surfaces in the relay descriptor and is therefore PUBLIC. Use
# an address that's monitored for abuse complaints and discoverability —
# do NOT use a personal address. The brand convention is the role-account
# `tor-relay@<your-domain>`.
ContactInfo <YOUR-CONTACT-EMAIL>
# ---------- relay config ----------------------------------------------------
# ORPort is the relay listener; the inbound connections from other relays
# come here. 9001 is the historical default; 443 confuses some censorship
# blocks (some networks allow 443 outbound but block 9001) but only matters
# for guard relays.
ORPort 9001
# Optional second ORPort on 443 — useful for guard relays in restrictive
# networks. Only enable if your IPv4 has port 443 free (i.e. no clearnet
# webserver on this box).
# ORPort 443
# DirPort optional — old clients fetch consensus over DirPort. Modern Tor
# uses tunnelled-over-OR fetches; DirPort is no longer needed for new
# relays per Tor Project guidance, late 2023+.
# DirPort 9030
# ---------- non-exit, non-bridge -------------------------------------------
ExitRelay 0
ExitPolicy reject *:*
BridgeRelay 0
PublishServerDescriptor 1
# ---------- bandwidth tuning ------------------------------------------------
# Tor's bandwidth-rate is byte-per-second NOT bit-per-second. The brand
# default for a 10 TB/month VPS: cap at 12 MB/s sustained, 25 MB/s burst —
# 10 TB / 30 days / 86400 sec ≈ 3.86 MB/s; the 12 MB/s ceiling exists for
# the inbound peaks during consensus ramp-up. RelayBandwidthBurst MUST be
# >= RelayBandwidthRate.
RelayBandwidthRate 12 MB
RelayBandwidthBurst 25 MB
# Daily/monthly accounting. Use this to STOP the relay if it exceeds the
# upstream cap rather than letting upstream throttle / bill you. Format:
# AccountingMax <bytes>; reset on the 1st of each month at midnight UTC.
AccountingMax 9 TB
AccountingStart month 1 00:00
# ---------- family ----------------------------------------------------------
# If you operate more than one relay (now or in the future), declare them as
# a family so Tor clients don't pick two of yours in the same circuit. The
# value is a comma-separated list of fingerprints (NOT nicknames). Fill this
# in AFTER first start, when the fingerprint of THIS relay is known —
# everything in the family points at everything else, mutually.
# MyFamily <FP1>,<FP2>,<FP3>
# ---------- protocol -------------------------------------------------------
# Disable the SOCKS port — this box is NOT for the operator's local Tor
# usage. A relay listening for local SOCKS is a footgun.
SocksPort 0
ClientUseIPv4 0
ClientUseIPv6 0
# ---------- logging --------------------------------------------------------
# notice-level only; the relay is not interesting to debug at INFO+ except
# during the first 24h of bringup, where temporary INFO is justified.
Log notice file /var/log/tor/notice.log
DataDirectory /var/lib/tor
# ---------- safety nets ----------------------------------------------------
DisableDebuggerAttachment 1
HardwareAccel 1
# Cap memory in case a peer floods cells. Tor's cell pool is the dominant
# memory user on a busy relay; 2 GB is a safe ceiling on a 4 GB VPS.
MaxMemInQueues 2048 MB
The RelayBandwidthRate calculation is worth understanding. AccountingMax is the hard ceiling Tor enforces — if the relay hits that monthly cap before the calendar month is over, Tor pauses itself until the reset, which is graceful but produces a 1-day-or-more outage for clients on the relay. Set it 10% below your actual upstream cap so a brief overshoot doesn’t trigger upstream throttling. The 9 TB / 10 TB choice in the example is that 10% safety margin.
RelayBandwidthRate is the sustained-rate limit Tor uses for shaping; the burst rate kicks in for short intervals. Tor’s own bandwidth-self-test publishes a measured-bandwidth value into the consensus that’s used by the bandwidth-authority weighted load balancer; clients then route proportional to consensus weight. [Tor Project — bandwidth scanner v2 spec]
Make sure /var/log/tor/ exists and is owned by debian-tor:
mkdir -p /var/log/tor
chown debian-tor:debian-tor /var/log/tor
chmod 0750 /var/log/tor
Open the firewall for ORPort:
nft add rule inet filter input tcp dport 9001 accept
Restart Tor and tail the journal:
systemctl restart tor
journalctl -u tor@default -f --since '60 seconds ago'
Watch for the four milestone log lines:
Configuration was valid— torrc parsesBootstrapped 100% (done)— relay has fetched consensusSelf-testing indicates your ORPort <ip>:9001 is reachable from the outside. Excellent.— other relays can reach you on the ORPortPerforming bandwidth self-test...done.— Tor has completed its initial bandwidth probe
All four should appear in the first 5-10 minutes after restart. If “ORPort is reachable” doesn’t appear, the firewall or the upstream’s port-blocking is the culprit — check from a third box with nc -z <vps-ip> 9001.
Step 4 — read the relay fingerprint
The relay’s identity fingerprint is the public-key-hash that uniquely identifies it on the Tor network. Read it after the first start:
is01cypher 1A2B3C4D5E6F7890ABCDEF1234567890ABCDEF12
The 40-hex-character fingerprint is the value that goes into MyFamily on every other relay you operate, AND is what Tor Metrics and Relay Search show. [Tor Metrics — Relay Search]
If you operate more than one relay, edit /etc/tor/torrc on EACH box, set MyFamily to the comma-separated list of every relay’s fingerprint, and restart each one. Failing to set MyFamily means clients can pick two of your relays in the same circuit, which defeats the load-balancing-by-operator-diversity logic the network depends on.
# Example MyFamily on relay 1 (fingerprint $FP1):
MyFamily 1A2B3C4D5E6F7890...,FEDCBA0987654321...,789ABCDEF0123456...
Step 5 — the four-week ramp-up
A new relay does NOT immediately receive its expected traffic share. The bandwidth-authority’s measurement system has a multi-week ramp:
| Period after launch | Traffic share | Reason |
|---|---|---|
| Week 1 | < 5% of expected | Consensus weight defaults to 0; only a handful of bandwidth scanners route through you. |
| Week 2 | 5-30% | First weighted measurements published; clients begin selecting you. |
| Week 3 | 30-70% | Bandwidth-authority confidence interval narrows. |
| Week 4+ | 70-100% | Steady state — your relay is now load-balanced at its measured weight. |
| Month 6+ | + Stable / Guard flags | Once the relay has been online consistently for ~14 days uptime in the last 30, the directory authorities issue the Stable flag; the Guard flag follows ~2 months in. |
Don’t panic if week one looks slow. The relay is correctly configured if the consensus shows it; the traffic will arrive. [Tor Project — relay lifecycle FAQ]
To see your relay’s status during ramp-up, check Relay Search:
https://metrics.torproject.org/rs.html#search/1A2B3C4D5E6F7890ABCDEF1234567890ABCDEF12
The page shows the consensus weight, the flags currently assigned (Fast, Stable, Running, Valid, V2Dir, eventually Guard), the measured bandwidth, and the historical uptime graph.
Step 6 — abuse handling for the rare non-exit complaint
Non-exit relays receive abuse complaints rarely (the relay is never the source IP of user-visible traffic) but not zero. The two complaint classes worth being prepared for:
-
“Your IP appeared in our IDS as Tor traffic.” This is true and is the entire point of the relay. Reply with the standard non-exit-relay template — the brand maintains one at
/legal/tor-non-exit-template.txtadapted from the Tor Project’s template-bundle. [Tor Project — Tips for running an exit/relay node] -
“Connections from your IP are being used to attack our service (e.g. brute-force SSH, web-app scraping).” This is materially the same complaint as the previous one — the brute force is being CONDUCTED via Tor by a user, the user’s exit is some OTHER relay, your relay is one of two intermediate hops in the circuit. Reply with the same template and add a note that your relay is non-exit and therefore did not originate the traffic.
The brand template, abbreviated:
Subject: Re: Abuse report regarding <ip> — non-exit Tor relay
Thank you for the report.
The IP address <ip> hosts a Tor middle-relay (non-exit), nickname <nickname>,
fingerprint <fp>. A middle-relay forwards encrypted traffic between other Tor
relays; it does not originate, terminate, or have visibility into traffic
content. The relay is operated under [Iceland Höfundalög / Romania Law 8/1996 /
Swiss Telecommunications Act §3a] which establishes the operator's neutral-
intermediary status for traffic forwarded in this role.
The activity you observed is being conducted via a Tor circuit; the source
of that traffic is an exit relay (a different operator, a different IP
address) selected by the Tor user. Please direct your complaint to the exit
operator if identifiable, or to the abuse-handling teams of the Tor Project
if it is not.
Operator contact: <CONTACT-EMAIL>
Tor Project resources: https://support.torproject.org/abuse/
If the upstream provider receives the complaint and forwards it to you, reply within 48 hours. Silence is the worst outcome — upstream interprets it as “customer is unresponsive” and may take the box offline preemptively.
Step 7 — four post-launch checks
Check 1 — clock skew
Tor circuits depend on synchronised time. A relay with > 30 seconds of clock skew is rejected from the consensus.
chronyc tracking
Confirm Stratum is ≤ 3 and System time deviation is sub-second. If chronyd is not running, install and enable:
apt install -y chrony
systemctl enable --now chrony
Check 2 — ORPort reachable
journalctl -u tor@default -n 200 --no-pager | grep -E 'ORPort.*reachab'
Expected: one line saying Self-testing indicates your ORPort ... is reachable from the outside. Excellent. If you see not reachable, fix the firewall.
Check 3 — descriptor publication
journalctl -u tor@default -n 500 --no-pager | grep -i 'descriptor' | head
Expected: at least one Tor opening new descriptor and one Successfully uploaded server descriptor per descriptor regeneration interval (every ~18 hours by default).
Check 4 — bandwidth accounting
grep -i 'accounting' /var/log/tor/notice.log | tail
Expected: regular Tor: Accounting period in N days, M hours; bytes read/written so far: X / Y lines. If you see Hibernating! ...wakeup time it means you’ve hit the AccountingMax — relay is correctly self-pausing, but you’ve under-set the cap relative to the upstream allowance.
Closing — what to do next
The relay is operational. Order of next steps:
- Subscribe operator email to the
tor-relaysmailing list — the canonical place where consensus-affecting changes, security advisories, and bandwidth-scanner deployments are announced. - After ~14 days uptime, check the Tor Metrics search page and confirm the
Stableflag has been issued. - If you intend to operate more relays, set
MyFamilyon every relay PROACTIVELY; back-filling family declarations on already-running relays is operationally fine but slightly delays the network from realising the diversity. - Read
bgp-resilience-for-tor-relay-operatorsfor the network-resilience pass — single-AS / single-DC relays are a known weakness of the Tor topology that the network is actively trying to spread out.
Don’t run the relay AND a hidden service on the same box. Co-tenancy of those two roles is a documented deanonymisation surface (the relay’s bandwidth-self-test creates a side-channel against the hidden-service circuit). Run the relay on its own VPS, full stop.
// END OF DOC
$ cd /docs # back to the manual