Back to Blog
Security & DevOps

Architecture Blueprint: Building a Hardened, Zero-Leak Tor Service

4 min read
Infrastructure Team

Introduction: The Threat Model & Architecture Goals

Before writing any code, it is critical to understand why standard web deployment methods fail on the darknet. If a web server like Nginx misconfigures an HTTP header or leaks a stack trace, an adversary can easily find the underlying public IPv4 address of the VPS, completely breaking anonymity.

The Zero-Leak Principle: The backend application must be fundamentally invisible to the public internet. It must bind strictly to local loopback interfaces or closed Unix sockets.

Privilege Isolation: The application process must run under a strictly sandboxed system user account that possesses zero access to the rest of the operating system.


Phase 1: Sandboxing the Operating System Env

To enforce strict boundary lines, a dedicated system account must own the application layer.

Creating the Unprivileged System User

  • Provisioning a non-login system account (onionuser) without a shell or a public home directory to minimize the attack surface if the web app is compromised.
  • Locking directory permissions down to 700 (drwx------) so standard server users cannot traverse the path or read environment secrets.

Local Environment Hardening

  • Restricting execution contexts so that all installation and runtime execution parameters are localized using --prefix configurations or strict working directory variables.

Phase 2: The Application Core (Next.js Setup)

The web application runs completely isolated from the outside network, acting as an internal ghost service.

Building for Production

  • Fetching the repository using explicit, user-proxied directory tags (git -C).
  • Triggering the immutable compiler build (npm run build) strictly within the isolated user context to prevent cross-contamination of node binaries.

Defensive Configurations (The Warrant Canary)

  • Implementing a Warrant Canary component (/app/canary/page.tsx) that leverages structural configuration metadata to periodically verify that the operator has not been subjected to silent legal constraints or subversion.

Local Port Binding

  • Forcing the Next.js production server to listen purely on 127.0.0.1 using a non-standard local port (e.g., 3737), ensuring it ignores external network adapters completely.

Phase 3: Process Management with PM2 Contexts

Standard process managers default to global user spaces. A hardened setup requires isolated daemon memory.

Working Directory Anchoring

  • Spawning the application via PM2 while injecting the system execution paths explicitly (env PATH=...).
  • Forcing the runtime root directory using the --cwd flag so the execution daemon never defaults back to system paths.

Context Impersonation Management

  • Utilizing sudo -u onionuser for all status tracking, log analysis, and state saves (pm2 save), splitting the deployment state completely away from clearnet websites running on the same hardware.

Phase 4: Setting Up the Tor Daemon Pipeline

This layer bridges the global Tor network to your local VPS environment securely.

Upgrading to Modern Cryptographic Consensus

  • Bypassing outdated system repository distributions to pull directly from the official Tor Project archives.
  • Ensuring the daemon uses modern protocols (like Tor 0.4.9.x+) containing valid, hardcoded Directory Authority keys to avoid stuck 30% bootstrap consensus rejections.

Hidden Service Configuration (/etc/tor/torrc)

  • Allocating a dedicated, strictly unprivileged hidden service directory (/var/lib/tor/rochaus_noir/) with absolute 700 permissions.
  • Mapping the incoming hidden service virtual port 80 traffic into a local, high-performance Unix socket interface (/var/run/tor/nextjs.sock) rather than exposing open TCP ports.

Phase 5: Nginx as the Reverse Proxy Bridge

Nginx acts as the gatekeeper, taking traffic out of the Tor Unix socket and feeding it directly to the internal Next.js application layer.

Configuring the Upstream Proxy Pass

Crafting an exclusive Nginx virtual host configuration block that intercepts requests and passes them seamlessly to the localized application loopback interface:

location / {
    proxy_pass http://127.0.0.1:3737;
}

System Socket Permission Bridges

  • Navigating the strict Linux security layer by appending the web server execution user (www-data) directly into the debian-tor system group.
  • Modifying transmission socket access structures (chmod 666 /var/run/tor/nextjs.sock) to allow fluid, bi-directional data pipelines without degrading security boundaries.

Phase 6: Operational Runbook & Maintenance

A reliable toolkit for keeping the service alive securely over time:

  • The "Truth Test" Verification Chain: Checking local port binding viability via network diagnostics (sudo ss -tulpn | grep :3737) and internal header validation (curl -I).
  • The Sequential Restart Rule: Always booting the Tor instance before Nginx so that the physical Unix socket pipeline file exists on the disk before the web server attempts to bind to it.
  • The Shell Optimization Hint: Implementing shorthand environment aliases (like alias opm2="sudo -u onionuser pm2") to simplify day-to-day administration without dropping permissions.