Running multiple Tor daemons with Docker

Running a Tor relay helps give bandwidth back to the network, however it's not uncommon for new relay operators to be surprised at Tor's performance profile.

Tor is not multi-threaded, so operators arrive with multi-core machines and find that only a single core is actually being worked. However, it is possible to maximise use of multiple CPU cores by running multiple instances of the tor daemon - this documentation details how to do it using docker (although it's perfectly possible without containerisation too).

You can run up to two tor relays per IP, so if your system only has a single IPv4 address, the process you'll want to follow is as follows

Create two configuration files:

cat << EOM > torrc_1
Nickname MyRelay443
ORPort 443
SocksPort 0
ExitPolicy reject *:*
User debian-tor
DataDirectory /var/lib/tor
MyFamily MyRelay443,MyRelay9001

ContactInfo [your contact info]
EOM


cat << EOM > torrc_2
Nickname MyRelay9001
ORPort 9001
SocksPort 0
ExitPolicy reject *:*
User debian-tor
DataDirectory /var/lib/tor
MyFamily MyRelay443,MyRelay9001

ContactInfo [your contact info]
EOM

And then start two dockerised instances of Tor

docker run -d --name=tor_relay_1 \
-p 443:443 \
-v $PWD/torrc_1:/etc/tor/torrc \
--restart=always doudou34/tor-server


docker run -d --name=tor_relay_2 \
-p 9001:9001 \
-v $PWD/torrc_2:/etc/tor/torrc \
--restart=always doudou34/tor-server

This will bind one relay to tcp/443 and the other to tcp/9001. Because the instances share a MyFamily downstream clients will never build a circuit that transits both.

Multiple IPs

If you've got multiple IPs, you'll want to take a slightly different approach and bind to different addresses - the example shows use of IPv6 as well as IPv4

cat << EOM > torrc_1
Nickname MyRelay443
ORPort 7.8.9.10:443
ORPort [2001::ffff]:443
SocksPort 0
ExitPolicy reject *:*
User debian-tor
DataDirectory /var/lib/tor
MyFamily MyRelay443,MyRelay9001,MyRelay2443,MyRelay29001

ContactInfo [your contact info]
EOM


cat << EOM > torrc_2
Nickname MyRelay9001
ORPort 7.8.9.10:9001
ORPort [2001::ffff]:9001
SocksPort 0
ExitPolicy reject *:*
User debian-tor
DataDirectory /var/lib/tor
MyFamily MyRelay443,MyRelay9001,MyRelay2443,MyRelay29001

ContactInfo [your contact info]
EOM

cat << EOM > torrc_3
Nickname MyRelay2443
ORPort 1.2.3.4:443
ORPort [2001::beef]:9001
SocksPort 0
ExitPolicy reject *:*
User debian-tor
DataDirectory /var/lib/tor
MyFamily MyRelay443,MyRelay9001,MyRelay2443,MyRelay29001

ContactInfo [your contact info]
EOM

In order for this to work, when launching the docker containers you need to specify that host networking should be used

docker run -d --name=tor_relay_1 \
--net=host \
-v $PWD/torrc_1:/etc/tor/torrc \
--restart=always doudou34/tor-server


docker run -d --name=tor_relay_2 \
--net=host \
-v $PWD/torrc_2:/etc/tor/torrc \
--restart=always doudou34/tor-server

docker run -d --name=tor_relay_3 \
--net=host \
-v $PWD/torrc_3:/etc/tor/torrc \
--restart=always doudou34/tor-server

However, if you're going to be running multiple instances, please proceed with caution and consider what it might look like if you suddenly dump a massive load of relays into the system. See Criteria for rejecting bad relays for an idea of what might cause you to trip a false positive.

As a guide

  • Always set MyFamily
  • Always set ContactInfo so you can be reached if something is wrong

If you do screw up, you're likely to see the following in your logs

"Fingerprint and/or ed25519 identity is marked rejected -- if you think this is a mistake please set a valid email address in ContactInfo and send an email to bad-relays @ lists.torproject.org mentioning your fingerprint(s)?"

Bridge

You can also run a Tor bridge in docker, although you shouldn't run it on the same IP as a relay (relay IPs are published, and therefore easily discovered and blocked by the very people that bridges are supposed to protect from)

cat << EOM > bridgerc
RunAsDaemon 0
SocksPort 0
BridgeRelay 1
Nickname DockerObfs4Bridge
Log notice file /var/log/tor/log
Log notice stdout
ServerTransportPlugin obfs4 exec /usr/bin/obfs4proxy
ExtORPort auto
DataDirectory /var/lib/tor

# Replace these
ORPort [Your IP]:9001
ServerTransportListenAddr obfs4 [Your IP]:443
ContactInfo [Your contact email]
EOM

# Start the container
docker run -d \
--restart always \
--name tor-bridge \
-v bridge-data:/var/lib/tor \
-v $PWD/bridgerc:/etc/tor/torrc:ro \
--net=host \
thetorproject/obfs4-bridge:latest

Conclusion

Whether you're running a couple of containers, or using multiple IPs, your relay should now be up and running. It may take a little time for you to see any appreciable traffic, see Lifecycle of a new Relay for more information on why this is.

You should also sign-up for the tor-relays mailing list - it provides another avenue for you to spot notification of issues with your relay, as well as providing a venue to seek support.