Installing Secure Tor Onion Hidden Services on Ubuntu (CLI and Webmin Guide)

Complete Guide: Installing Secure Tor Onion Hidden Services on Ubuntu Server or Laptop

Part 1 will cover how to manually install and configure multiple Tor Onion services on the latest Ubuntu versions using CLI, including setting up NGINX, PHP, and MySQL/MariaDB, configuring multiple hidden services, securely uploading site files, creating databases, hardening the server, and managing the firewall and open ports.

Part 2 will demonstrate how to do the same tasks using the Webmin panel, including installation, access setup (both via LAN and Tor Onion address), NGINX/PHP/MariaDB integration, virtual host management for multiple onion sites, file uploads, database administration, security tweaks like port changes, and mapping the Webmin panel to a .onion address.

Installing Tor Onion Hidden Services on Ubuntu (CLI and Webmin Guide)

Tor “hidden services” (onion services) let you host websites with .onion addresses for anonymous access. We’ll cover Part 1: manual CLI setup and Part 2: using the Webmin web panel on Ubuntu (e.g. 22.04 LTS). The stack includes Nginx, PHP, and MySQL/MariaDB for both static and dynamic (WordPress, PHP) sites. We use all commands via terminal (SSH). Finally, we’ll harden the server (firewall, fail2ban, disable root login, etc.) and even map Webmin to its own onion address.

Tor onion hidden services route traffic internally, so the webserver only listens on localhost. This keeps your server IP hidden and restricts access to Tor only. Onion addresses are 56-character .onion URLs generated by Tor. To set one up, first ensure Ubuntu is updated and a non-root sudo user exists. For example, create a sudo user (replace alice with your name):

sudo adduser alice             # create new user
sudo usermod -aG sudo alice    # add user to sudo group

This follows Ubuntu’s recommended initial setup steps. You should also disable root SSH logins in /etc/ssh/sshd_config (set PermitRootLogin no and PasswordAuthentication no), then restart SSH. This forces all admin work through your sudo user.

Part 1: CLI Installation and Configuration

1. Update System and Basic Security

Update packages and install essential tools:

sudo apt update && sudo apt upgrade -y
sudo apt install curl gnupg2 ufw fail2ban -y

Set up a basic firewall (UFW) to allow SSH and later Nginx or other services. For example, allow OpenSSH and enable UFW:

sudo ufw allow OpenSSH
sudo ufw enable

Check status to confirm SSH is allowed. By default UFW now denies other incoming connections. Later, you may allow web ports as needed.

Install fail2ban to block brute-force attacks on SSH or web forms:

sudo apt install fail2ban -y
sudo systemctl enable --now fail2ban

Fail2ban will ban IPs that fail login too many times, adding extra protection.

2. Install Tor and Configure Onion Service

Add the official Tor repository (recommended for up-to-date Tor). For Ubuntu, you can use the Tor Project’s apt repo. Example (for Ubuntu 22.04 “jammy”):

sudo apt install apt-transport-https -y
curl https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | \
  gpg --dearmor | sudo tee /usr/share/keyrings/tor-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.org/torproject.org $(lsb_release -sc) main" | \
  sudo tee /etc/apt/sources.list.d/tor.list
sudo apt update
sudo apt install tor deb.torproject.org-keyring -y

Alternatively on newer Ubuntu, simply:

sudo apt install tor -y

but using the Tor repo ensures the latest stable version. After installation, Tor will run as user debian-tor.

Edit Tor’s config in /etc/tor/torrc. At the end of this file, add one or more HiddenService stanzas for each onion site. For example, for a website listening on local port 8080:

HiddenServiceDir /var/lib/tor/my_onion_site/
HiddenServicePort 80 127.0.0.1:8080

This tells Tor to create /var/lib/tor/my_onion_site/ and forward port 80 of the onion to localhost:8080. Each HiddenServiceDir (with accompanying HiddenServicePort) produces a separate .onion address. You can add multiple services by repeating HiddenServiceDir lines. For example:

HiddenServiceDir /var/lib/tor/site1/
HiddenServicePort 80 127.0.0.1:8080

HiddenServiceDir /var/lib/tor/site2/
HiddenServicePort 80 127.0.0.1:8081

This creates two onions pointing to different ports. Make sure to mkdir /var/lib/tor/site1 and chmod 700 it if needed. After saving torrc, restart Tor:

sudo systemctl restart tor

Tor will generate a hostname file in each HiddenServiceDir containing your new .onion address. For example:

sudo cat /var/lib/tor/my_onion_site/hostname

Save these addresses – they are your site URLs.

3. Install Nginx, PHP, and MySQL/MariaDB (LEMP stack)

Next install the web and database stack. We’ll use Nginx, PHP-FPM, and MariaDB (MySQL-compatible). Update apt and run:

sudo apt update
sudo apt install nginx -y       # Install Nginx web server:contentReference[oaicite:11]{index=11}

By default Nginx will listen on port 80. We’ll later configure it to only listen on localhost for anonymity.

Install the database server (MariaDB is a drop-in replacement for MySQL):

sudo apt install mariadb-server mariadb-client -y   # or use mysql-server:contentReference[oaicite:12]{index=12} 

