Self-Hosting on the Dark Web
Self-Hosting on the Dark Web
By David Álvarez Rosa | Published June 1, 2026
I have officially expanded the reach of this website by deploying it as a Tor hidden service. This means the site is now accessible via a .onion address, which is only resolvable within the Tor network.
The Nature of Onion Services
Unlike traditional hosting, this setup bypasses the standard internet infrastructure. There is no DNS, no Certificate Authority (CA), and no public IP address to expose. Instead, the address is a cryptographic derivative of a public key.
Mathematically, we can think of the address generation as:
The connection is end-to-end encrypted by the Tor protocol. Traffic is routed through a series of volunteer-operated relays, ensuring that no single entity can correlate your identity with your activity. A hidden service simply extends this layer of anonymity to the server side.
The Tor Project is a nonprofit dedicated to promoting human rights and digital liberties through open-source software. Their goal is to provide a web experience free from censorship, surveillance, and tracking.
Because the network relies on community participation, I encourage you to support them or host your own relay to help millions maintain their privacy.
Technical Implementation
1. Configuring the Hidden Service
To get started, I installed Tor and mapped a hidden service to a specific local port. This requires editing the torrc configuration file:
File: /etc/tor/torrc
HiddenServiceDir /var/lib/tor/blog/
HiddenServicePort 80 127.0.0.1:8080
Critical Note on Permissions:
The HiddenServiceDir must be a dedicated path owned by Tor. If you point it at your actual web root, Tor will fail to start. The directory requires specific ownership and permissions:
- User:
debian-tor - Permissions:
chmod 700
Once configured, I restarted the service and retrieved the generated hostname:
$ sudo systemctl restart tor@default
$ sudo cat /var/lib/tor/blog/hostname
dhevt6e4rtgbtr3jh53xrpwmgtilkah6nyjujocsspssrsexc7omxhid.onion
2. Serving the Content
Tor acts as a proxy, forwarding traffic from the onion's port 80 to 127.0.0.1:8080. Therefore, the web server only needs to listen on that local interface.
I added a specific Nginx server block. Note that I omitted TLS, HTTP/2, and QUIC, as Tor handles the encryption via TCP.
server {
listen 127.0.0.1:8080;
server_name dhevt6e4rtgbtr3jh53xrpwmgtilkah6nyjujocsspssrsexc7omxhid.onion;
root /srv/tor.david.alvarezrosa.com;
index index.html;
error_page 404 /404/index.html;
location / {
try_files $uri $uri/ = 404;
}
}
3. Handling Static Site Builds
Since I use a static site generator, absolute links are baked into the HTML during the build process. A standard "clearnet" build would redirect Tor users back to the public domain.
To solve this, I generate a second version of the site using the onion address as the base URL:
$ hugo --minify --baseURL="http://dhevt6e4rtgbtr3jh53xrpwmgtilkah6nyjujocsspssrsexc7omxhid.onion/"
Deployment Workflow:
- Push code to repository.
- GitHub Actions triggers dual build (Clearnet & Tor).
-
rsyncdeploys each build to its respective web root. - Site remains synchronized automatically.
Architecture Overview
Comparison Table: Clearnet vs. Dark Web
| Feature | Clearnet Hosting | Tor Hidden Service |
|---|---|---|
| DNS | Required | Not Used |
| IP Address | Publicly Exposed | Hidden |
| Encryption | SSL/TLS Certificates | Native Tor Encryption |
| Identity | Linked to Domain/IP | Cryptographic Key |
Traffic Flow
Final Thoughts
For those interested in the underlying hardware and OS setup, see my post on First Steps on a New Server. My full configuration is available in my homelab repository, and the deployment logic is housed in the site's own GitHub Actions workflow.
Visit the site over Tor: http://dhevt6e4rtgbtr3jh53xrpwmgtilkah6nyjujocsspssrsexc7omxhid.onion
Related Reading
- Sept 21, 2026: Self-Hosting Behind CGNAT — Navigating libre hardware and basement hosting.
- May 17, 2026: First Steps on a New Server — My personal machine initialization checklist.
- Aug 27, 2026: Optimizing a Spin-Lock — A deep dive into C++ performance.
Subscribe: My mailing list is free, infrequent, and covers a wide array of technical topics.