Version: 25.5.18
In this tutorial, I will show you how to install a Tor server as a middle relay on a VPS. At the same time, you’ll set up a proxy server that allows you to use the Tor connection in a web browser (e.g., Firefox) to browse the internet anonymously. This way, your own browsing behavior is mixed with the traffic passing through the server.
🖥️ What do you need?
1. A VPS server with a public IPv4 address on the internet and enough free traffic per month (up to 2,5TB in our configuration)
2. Linux and SSH knowledge (terminal)
3. Docker and Docker-Compose installed (an installation script will also be shown)
4. The conviction to take action against censorship and restrictions on freedom on the internet 😊
We start and log in to the server:
ssh Username@Server-IP
Go to your Docker project folder, which in my case is located under /home/.
cd /home/
A folder named “tor” is created:
mkdir tor
And changed into this:
cd tor
🐳 If you don’t have Docker and Docker-Compose installed yet, here are some quick installation instructions. You can skip them if you like: First, install Docker by creating a file named “install.sh” in the /home/tor/ directory:
nano /home/tor/install.sh
The following content is added to the file (Thanks to Patrick Asmus: https://git.techniverse.net/scriptos/public-linux-docker-installer)
#!/bin/bash
# Script Name: docker-installer.v3.sh
# Beschreibung: Docker & Docker-Compose Installer für Ubuntu 22.04 Jammy und Ubuntu 24.04
# Aufruf: bash ./docker-installer.v3.sh
# Autor: Patrick Asmus
# Web: https://www.techniverse.net
# Git-Reposit.: https://git.techniverse.net/scriptos/linux-docker-installer
# Version: 3.4.5
# Datum: 15.11.2024
# Modifikation: change docker-compose version
#####################################################
# Variablen:
COMPOSEVERSION="v2.30.3"
# Betriebssystem und Version prüfen
OS=$(lsb_release -is)
VERSION=$(lsb_release -rs)
if [ "$OS" != "Ubuntu" ] || { [ "$VERSION" != "22.04" ] && [ "$VERSION" != "24.04" ]; }; then
echo "Dieses Script unterstützt nur Ubuntu 22.04 und Ubuntu 24.04. Installation abgebrochen."
exit 1
fi
# Variablen
USER="root"
DOCKER_ROOT_DIR="/var/docker-bin"
COMPOSE_DIR="/home/docker-container"
# Docker installieren
sudo apt update
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
if [ "$VERSION" == "22.04" ]; then
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
elif [ "$VERSION" == "24.04" ]; then
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
fi
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io
sudo usermod -aG docker $USER
# Docker-Root-Verzeichnis ändern & Compose Verzeichnis erstellen
sudo systemctl stop docker
sudo mkdir -p $DOCKER_ROOT_DIR
echo "{\"data-root\": \"$DOCKER_ROOT_DIR\"}" | sudo tee /etc/docker/daemon.json > /dev/null
cp /var/lib/docker/* $DOCKER_ROOT_DIR -r
rm -R /var/lib/docker
sudo systemctl start docker
mkdir -p $COMPOSE_DIR
# Docker-compose installieren (gleicher Prozess für beide Versionen)
sudo apt install -y curl
sudo curl -L "https://github.com/docker/compose/releases/download/$COMPOSEVERSION/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Optional: Plugin für Oh my ZSH aktivieren
echo "OhMyZSH Plugin für Docker hinzufügen"
sudo sed -i 's/plugins=(git)/plugins=(git docker)/g' /root/.zshrc
# Überprüfen der Installation
docker --version
docker-compose --version
exit 0
Then run the file:
cd /home/tor
bash install.sh
After completing the script, Docker and Docker-Compose are installed.
📁 Now we want to focus on the Tor server and create the following file in the /home/tor folder:
nano Dockerfile
Paste the following content into the file and save it – the current Tor version 0.4.8.16 is used:
FROM debian:bullseye
# Basis-Tools installieren
RUN apt-get update && apt-get install -y \
curl \
gnupg2 \
apt-transport-https \
ca-certificates \
python3 \
python3-pip \
git \
locales \
privoxy
# UTF-8 Locale setzen (für Nyx)
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && \
locale-gen
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8
# Offiziellen Tor-GPG-Schlüssel importieren
RUN curl -fsSL https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc \
| gpg --dearmor -o /usr/share/keyrings/tor-archive-keyring.gpg
# Tor-Repository einbinden
RUN echo "deb [signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.org/torproject.org bullseye main" \
> /etc/apt/sources.list.d/tor.list
# Tor installieren
RUN apt-get update && apt-get install -y \
tor \
deb.torproject.org-keyring && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# Nyx installieren
RUN pip3 install nyx
# Konfigurationsdateien & Startskript kopieren
COPY privoxy.config /etc/privoxy/config
COPY start.sh /start.sh
RUN chmod +x /start.sh
# Ports freigeben
EXPOSE 9001 9030 8118
# Startkommando
CMD ["/start.sh"]
A new file is created:
nano start.sh
This file ensures that Privoxy (our proxy server through which you can later access Tor via port 8118) and NYX only start after the Tor server has started:
#!/bin/bash
set -e
# Starte Tor im Hintergrund
tor -f /etc/tor/torrc &
# Warte kurz, bis Tor initialisiert ist
sleep 5
# Wenn ein Terminal vorhanden ist, starte Nyx in einem neuen Prozess
if [ -t 1 ]; then
echo "Starte Nyx zur Überwachung von Tor..."
nyx &
fi
# Starte Privoxy im Vordergrund (wichtig für Docker!)
exec privoxy --no-daemon /etc/privoxy/config
The next file you create:
nano torrc
The following content goes here:
Nickname Nickname
ContactInfo contact@proton.me
ORPort 9001 IPv4Only
DirPort 9030
ControlPort 9051
CookieAuthentication 1
ExitRelay 0
DataDirectory /var/lib/tor
RelayBandwidthRate 1 MB
RelayBandwidthBurst 2 MB
Log notice stdout
#Address VPS-IP(optional)
Of course, you’ll also need to change your relay’s nickname and contact email address accordingly. In our example, the Tor relay is only running as an IPv4 host, which is easier to implement. A new file follows:
nano privoxy.config
This is the configuration file of our proxy server:
listen-address 0.0.0.0:8118
forward-socks5t / 127.0.0.1:9050 .
logfile /dev/stdout
🚀 After you have created this file, you can build your own Docker image (everything will be saved and executed in the path /home/tor/):
docker build -t tor-privoxy-nyx .
You’ve now created your own Docker container with Tor Privoxy. You can verify this with the “docker images” command. The corresponding container should now appear here:

⚙️ Create the appropriate Docker-Compose.yml to start the container properly and safely:
nano docker-compose.yml
The file is saved in the /home/tor folder with the following content:
version: '3.8'
services:
tor-privoxy:
build: .
image: tor-privoxy-nyx
container_name: tor-privoxy-nyx
volumes:
- ./torrc:/etc/tor/torrc
- ./tor_data:/var/lib/tor
ports:
- "9001:9001"
- "9030:9030"
- "8118:8118"
restart: always
Now you’ve completed all the steps to run a Tor server as a middle node on our VPS server. You can now start the container in the background:
docker compose up -d
You can view log files with
docker logs -f tor-privoxy-nyx
If you find “100%” in the logs, you’ve done everything correctly:

It is also important that ports 9001 and 9030 are accessible from the Internet and are open in the firewall.
Cauction: Only Allow Connections from your private IP to Port 8118 or block it. Thats the proxy-server function.
🔍 There is also the following function test for the proxy server:
curl --proxy http://localhost:8118 https://check.torproject.org/
A confirmation should appear here that a connection via TOR was possible.
✅ What have you achieved in the tutorial?
- The latest version of TOR runs in a Docker container on the VPS server.
- Privoxy and NYX are installed
- Fingerprints and RSA Keys are saved in the “tor” directory outside the container
- The Tor server is publicly accessible via TCP ports 9001 and 9030.
- The proxy server that uses Tor is accessible via IP:8118 and can thus be specified as a proxy in the browser, for example (Cauction: Port 8118 only for your IP in the firewall settings of your vps)
- You are actively committed to freedom on the Internet 😊
You can watch statistic via nyx with:
docker exec -it tor-privoxy-nyx bash
nyx

Leave the Statistic-Page with STRG+C and then type “exit”.
On the following page you can also retrieve information about your own Tor Relay:
https://metrics.torproject.org/rs.html

bc1q8dxp9mlt3mkvaklu2vn8j6jteqyv53kschc90v

Lightning: itsc@strike.me