Secure the database installation by running the built-in script:

sudo mysql_secure_installation

Answer prompts (e.g. set a root password, remove anonymous users, disallow remote root, remove test DB, etc.). This locks down MySQL/MariaDB as recommended.

Install PHP and related modules. For example (Ubuntu 22.04 has PHP 8.1):

sudo apt install php8.1-fpm php8.1-mysql php8.1-cli php8.1-mbstring php8.1-zip -y

This installs php-fpm and the MySQL extension. The PHP-FPM service (php8.1-fpm) should start automatically.

Test Nginx: open http://your_server_ip/ in a browser (clearnet) to see the Nginx welcome page. If using UFW (as above), allow HTTP:

sudo ufw allow 'Nginx Full'

or just port 80. Verify with ufw status.

4. Configure Nginx Virtual Hosts for Onion Sites

For each onion address (HiddenService), configure an Nginx server block. For example, for the site above listening on port 8080, create a new config:

sudo mkdir -p /var/www/my_onion_site
echo "<html><body><h1>It works!</h1></body></html>" | sudo tee /var/www/my_onion_site/index.html
sudo chown -R www-data:www-data /var/www/my_onion_site
sudo chmod -R 755 /var/www/my_onion_site

Then create /etc/nginx/sites-available/my_onion_site:

server {
    listen 127.0.0.1:8080;
    server_name YOUR_ONION_ADDRESS.onion;

    root /var/www/my_onion_site;
    index index.php index.html index.htm;
    location / {
        # Only allow Tor (localhost) to access the site
        allow 127.0.0.1; 
        deny all;
        try_files $uri $uri/ /index.php?$args;
    }
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }
    # (Disable any server tokens for privacy)
    server_tokens off;
}

Replace YOUR_ONION_ADDRESS.onion with the address from Tor’s hostname file. Note that Nginx is set to listen 127.0.0.1:8080, matching the Tor HiddenServicePort. This ensures the site is only accessible via Tor. The allow 127.0.0.1/deny all enforces it (only Tor’s requests from localhost will reach it). Similar to examples in guides, we listen on localhost and set server_name to the onion.

Enable the site and restart Nginx:

sudo ln -s /etc/nginx/sites-available/my_onion_site /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

Repeat for additional onion sites (different ports and directories, each with its own HiddenServiceDir in Tor).

5. Upload Site Files and Configure Databases

Upload your website files (HTML/PHP) into /var/www/your_site/. You can use scp or rsync from your local machine, or use Nginx’s text editor. For example:

