The dark web is often associated with illegal practices or activities, and is generally portrayed by the mainstream media as a sort of black market bazaar which focuses on illegal purchases. While this may be true for a few out there, the special configurations required to access the dark web offer many advantages – this being the main concern of users no matter their reason for visiting.
One such advantage is that hidden sites can only be hosted and/or accessed using Tor connections and browsers, granting both the host and the visitor a fairly high level of security through anonymity and encryption, as well as privacy. With this requirement, hidden sites are not indexed by Google, Bing, Yahoo, DuckDuckGo, Yandex or other search engines, meaning that an automated effort by big-tech to index, suppress or stop certain phrases or patterns will not stop dark web hosts from sharing or passing information with their network or consumers, nor is there anyone to send a take-down order to, like on the open (or “normal”) web.
In this post, we will cover potential use-case scenarios for hosting hidden (Tor) websites then I’ll share my personal set up and provide a simple walk-through for setting up your own hidden site (in 8 steps). I’ve provided command line samples to copy/paste into your own terminal, making this project ‘Easy’ to ‘Extremely Easy’ for those with no Linux experience.
Use-Case
This post is for educational purposes only and should not be taken as advice to break the laws of your state or country, trafficking illegal or illicit information or data.
There are many systems used for passing updates or directions and sharing information within an underground network, but most notable is probably the Number Station. Starting at some point around World War I, numbers stations have operated as a simple and foolproof method for government agencies and underground networks to communicate instructions to assets working undercover. Messages which are encrypted, are typically preceded by a specific tune or song, then read by a woman or child. The message or numbers are then decrypted with a one-time pad by the assets who receive them. These are usually received by short wave radio, making them a one-way communication and thus reducing the assets’ and broadcaster’s exposure to risk. Here is a recording of a famous example:
This method has many advantages and while the broadcast stations can be quickly located and taken offline, this is a low-tech, compass & map skill equivalent to passing instructions – especially when/if other hi-tech communication systems fail or there are regional and sporadic service outages.
Project Scope
The goal of this project/post is to enable secure, private one-way communications which allow a centralized authority to distribute information and coordinate their network within a country such as Hong Kong, Venezuela, Colombia, Cuba, Brazil, and others in early phases of either occupation of foreign forces or oppression by their own governments.
This will work in a similar manner as a numbers station, but will utilize the Tor hidden sites for broadcast instead of shortwave, which offers many advantages. One of the biggest is that, unlike the numbers stations, your site is not likely to be discovered on accident, or even intentionally, nor do your recipients need to be within a specific range to receive the information.
Getting Started: Hardware Requirements
Keeping in alignment with this blog’s goal to train or deploy effective technologies and techniques on a budget, this project has minimal hardware requirements:
- A computer for setting up the hidden host system.
- Host system: either a raspberry pi, spare computer, or blank USB flash drive
- A way to operate the host system: You can use a keyboard and spare monitor, but I will be showing you how to use SSH from your laptop.
- Any Android cell phone (for your network): I highly recommend GrapheneOS for privacy and security reasons, but any Android will work – though there are some OPSEC concerns that I will write about in a later post.
On the last point: If you are planning to use a regular Google Android phone or tablet, Samy Kamkar has published some great research into how Every Android, iPhone and Microsoft computer is a war-driving device. While this matters to few today, it matters to almost everyone living within Hong Kong, Venezuela, Columbia and maybe Brazil pretty soon….. if you know what I mean.
Personal Hardware Setup
This section contains Amazon Affiliate links. For more information on their use on this site, visit the About Page.
I like to compartmentalize my devices by activity type where possible, but especially for this type of application. I also want this capability hosted on my own device that I have physical access to, so I was not interested in the virtual private server(VPS) options out there or running this locally in a virtual machine in the background of my computer.
I chose to use my Raspberry Pi 4 which I am preparing and operating from the Pop!_OS Linux distro (Ubuntu Based). This was actually comparable to the price of running a VPS by the 18 months mark and included just 3 items and 1 service, listed below:
- A computer for setup: Most people already have one of these.
- Raspberry Pi 4 (8 GB Ram): I bought this for expandability and because I put mine through the wringer, but the Raspberry Pi 4 B with 4 GB of ram will work just fine with this project.
- MicroSD Memory Card: I’ve used ScanDisk a lot for my cameras, but recently switched to PNY Class 10 for this application because it has been working better than the ScanDisk for this type of application. At the time of this writing, the link shown is a 3-pack of 64 GB for $20. What ever you get, remember that you need at least 16 GB of storage minimum.
- Alfa USB adapter: You can use any USB WiFi adapter that it is compatible with Debian/Ubuntu (or Pop!_OS Pi ed.) or you can plug in the Ethernet cable. I chose the Alfa WiFi adapter because I had it for another project, the antenna is detachable and can be replaced by Alfa APA-M25 Directional Panel Antenna (needed for another project), including those on Kali, which is important from a driver support standpoint.
Considerations for your Setup
Again, you can use any computer for this project, but I would first jot down your use-case. For this project, I considered the following:
- Mobility: My daily driver is a 17” laptop from System76. Its wide, flat, fragile, looks like a laptop and weighs roughly 5 lbs. The Pi is about the size of a credit card but weighs just a little more than the credit card. Not that I recommend running through the woods with this in the pocket of your Carhartt, but if you did, it would still be exposed to a lot less risk than the laptop.
- Concealment: With its small size, this can be concealed in many small cases or self-sealing Tupperware. Likewise, the damning evidence (MicroSD card) is about the size of a dime and can be concealed virtually anywhere, quickly if needed.
- Multi-Role Platform: Changing your Pi back to a NES Gaming platform, Mini-desktop for software development, or a SIGINT platform – is as simple as changing out the MicroSD card. Personally, I’m developing a SIGINT project and hidden Tor server with the same hardware – minus the $6 MicroSD card.
- Loss: If I lose the Pi or it’s confiscated, it’s not the end of the world. However, if I loose my personal laptop, it would be a pretty big problem.
A lot of arguments could be made for hosting this service within a virtual machine inside of your laptop, though you lose a lot of flexibility and deniability if your hardware was seized because you cannot separate the hard drive from the device as quickly – or will look suspect for trying. There is also the chance (high) that an adversary gains reverse shell to your laptop while operating under normal conditions, and can then record your other activity.
Live Boot USB Option
Instead of running through a VM, I would boot Pop!_OS live from a USB (with data persistence) using a 64 GB PWY 3.1 USB Flash Drive if only for this type of work, or one of the larger sizes if you’re going to run a few more applications. Since you are booting from a live USB, this option has many of the advantages of the Raspberry Pi, and will not leave a trace of your activity on the OS writing to your computer’s internal drive.
Setting Up Your Device
As I am attempting to create a universal build and get the ‘less than tech-savvy’ up and running while on a budget, so I will be using a Raspberry Pi, but you can follow along with an older computer or laptop if you like. As long as you are using a Debian or Ubuntu based OS, these commands will work.
1). Install your Linux Distro of choice:
For this guide, I’m running Raspian OS for the sake of universality. For this, you can flash an .iso or .img through your medium of choice, or you can use the Raspberry Pi Imager (easiest) shown in this 45s video.
In practice, I will likely run System76’s Raspberry Pi distro, because full disk encryption is important to me. Again, all commands and scripts shown in this tutorial will work for both, as well as other Rapberry Pi distros.
2). Connect to WiFi (Optional):
If going this route, enter your WiFi credentials. If going with an Ethernet cable instead then skip this step. Which ever you choose, remember that in practice, you may not choose to connect to the Tor network from your own home. You may choose to use a public library, coffee shop or a connection from a neighboring office at work.
3). Activate SSH
I’m using this option so that I do not have to come up with a spare screen or keyboard. ssh stands for “Secure Shell” and it is a protocol used to securely connect to a remote server/system. ssh is secure in the sense that it transfers the data in encrypted form between the host and the client.
- Start > Preferences > Raspberry Pi Configuration > Interfaces
- Next to SSH, click enable. Click OK.
4). Boot up your Pi and SSH In:
With the above steps complete, it’s time to insert the MicroSD card in your device, power up and connect to your Pi. The syntax for this is as follows:
ssh [user_name]@[IP]
ex. “$ ssh [email protected]” Accept the signature, then type in the password set during the installation when prompted. Now you should be looking at your Pi terminal.
5). Updating your device & installing Tor:
Update the repositories on your Pi (you’ll be doing this a lot) with the following:
sudo apt update
Install Tor:
sudo apt install tor -y
6). Configuring Tor
Now we have to play with the Tor config file to make sure that everything is functioning properly. You can open this file with the below command:
sudo nano /etc/tor/torrc
Scroll down and uncomment “HiddenServiceDIR” and “HiddenServicePort” which are highlighted in the image below, by deleting the # sign at the beginning of the line. This will make the whole line white. When complete, hit Ctrl + S to save the nano file, and Ctrl + X to exit.

