Version 19 (modified by trac, 10 years ago) (diff)


## Copyright (c) 2004 Steven J. Murdoch. ## Distributed under the MIT license, ## See ./LegalStuff for a full text [:../:up to Tor]

The documentation for Tor suggests running it in a chroot but I have not found this to be entirely trivial and I couldn't find any documentation on how to achieve this.

This document describes how I set up Tor to run in a chroot on Debian GNU/Linux 3.0 (Woody) with a 2.4.18 Debian kernel, but it should be applicable to other Tor versions and most of it will be the same for other Linux distributions. The original version of these instructions was posted on the or-dev mailing list.

Another way with debian is to use debootstrap to install a complete separate environment for tor and privoxy.

Scripts for easy chrooting of Tor and Privoxy on Debian is available at


Unpacking and compilation

gpg tor-
tar -xzvf tor-
cd tor-
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 hard-coded paths starting with // which should work under *nix, but IIRC they break in Windows. For example, in the torrc.sample file you would have the following line: RouterFile //etc/tor/dirservers.

Copying files

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 hard-coded.

System setup

Shared libraries

Tor 0.1 needs libevent, so to install this from Peter Palfrader's backport, add the following lines to /etc/apt/sources.list

deb experimental-woody main
deb-src experimental-woody main

Then run

sudo apt-get update
sudo apt-get install libevent1 libevent-dev

To copy over the required libraries, run

ldd $TORCHROOT/tor/bin/tor
sudo mkdir $TORCHROOT/lib
sudo cp /usr/lib/ /usr/lib/ /usr/lib/ \
 /lib/ /lib/ /lib/ /lib/ \
 /usr/lib/ $TORCHROOT/lib
sudo cp /lib/libnss* /lib/libnsl* /lib/libresolv* /usr/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 notes). The libraries libnss* and libnsl* were not listed in the ldd output, but if they are not included then getpwnam() and gethostbyname() will fail.

Static (i.e. no external libraries

Another way to compile tor is using special flags to reduce liability on libraries ; however be aware that if another vulnerability comes out in SSL, once you have upgraded SSL you will need to recompile tor.

To achieve a "static" binary (one that requires no external libraries) you can pass other arguments to configure, for example:

LDFLAGS="-static" CFLAGS="-static" ./configure --prefix=/tor

Device nodes

sudo mkdir $TORCHROOT/dev
sudo mknod -m 644 $TORCHROOT/dev/random c 1 8
sudo mknod -m 644 $TORCHROOT/dev/urandom c 1 9
sudo mknod -m 666 $TORCHROOT/dev/null c 1 3

Tor needed access to /dev/(u)random so I created these. Also /dev/null is needed if Tor is run as a daemon.

For those who are running tor on OpenBSD and have the default nodev option set on your partition where you've chrooted tor to, which in turn gives you errors about not being able to access /dev/null, you may use OpenBSD's virtual filesystem support to create a small dev filesystem for tor. This prevents normal users from doing potentially nasty things to your raw devices, had you simply removed the nodev option to get things working.

cd /home/tor
sudo /bin/mkdir dev
sudo /bin/dd if=/dev/zero of=devfs bs=1024 count=256
sudo /usr/sbin/vnconfig -c -v /dev/svnd0c devfs
sudo /sbin/newfs /dev/svnd0c
sudo /sbin/mount /dev/svnd0c dev
cd dev
sudo /sbin/mknod -m 444 urandom c 45 2
sudo /sbin/mknod -m 444 random c 45 0
sudo /sbin/mknod -m 666 null c 2 2

Configuration files

sudo mkdir $TORCHROOT/etc
sudo sh -c "grep ^tor /etc/passwd > $TORCHROOT/etc/passwd"
sudo sh -c "grep ^tor /etc/group > $TORCHROOT/etc/group"
sudo cp /etc/nsswitch.conf /etc/host.conf /etc/resolv.conf /etc/hosts $TORCHROOT/etc
sudo cp /etc/localtime $TORCHROOT/etc
sudo mkdirhier $TORCHROOT/var/run

switch_id() calls getpwnam() which needs /etc/group and /etc/passwd so I copied these over too. Also getpwnam() and gethostbyname() needs nsswitch.conf /etc/host.conf, /etc/resolv.conf, /etc/hosts and access to /var/run. To get the timezone correct /etc/localtime is needed.

Tor configuration

sudo cp $TORCHROOT/tor/etc/tor/torrc.sample $TORCHROOT/tor/etc/tor/torrc
sudo sh -c "echo -e 'User tor\nGroup tor' >> \

Since chroot needs to be run as root, but Tor does not, I set the config file to switch UID/GID on startup.


sudo chroot $TORCHROOT /tor/bin/tor

which produced the following output:

[notice] Tor v0.1.0.11. This is experimental software. Do not rely on it for strong anonymity.

and terminate it with Ctrl+C

[err] Catching signal TERM, exiting cleanly.

Starting on boot

This part is quite Debian specific, but modifications to it should be applicable to other Linux distributions and *nix operating systems.

Add the following to $TORCHROOT/tor/etc/tor/torrc

PidFile /var/run/tor/
Log notice file /var/log/tor/log
RunAsDaemon 1

then run

sudo wget -O /etc/init.d/tor
sudo wget -O /etc/default/tor
sudo wget -O $TORCHROOT/tor/bin/tor-chroot
sudo chmod 755 /etc/init.d/tor etc/default/tor $TORCHROOT/tor/bin/tor-chroot
sudo update-rc.d tor defaults 19
sudo /etc/init.d/tor start

This downloads my modifications to Peter Palfrader's Debian Tor init script and a small wrapper which will perform the chroot. The scripts are not on the wiki so that they are not maliciously modified. Running update-rc.d will set up the start and stop links in the correct runlevel directories.

Setting up as a server

sudo mkdirhier $TORCHROOT/var/lib/tor
sudo chown tor.tor $TORCHROOT/var/lib/tor

# Set up server details, including the data directory:
# "DataDirectory /var/lib/tor"
sudo vim $TORCHROOT/tor/etc/tor/torrc

sudo /etc/init.d/tor restart

This creates the data directory and ensures it is owned by the tor user. The default location in the torrc.sample is inside the install prefix, unlike the log and pidfile locations so I change this to be /var/lib/tor. You will also have to set up the other server configuration options (Nickname, Address, ORPort, ORBindAddress, ExitPolicy). Then mail the file $TORCHROOT/var/lib/tor/fingerprint as described in configuring a server.


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.

Anchor(ldpath)? 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 /local/bin/tor"

-- StevenMurdoch

-- Simon B, bit about -static