scp -r ~/mywebsite_files/* alice@server_ip:/var/www/my_onion_site/

Ensure permissions: sudo chown -R www-data:www-data /var/www/my_onion_site.

For dynamic sites (WordPress, PHP apps), create a MySQL database and user via the terminal:

sudo mysql -u root -p   # enter MariaDB root password

Then inside the MySQL shell:

CREATE DATABASE dbname CHARACTER SET utf8mb4;
CREATE USER 'dbuser'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON dbname.* TO 'dbuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Use dbname, dbuser, and a strong password as needed. WordPress and other scripts can then use these credentials to access the database.

6. Final Security Hardening

Now that services are running, tighten security:

  • Firewall: Verify UFW only allows needed ports. For onion-only sites, external HTTP (80) need not be open. Make sure ufw allow ssh is enabled. You may also allow SSH on a non-standard port for obscurity (e.g. change SSH port in /etc/ssh/sshd_config and sudo ufw allow <new_port>).
  • Disable Unused Services: Remove or disable any services you don’t need.
  • Server Updates: Enable automatic security updates, or regularly run sudo apt update && sudo apt upgrade.
  • Intrusion Prevention: We installed fail2ban to ban repeated SSH or web login failures.
  • SSH Keys: Use SSH keys (disable password login) for your user – DO’s initial setup guide shows how.
  • Hide Version Info: We disabled server_tokens in Nginx. You can similarly hide PHP and database version details.
  • Port Knocking / Security through Obscurity: Optionally, use non-default ports (e.g. SSH on 2222). Remember to reflect these in UFW (e.g. ufw allow 2222/tcp).
  • Tor-specific: Only listening on localhost (127.0.0.1) prevents any IP leaks. Tor’s official docs recommend using Unix sockets or localhost binding. Follow their advice on not revealing server info.

At this point your onion sites should be accessible via the Tor Browser at http://your_onion_address.onion. They will be isolated from the clearnet. SSH remains your secure access to the server.

Part 2: Installation and Setup with Webmin

Webmin provides a browser interface to manage your server. We’ll install Webmin and then repeat the above tasks through its UI.

1. Install Webmin on Ubuntu

Add the Webmin repository and install Webmin (Ubuntu 22.04 example):

curl -fsSL https://download.webmin.com/jcameron-key.asc | sudo gpg --dearmor -o /usr/share/keyrings/webmin.gpg
echo "deb [signed-by=/usr/share/keyrings/webmin.gpg] http://download.webmin.com/download/repository sarge contrib" | sudo tee /etc/apt/sources.list.d/webmin.list
sudo apt update
sudo apt install webmin -y    # install Webmin package:contentReference[oaicite:23]{index=23}

By default, Webmin listens on port 10000 and uses HTTPS. After installation it will start automatically. Allow its port through the firewall:

sudo ufw allow 10000/tcp     # allow Webmin GUI:contentReference[oaicite:24]{index=24}

You can now access Webmin in a web browser at https://SERVER_IP:10000 (accept the self-signed certificate warning). Log in as your sudo user (or root if enabled). You may wish to set a strong password or SSH key auth.

To access Webmin via Tor, add another hidden service for port 10000. In /etc/tor/torrc, append:

HiddenServiceDir /var/lib/tor/webmin_service/
HiddenServicePort 10000 127.0.0.1:10000

Restart Tor. Tor will create /var/lib/tor/webmin_service/hostname containing a new .onion address for Webmin. You can connect to this via Tor Browser to manage your server anonymously.

2. Using Webmin to Install Nginx, PHP, and MariaDB

Webmin’s “System” ➔ “Software Packages” module lets you install packages without CLI. However, many prefer the Terminal module in Webmin for commands. You can also do under “System” ➔ “Software Package Updates”. Install Nginx, PHP, and MariaDB through Webmin’s APT package manager: search for nginx, php8.1-fpm, php-mysql, and mariadb-server and install them. This is equivalent to the CLI commands above (e.g. sudo apt install nginx, etc.).

Alternatively, if you already did the CLI install above, simply configure them via Webmin. Ensure Nginx and PHP-FPM are running (check “System” ➔ “Bootup and Shutdown” to confirm services).

3. Adding Onion Sites in Webmin (Nginx Virtual Hosts)

In Webmin’s sidebar under “Servers” ➔ “Nginx Webserver”, you can manage virtual hosts. Create a new Virtual Server (or “Server Block”) for each onion site. Set:

  • Listen: 127.0.0.1:<port> (e.g. 8080).
  • Server Name: use the .onion hostname.
  • Document Root: e.g. /var/www/my_onion_site.
  • Other settings: Configure index files and enable PHP processing by selecting fastcgi_php in Webmin. Under “Edit Directives”, ensure you have location blocks similar to the CLI config above (allow 127.0.0.1; deny all;).

Webmin can generate the server { } block for you. After saving, Webmin will create the config file and reload Nginx. This replicates the manual Nginx setup.

4. Uploading Files and Managing Databases in Webmin

Webmin has a “File Manager” (under Tools) to upload or edit site files directly. Navigate to the document root (e.g. /var/www/my_onion_site) and upload your site files (HTML, PHP, etc.). You can also use SFTP via your SSH user if preferred.

For databases, use “Servers” ➔ “MySQL Database Server”. Click “Create new database”, and “Create new user”, mirroring the CLI SQL steps. You can also import SQL dumps here. Webmin makes it GUI-easy to configure MySQL/MariaDB without touching the command line.

5. Security and Port Customization

You can tweak ports and security in Webmin as well. In “Networking” ➔ “Port Configuration”, you could change SSH’s port (if installed) for obscurity (remember to update UFW). For Webmin itself, you could edit “Webmin Configuration” ➔ “Ports and Addresses” to change 10000 to a custom port.

To allow Webmin over Tor only, you could also restrict Webmin’s firewall rule to Tor’s user (127.0.0.1). For example, UFW can be set to allow from 127.0.0.1 to any port 10000 instead of open SSH. This ensures Webmin isn’t reachable over the internet directly – only via Tor. The Tor forum suggests firewall rules like ufw allow from 127.0.0.1 to any port 10000 to lock services to local only.

Finally, ensure Webmin itself is secured (strong password, up-to-date Webmin version). You can also install the Fail2Ban Webmin module to manage bans from the UI.

Summary

By following these steps, you will have a production-ready Ubuntu server (or VM) hosting one or more .onion websites via Nginx, PHP, and MySQL/MariaDB, all running on localhost and only exposed through Tor. Part 1 covered manual CLI setup (installing packages, editing configs, using mysql_secure_installation, UFW, fail2ban, etc.), and Part 2 showed how to accomplish the same tasks through the Webmin web interface. Throughout, we emphasize security hardening: new sudo user, disable root SSH, enable UFW (only SSH port open by default), install fail2ban, and bind all services to 127.0.0.1 so they’re only reachable via Tor. Mapping Webmin to its own onion address lets you manage the server privately as well.

Your server is now set up for static and dynamic content (WordPress, PHP apps, etc.) on Tor. Always keep software updated and monitor logs. For more details on hidden services and best practices, see the Tor Project’s documentation.

Sources: Official Tor documentation for hidden services; DigitalOcean tutorials for LEMP and Webmin installation; community guides and gists on Tor and Nginx. These show the exact commands and configurations used above.

Author :

0 thoughts on “Installing Secure Tor Onion Hidden Services on Ubuntu (CLI and Webmin Guide)

Leave a Reply

Recent Posts

program9 social network
molly9 SEO agency
server5 web hosting
molly9 free blogs
blog5 free blogs
seoworks.click seo blog
free web hosting
web analytics
seo reports tool
hetzner cloud