Running Tor in a chroot

Steven Murdoch tor+Steven.Murdoch at
Wed Jun 2 17:01:52 UTC 2004

The documentation suggests running Tor in a chroot, so I have been
trying to do this, but it is not entirely trivial and I couldn't find
any documentation on this, so I thought I would pass on my
experiences. Hopefully these will help anyone else who would like to
do this. Any comments would be appeciated.

This is on Debian GNU/Linux 3.0 (Woody) with a 2.4.18 Debian kernel.

I am using tor-0.0.7pre1 since I had a few problems with 0.0.6, in
particular log messages about switch_id being dropped, but these were
fixed in src/or/main.c v1.273 and so work in release 0.0.7pre1.

Commands I executed are enclosed within "=== ... ===".

Firstly the configuration stage:
gpg tor-0.0.7pre1.tar.gz.asc
tar -xzvf tor-0.0.7pre1.tar.gz
cd tor-0.0.7pre1
umask 022
./configure --prefix=/tor
The "prefix" at the configure stage is the one used at runtime, so
should be set relative to the chroot. I didn't use "/" as the prefix
since that would result in the hardcoded paths starting with "//"
which should work under *nix, but IIRC they break in Windows. For
example: "RouterFile //etc/tor/dirservers".

Then installation:
sudo adduser --disabled-login --gecos "Tor user,,," tor
sudo mkdir $TORCHROOT
sudo make install prefix=$TORCHROOT/tor exec_prefix=$TORCHROOT/tor
I firstly created a new user for the purposes of running Tor. Running
the install within the chroot would be difficult since I would need to
install a shell and other commands the makefile used, so I ran it
outside, but set the install time prefix to be different than the
runtime prefix. I had to set both "prefix" and "exec_prefix" because
the Makefile had "exec_prefix" hardcoded:
[From tor-]
prefix = /
exec_prefix = /
datadir = ${prefix}/share
sysconfdir = ${prefix}/etc

Then I copied over shared the libraries required by Tor:
ldd $TORCHROOT/bin/tor
sudo mkdir $TORCHROOT/lib
sudo cp /usr/lib/ /usr/lib/ \
 /lib/ /lib/ /lib/ $TORCHROOT/lib
I used ldd to find out which shared libraries were needed, and copied
them over to $TORCHROOT/lib. To keep things simple, I put libraries in
/lib since /lib and /usr/lib are hardcoded into the Linux dynamic
linker. If you put them in other places then you will need to set
LD_LIBRARY_PATH (see gotchas).

Tor needed access to /dev/(u)random so I created that:
sudo mkdir $TORCHROOT/dev
sudo mknod -m 644 $TORCHROOT/dev/random c 1 8
sudo mknod -m 644 $TORCHROOT/dev/urandom c 1 9
Tor seems to prefer to seed the RNG on /dev/urandom if it exists before
trying /dev/random. The function "crypto_seed_rng()" only seems to be
called once, so depending on preference there may be a case to switch
to a blocking RNG like /dev/random.

Since chroot needs to be run as root, but Tor does not, I set the
config file to switch UID/GID on startup:
sudo cp $TORCHROOT/etc/tor/torrc.sample $TORCHROOT/etc/tor/torrc
sudo sh -c "echo -e 'User tor\nGroup tor' >> \
sudo mkdir $TORCHROOT/etc
sudo sh -c "grep ^tor /etc/passwd > $TORCHROOT/etc/passwd"
sudo sh -c "grep ^tor /etc/group > $TORCHROOT/etc/group"
switch_id() calls getpwnam() which needs /etc/group and /etc/passwd so
I copied these over too.

I thought this would work, but getpwnam() failed, so after digging
through strace output I found it required some other shared libraries
that did not show up in ldd output:
sudo cp /etc/nsswitch.conf $TORCHROOT/etc
sudo cp /lib/ $TORCHROOT/lib
sudo cp /lib/ $TORCHROOT/lib
sudo mkdirhier $TORCHROOT/var/run

Finally I ran tor:
sudo chroot $TORCHROOT /tor/bin/tor
which produced the following output:
Jun 02 16:38:43.382 [notice] tor_main(): Tor v0.0.7pre1. This is \
 experimental software. Do not use it if you need anonymity.
Jun 02 16:38:46.202 [notice] circuit_send_next_onion_skin(): Tor has \
 successfully opened a circuit. Looks like it's working.

There are a few gotchas: 

Presumably torify will be run outside of the chroot, but its config
file location is set to be relative to the chroot by ./configure. I
can't think of any neat way to fix this.

The library situation is a bit fragile. There may be some other
libraries, like libnss_compat which don't show up in ldd but are
required. Also there may be other files required that I haven't copied
into the chroot. I have tested it as a client and it seems to work OK,
but I haven't tried it as a server yet.

If you put shared libraries outside of /lib and /usr lib you need to
set LD_LIBRARY_PATH, but sudo drops the LD* environment variables for
security reasons. If you want to put libraries in, say /tor/lib, you
need something like:
 sudo su -c "export LD_LIBRARY_PATH=/tor/lib; chroot $TORCHROOT \

Hope this helps,
Steven Murdoch.

More information about the tor-dev mailing list