Want a private blog or small business site that nobody can reach unless they use the Tor Browser?
Below is a step-by-step guide that keeps the server lean, secure, and accessible only via an .onion address.
All commands are for Ubuntu/Debian; adjust paths if you’re on another distribution.
Security note: This setup hides your IP but still exposes the WordPress install to the internet (through Tor).
Treat it like any public site: keep software updated, use strong passwords, and monitor logs.
Prepare a Clean Server
- Pick a fresh VPS or a dedicated local machine.
- Remove unneeded packages:
sudo apt update && sudo apt upgrade -y
- Disable unused services (e.g.,
bluetoothdif you don’t need it).
Why? A minimal footprint reduces the attack surface and makes troubleshooting easier.
Install Tor
sudo apt install tor -y
sudo systemctl enable --now tor
Verify it’s running:
systemctl status tor | grep Active
Tor will create its default data directory at /var/lib/tor.
Why? Tor provides the hidden-service layer that masks your real IP.
Create a Hidden Service
Edit the Tor configuration:
sudo nano /etc/tor/torrc
Add (or uncomment) these lines:
HiddenServiceDir /var/lib/tor/wp/
HiddenServicePort 80 127.0.0.1:8080
HiddenServiceDir– where Tor writes the .onion address and private key.HiddenServicePort– forwards traffic from port 80 of the hidden service to localhost 8080 (our web server).
Restart Tor:
sudo systemctl restart tor
Check the generated address:
sudo cat /var/lib/tor/wp/hostname
# e.g., b5u6p7q9r1s3t4u5v6w7x8y9z0a1b2c3d4e5f6g7h.onion
Why? The .onion file contains the public key; anyone with that address can reach your site through Tor.
Secure the hidden service directory permissions:
sudo chown -R debian-tor:debian-tor /var/lib/tor/wp
sudo chmod 700 /var/lib/tor/wp
Install WordPress
Option A: Lightweight LAMP (Nginx + MariaDB)
# Nginx
sudo apt install nginx -y
# MariaDB
sudo apt install mariadb-server php-fpm php-mysql -y
sudo mysql_secure_installation
# PHP extensions for WP
sudo apt install php-curl php-gd php-xml php-zip -y
Create a database:
sudo mysql -u root -p
CREATE DATABASE wp_hidden;
GRANT ALL PRIVILEGES ON wp_hidden.* TO 'wp_user'@'localhost' IDENTIFIED BY 'StrongPass!23';
FLUSH PRIVILEGES;
EXIT;
Download WordPress and configure:
cd /var/www
sudo wget https://wordpress.org/latest.tar.gz
sudo tar -xzf latest.tar.gz
sudo mv wordpress wp_hidden_site
sudo chown -R www-data:www-data wp_hidden_site
# Edit wp-config.php
cd wp_hidden_site
sudo cp wp-config-sample.php wp-config.php
sudo nano wp-config.php
Replace the DB settings with your credentials.
Option B: Docker/WordOps (Optional)
If you prefer containers, use WordOps or a simple Docker Compose file.
The steps are analogous; just map port 8080 inside the container to 127.0.0.1:8080 on the host.
Configure the Web Server to Listen on localhost
Nginx example:
sudo nano /etc/nginx/sites-available/wp_hidden_site
Insert:
server {
listen 127.0.0.1:8080;
server_name _;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header Referrer-Policy "no-referrer";
add_header Permissions-Policy "geolocation=(), camera=(), microphone=()";
root /var/www/wp_hidden_site;
index index.php index.html index.htm;
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock; # adjust PHP version
}
location ~ /\.ht { deny all; }
}
Enable the site and reload Nginx:
sudo ln -s /etc/nginx/sites-available/wp_hidden_site /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Why? Binding to
127.0.0.1ensures that only Tor’s hidden service can reach the web server; no one can hit your IP directly.
Secure WordPress
- Updates:
wp-cli core update,wp-cli plugin update --all,wp-cli theme update --all. - Passwords & 2FA: Use a strong admin password and enable two-factor authentication via the “Two-Factor” plugin.
- File Editing Disabled: Add to
wp-config.php:
define('DISALLOW_FILE_EDIT', true);
- Security Plugins: Install “Wordfence” or “iThemes Security” for additional hardening (just be mindful of extra load).
Test via Tor Browser
- Open the Tor Browser.
- Enter your .onion address (
http://your_onion_address.onion). - If you used a self-signed cert, accept the warning or add the certificate to the browser’s trust store.
- Verify that:
- The page loads over HTTPS (or HTTP if you skipped TLS).
- No other IP is exposed in the request headers.
Tor already encrypts traffic end-to-end between the user and the service.
HTTPS over Tor adds another layer, but is optional. Use it only if you need browser trust indicators or plugin compatibility.
Final Checklist
[ ]Tor running, hidden service configured.[ ]WordPress installed on localhost port 8080.[ ]Web server bound only to 127.0.0.1.[ ]Security hardening applied.[ ]Site reachable only through the .onion address.[ ]Backup WordPress and var/lib/tor/wp regularly.
The latter contains your private onion key – lose it and your address changes.
Now you have a fully functional WordPress site that’s invisible to anyone who isn’t using Tor.
Happy blogging in the shadows!