Before editing this file, Tor was running under the previous configuration. Since we just edited this, we’ll need to restart Tor services to make sure that the changes are implemented.
sudo service tor stop
sudo service tor start
Now, verify that the Tor service is running with the following:
sudo service tor status
This should return the following. Take special note of the green “active (exited)” wording, indicating that you have successfully connected to the Tor network.

To leave this menu, hit Ctrl + C. Next, we’ll want to grab your Tor address and save it in a .txt file for easy distribution. As you can see, this will create a file titled “mytor_url.txt” but if you would like to change this, just do so ahead of the .txt.
sudo cat /var/lib/tor/hidden_service/hostname > mytor_url.txt
7.). Install your web server software:
In this tutorial, I will be using Nginx, pronounced “Engine – X”:
sudo apt install nginx -y
Start Nginx:
sudo service nginx start
If you want to check the status, it’s the same as the above Tor line (or any Linux Service): $ sudo server nginx start. As with Tor, if you see ‘active (running) in green, then you’re online. With that, your website is now online through port 80. Use Tor browser to check it out.

With that, your website is now online through port 80. You can now use Tor Browser with the link from the saved file (ex. mytor_url.txt) to visit your site!

If you saw this message (the default Nginx page), then congrats! Your hidden site is now online….well, online on the dark web!
8). Modify your Nginx Config file
In the next few steps, we’re going to modify the config files to make it safer for the host, then we’ll quickly go over ways to modify the site content itself.
sudo nano /etc/nginx/nginx.conf
Under “# Basic Settings”, uncomment “server_tokens off;” and “server_name_in_redirect off;” then under “server_tokens off;” add a line “port_in_redirect off;” When complete, your file should look like the image below.

