Setting up a hidden service is not difficult, despite all the headlines lately of major busts and it often being referred to as the “dark net”. In this quite short guide, we have the very simple aim of setting up a hidden service to serve up static HTML pages using Nginx. I could write a whole thesis on why using Nginx is superior to Apache for this use case, but for now I shall keep it simply to “it’s simpler and more secure”.

This guide is in no way meant to be exhaustive here. This is not a hardening guide. This is here to get you started with your first hidden service. You can rent a VPS to do this, or you can even host it on a virtual machine on your computer (it makes no difference – really).

Now I intend for this to be as accessible as possible but there is a very small set of requirements. I don’t believe this will rule out anyone who is intending on setting up a basic hidden service.


– Know how to SSH into a VPS/server
– Running Debian 7 (Wheezy) 64 bit

What I would recommend for your Debian installation is at least 256 MB RAM, 1 core or more and 8Gb or more hard drive space. If you are installing Debian on your local machine, you do not need to install anything but the very base files. Everything you  need in this guide will be installed as we go along. However for the purpose of this guide, I will act like you are using a basic VPS. Commands will be highlighted in purple & configuration entries in blue.


Contents at a glance:

1. Connect to the server
2. Retrieve some packages
3. Setup user
4. Add user to sudoers & basic SSH configuration
5. Download & install Tor
6. torrc file configuration & hidden service key generation
7. Nginx installation & configuration


1. Connect to the server

To SSH into your VPS, it is very simple. If you have a Linux computer, go to the command line and type:

ssh root@<ip-address-here>

This will prompt you to enter the root password and once you have entered it, you should be logged in as root!


2. Retrieve some packages

As root, type the following command:
apt-get update && apt-get upgrade && apt-get install sudo nano
You will then be told how much additional space is required to install the above packages after the package list has been updated, and the updates downloaded. Type “Y” and hit enter to accept and install them.


3. Setup user

It is recommended you never run any software as root when you can avoid it. So as root type:

adduser user

This will add a new user called “user” (feel free to replace this with whatever you want). You may be asked for various other bits of information like full name, office number etc, you can just hit enter to skip them. At the end you will be asked “Is the information correct?”, again type Y and hit enter to confirm.


4. Add user to sudoers & basic SSH configuration

For those not familiar with Linux systems, sudo is the package which enables users to obtain superuser capabilities just like root for certain tasks. This allows a user to login to the system and manage it without needing to switch to root. To add your new user to the sudo list, type the following as root:
sudo adduser user sudo

Now “user” has been added to the sudoers list. Now we should make some very quick and basic changes to your sshd process to block off anyone trying to SSH into your VPS as root and a simple technique to stop brute force SSH attempts.

To open up your sshd configuration, type:
nano /etc/ssh/sshd_config

The first option to find is “Port 22” which should be near the top of the file. Change the port “22” to something non-standard, for example 22555, so the new entry should look like this:
Port 22555

Now you need to disable root SSH login attempts. Find the option “PermitRootLogin yes” and change it to “no” so the new entry is as follows:
PermitRootLogin no

Now as root, reload the SSH service using:
service ssh reload

This reloads sshd, and your changes should now take effect. Note that in future when you SSH into your server, you must remember the new port and login as a user. So for example, if your new user is called “user” and the port you changed the above setting to is 22555, your new ssh command is:

ssh -p 22555 user@<ip-address-here>


5. Download & install Tor

The first and most important thing that must be done is to update the sources list to the official Tor Project repository. To make this easy for you, I have reduced this to a single command:

echo ‘deb wheezy main’ >> /etc/apt/sources.list && echo ‘deb-src wheezy main’ >> /etc/apt/sources.list && gpg –keyserver –recv 886DDD89 && gpg –export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | sudo apt-key add – && apt-get

This means the official Tor repository is now added to your sources list, and you have downloaded the official Tor Project keys to your server to cryptographically ensure the binaries you receive are genuine. Now to install Tor itself, we want to switch to our newly created user which in this instance I have called “user”. This can be done by running the command:

su user

Now to install the Tor binary and the Tor Project keyring, run:

sudo apt-get update && sudo apt-get install tor

Tor is now installed and automatically starts!


6.  torrc file configuration & hidden service key generation

The torrc file is the configuration file Tor reads your options from. The file is full of information that we don’t currently need, and so I recommend deleting the existing torrc file and creating a new one. This can be done using a single quick command:

sudo rm /etc/tor/torrc && sudo nano /etc/tor/torrc

This should now remove the existing torrc and open a new one up in the nano file editor. The minimum you will require for running a hidden service is the following configuration, which can be pasted and saved in the new file:

DataDirectory /var/lib/tor
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80

Pressing Ctrl + X will save the file. Now to generate the hidden service key and make the Tor process take note of our changes, we should reload the process:

sudo service tor reload

To find out what your hidden service key is (also known as the hostname), use the cat command. Write this hostname down somewhere or copy it to your clipboard – you will need it in a moment:

sudo cat /var/lib/tor/hidden_service/hostname

The private key can be found at (you don’t need to view this right now, this is for your information only):

You can share the hostname key with anyone you want to visit your site. It should look something like qhzwfy24i22jchdw.onion (this is the one I generated when testing this tutorial).


7. Nginx installation & configuration

As user, type the following command to install Nginx:

sudo apt-get install nginx

Now we need to make a new directory in /var/www/ for our hidden service site. Use the mkdir command to do this:

sudo mkdir -p /var/www/hidden_service/

Finally, we need to set the permissions for the new folders:

sudo chown -R www-data:www-data /var/www/hidden_service/ && sudo chmod 755 /var/www

So we can test the setup in a moment, let us generate a quick test index page, very similar to how we made the new torrc file earlier:

sudo nano /var/www/hidden_service/index.html

In this file, paste the following snippet of HTML code and save the file:

<html> <head> <title>Hidden Service Success</title> </head> <body> <h1>Success: You Have Set Up Your Hidden Service With NGINX</h1> </body> </html>

Now comes the part where we need to configure Nginx to listen in the correct place. In Apache, this would be called a Virtual Host but on Nginx they are known as Server Blocks. To make the new Server Block, we are going to to use the nano command again:

sudo nano /etc/nginx/sites-available/hidden_service

In this newly created file, paste the following snippet of information. Using the hostname you copied earlier to replace qhzwfy24i22jchdw.onion with your own address:

server {

root /var/www/hidden_service/;
index index.html index.htm;
server_name qhzwfy24i22jchdw.onion;

Save and exit this new file. The last step now is to create a symbolic link between the sites-available directory and sites-enabled directory. In Apache, we use a2ensite but Nginx does not have such a function, but instead we can use the following command to form one:

sudo ln -s /etc/nginx/sites-available/hidden_service /etc/nginx/sites-enabled/hidden_service

Finally, restart Nginx for all the new configuration options to take effect:

sudo service nginx restart


That’s it! You now have your own hidden service online! Using the Tor Browser, if you visit your hostname (the 16 characters followed by the .onion) you should now see a page reading “Success: You Have Set Up Your Hidden Service With NGINX”. You can now upload your files in the /var/www/hidden_service/ directory or follow other setup guides on the net to install other applications!

I hope this guide has been of some use to you, particularly if you are new to hidden services. For the non-techies out there, it is a considerable stepping stone to understanding how the web works once you have gone through the steps of setting up your own, particularly using a hidden service! If you have any further questions on this, have errors or want me to write further guides on installing specific applications, please do let me know by getting in touch via the Contact page or catch me on Twitter @CthulhuSec!