December 29, 2019

Guide: Host your own .onion site using nginx and Tor

Use nginx to install and configure virtual hosts to enable connectivity on the Tor network using minimal bloat.

For demo and fun (woo!) - hop over to our .onion

It's good practice to prevent nginx leaking any information to the not-so-friendly by changing the default return code, in this case refusing connection and turning server_tokens off by default.

Traveling through Tor

This demo we're using 'Bionic' Ubuntu 18.04 LTS

Only use the latest releases by updating the Repository.

echo -e "deb bionic main\ndeb-src bionic main" > /etc/apt/sources.list.d/tor.list
Configure Tor Repository
wget -qO- | gpg --import 
gpg --export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | apt-key add 
Cut the keys for the new place 🔐

Perfect, everything has verified "OK"- Let's proceed.

Update the repo. Upgrade the system. Install our packages; tor, nginx

apt update && apt -y upgrade && apt-get -y install nginx tor

Insist we start Tor and nginx on boot, who turns off intentionally?

systemctl enable nginx && systemctl enable tor && systemctl start tor.service
Enable Tor and nginx boot

Before proceeding now would be the ideal time to configure firewall rules.
I'd' recommend by default let's deny incoming. Whitelist YOUR_IP to SSH.
For demonstration purposes; we're allowing public connections to 80 and 443 - to enable a clear net version.
We need to allow connections for port 9050 for Tor delivery.

ufw default deny incoming && ufw allow from YOUR_IP to any port 22 && ufw allow 80 && ufw allow 443 && ufw allow 9050 && ufw enable
Firewall rules - Change YOUR_IP | It's a yes from me

Open /etc/nginx/nginx.conf - turn off our server_tokens. Change hash_bucket_size to allow for a lengthy address. I tend to use nano.

nano /etc/nginx/nginx.conf 

Within http {

server_names_hash_bucket_size 125;
server_tokens off;


Exit and Save:  CTRL + x + y | ENTER
Do test for any errors, reload nginx.

nginx -t
nginx -s reload

Proceed to configure a Hidden Service within Tor, using your editor open /etc/tor/torrc

nano /etc/tor/torrc
HiddenServiceDir /var/lib/tor/nginx/
HiddenServicePort 80

Exit and Save:  CTRL + x + y | ENTER
Reload Tor, to generate your .onion address.

service tor reload
cat /var/lib/tor/nginx/hostname
You may find; cat: /var/lib/tor/nginx/hostname: No such file or directory

Okay, speedy fingers! Wait a couple of seconds for Tor to load.

cat /var/lib/tor/nginx/hostname

Perfect - http://y3jzukyhsjymr4dp.onion/

Success. This mirrors our default virtual host.

I wouldn't recommend stopping there..
We're going to change ports, tighten things up slightly. This virtual host configuration below will improve security and only on the Tor network, without a clear net version - prevent snoopers directory listing, gaining potential information.

Unlink the nginx default configuration

sudo unlink /etc/nginx/sites-enabled/default

Create the new blackhole

nano /etc/nginx/sites-available/default-blackhole


server {
  listen      81 default_server;
  server_name _;
  access_log  off;
  return      444;

This ensures nginx returns 444.

Connection closed. Status code used to instruct nginx to close the connection without sending a response to the client.

Create the symlink:

sudo ln -s /etc/nginx/sites-available/default-blackhole /etc/nginx/sites-enabled/

Now is the moment. Let's create our only.on.onion site:

nano /etc/nginx/sites-available/only.on.onion


server {
  listen 81;
    root /var/www/tor/;
    allow all;
  # This is the location block invalid requests will be routed to
  location @blackhole {
    return 444;

  # This block redirects invalid requests to @blackhole
  location / {
    # Route all errors to @blackhole
    error_page 403 404 500 502 503 504 =444 @blackhole;
Change: 'root' and 'listen'

Root - Directory where you files are to be
Listen - Port number for the nginx virtual host

Exit and Save:  CTRL + x + y | ENTER
Another, Symlink, please

sudo ln -s /etc/nginx/sites-available/only.on.onion /etc/nginx/sites-enabled/

Test the nginx configuration before reloading

nginx -t

Reload nginx

nginx -s reload

Proceed to change your port in Tor, using your editor open /etc/tor/torrc

HiddenServiceDir /var/lib/tor/nginx/
HiddenServicePort 80

Exit and Save:  CTRL + x + y | ENTER
Reload Tor to change port number

service tor reload && cat /var/lib/tor/nginx/hostname


To follow up with
Generate the SSL certificates through Lets Encrypt

Hire me..

Related articles
Simple guide: Tor Middle Relay

Guide | Insight | Life | Linux | Tor