Hit Ctrl + S to save the nano file then Ctrl + X to exit. As with the Tor service, nginx was running with the default configurations, so we’ll need to restart the service to make all of our changes active.
sudo service nginx restart
To Recap: You just updated your Pi, installed and configured both your Tor connections and your web server software, learned how to start/stop/restart services and modify configurations files for safety & privacy.
Modifying Your Site’s Content
Now that you are online, let’s change the content on your website. To do this, we will need to navigate to the directory and file where nginx stores this information, then locate the .html file. This can be done with the following command:
cd /var/www/html
Now type in ‘ls’ and it should be the only file that you see in there titled “index.nginx-debian.html”. Let’s leave this alone for a second while we build a quick & easy html file, using LibreOffice, but leave this terminal open.
To build a simple html file, click on the start button (looks like a raspberry) in the upper left then navigate to Office > LibreOffice Writer. Once it’s booted up, go to File > New > HTML Document. Type out a quick message then save it in Documents. I saved mine as sample.html.
Now open a new terminal and navigate to your file with the following:
cd Documents
Once here, you can type ‘ls’ to see all of the files in the directory, but we want to display the html coding. This can be done with the following:
cat sample.html
What we want here is everything after <body all the way down to </body> as shown highlighted in the below image.

Highlight this, right click and copy. Next, go back to the terminal you kept open with the index.nginx-debian.html file shown. Type in “sudo nano I” then press the Tab key and it should auto-complete to spell out the file. Hit Enter.
In this file we’re going to delete everything (and including) <head> to </body> because we’re going to be replacing this with the info in our clipboard. Once deleted, right click + paste. Hit Ctrl + S to save, then Ctrl + X to Exit.
Now, restart the nginx service as shown above and navigate back to your site. Here is an example I created for this project. It might not mean anything to someone who obtains the hidden address, but it could mean everything to those it was intended for.

In practice, you are more likely to produce content that is less specific and is closer the to numbers station, with number sequences typed for decoding at a later time.
Conclusion
It is up to you to research best practices for communications windows (or site up-time in our case), whether or not to encrypt the information further with one-time pads (I would) and how many people handle the information between the broadcast station and its final destination. In another post, I make the argument that the Briar Secure Messenger App combined with a GrapheneOS phone is a great way to handle and pass updates by simply passing within range of a friendly WiFi router or Bluetooth device.
I will continue to research methods, techniques and configuration file changes to make this method safer, which I will update here and on social media. In the mean time, I hope that you took something useful away from this post and that you will feel free to reach out through the Contact form here or through your social media of choice. If you have any questions, ideas or want to bounce a specific use-case off the wall, I’d love to hear from you.