← Back to Blog

Demystifying the wadhwas.org Infrastructure: A Docker-Powered Nginx Setup

June 28, 2026 6 min read

As a Site Reliability Engineer, I spend my days managing infrastructure at planetary scales. However, applying the same principles of isolation, reliability, and security to my own home server and family projects is just as rewarding. In this post, I'll walk you through the reverse proxy setup that makes all components of the wadhwas.org ecosystem run smoothly.

The Problem: Multiple Services, Single Ingress

The wadhwas.org network hosts several distinct projects: a Nextcloud cloud instance, my portfolio and blog, my wife's portfolio, and our interactive family tree. All of these require secure HTTPS access over standard ports (80 and 443), but they are run using different stacks and runtimes.

To solve this, I designed a containerized infrastructure using Nginx as an ingress controller. Nginx acts as a reverse proxy, terminating SSL, evaluating the host headers, and routing traffic to the correct container or serving static assets.

Network Topology & Container Layout

The architecture centers around a custom Docker bridge network called nginx-network. This isolates our containers from the host network while enabling secure container-to-container communication.

[ Host Ingress (80/443) ]
          │
          ▼
┌──────────────────────────────────────┐
│ Nginx Reverse Proxy Container        │
│ (Ports 80/443 mapped to host)        │
└──────────┬──────────────┬────────────┘
           │              │
           │ proxy_pass   │ direct root serving
           ▼              ▼
┌──────────────────┐    ┌──────────────────────────────────────────────┐
│ Nextcloud App    │    │ Local Directory Volume Mounted               │
│ Container        │    │ (/etc/nginx/conf.d/)                         │
│                  │    ├──────────────────┬──────────────┬────────────┤
└──────────────────┘    │ /tanmay          │ /WFT         │ /anushka   │
                        │ (My Portfolio)   │ (Family Tree)│ (Portfolio)│
                        └──────────────────┴──────────────┴────────────┘

The Nginx proxy container is started within the bridge network so it can reliably talk to other backend services:

docker run -d -p 80:80 -p 443:443 \
  -v $(pwd):/etc/nginx/conf.d \
  --network=nginx-network \
  --name nginx-reverse-proxy --restart always nginx:latest

By mounting the local workspace folder to /etc/nginx/conf.d, Nginx reads our configuration files directly from the host. This mount also lets Nginx serve static assets for the other projects directly from directories in the repository without the overhead of additional container runtimes.

Breaking Down the Nginx Server Blocks

Our nginx.conf is configured with distinct server blocks. Let's look at how the different services are routed.

1. Global HTTP to HTTPS Redirection

For security and SEO integrity, we redirect all incoming HTTP (port 80) traffic to its HTTPS equivalent. Nginx catches all domains in one listener block:

server {
    listen 80;
    server_name www.cloud.wadhwas.org cloud.wadhwas.org
                tanmaywadhwa.com www.tanmaywadhwa.com www.tanmay.wadhwas.org tanmay.wadhwas.org
                anushkajain.wadhwas.org www.anushkajain.wadhwas.org
                familytree.wadhwas.org www.familytree.wadhwas.org;

    location / {
        return 301 https://$host$request_uri;
    }
}

2. Nextcloud Storage Proxy (cloud.wadhwas.org)

Nextcloud runs inside a separate container on the private network. Since we use it for backup and file transfers, we must set a generous client body size to allow large file uploads:

server {
    listen 443 ssl;
    server_name www.cloud.wadhwas.org cloud.wadhwas.org;
    ssl_certificate /etc/nginx/conf.d/certs/cert_nc.pem;
    ssl_certificate_key /etc/nginx/conf.d/certs/privkey_nc.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    client_max_body_size 20G; // Support uploads up to 20GB

    location / {
        proxy_pass http://nextcloud-container;
        proxy_set_header Host $host;
    }
}

3. Serving Static Portfolios & Projects

For the other domains (my portfolio/blog, my wife's portfolio, and the family tree), we do not need backend application servers. Nginx serves these static files directly from our mounted volume paths, optimizing load times and keeping resource consumption to an absolute minimum:

# Serving Tanmay's Site & Blog (tanmay.wadhwas.org / tanmaywadhwa.com)
server {
    listen 443 ssl;
    server_name tanmaywadhwa.com www.tanmaywadhwa.com www.tanmay.wadhwas.org tanmay.wadhwas.org;
    ssl_certificate /etc/nginx/conf.d/certs/cert_tw.pem;
    ssl_certificate_key /etc/nginx/conf.d/certs/privkey_tw.pem;
    ssl_protocols TLSv1.2 TLSv1.3;

    root /etc/nginx/conf.d/tanmay;
    index index.html;
    location / {
        try_files $uri $uri/ =404;
    }
}

# Serving Wadhwa Family Tree (familytree.wadhwas.org)
server {
    listen 443 ssl;
    server_name familytree.wadhwas.org www.familytree.wadhwas.org;
    ssl_certificate /etc/nginx/conf.d/certs/cert_ft.pem;
    ssl_certificate_key /etc/nginx/conf.d/certs/privkey_ft.pem;
    ssl_protocols TLSv1.2 TLSv1.3;

    root /etc/nginx/conf.d/WFT;
    index index.html;
    location / {
        try_files $uri $uri/ =404;
    }
}

SSL Automation and Renewal Pipeline

Enforcing SSL is only half the battle; manual certificate renewal is a major source of operational toil. To solve this, I wrote an automated pipeline using Let's Encrypt's certbot and a script to coordinate the cert update flow.

Since Certbot's standalone mode requires port 80 to verify domain ownership, our script takes the following steps:

  1. Stop the Nginx reverse proxy container to release ports 80 and 443.
  2. Execute certbot renew on the host system to fetch updated certificates.
  3. Copy and rename the renewed certs/keys (renamed to cert_*.pem and privkey_*.pem) into the local project's certs/ directory.
  4. Trigger our Docker refresh script to destroy the old container instance and start a new container with the refreshed keys.
"Automating the certificate cycle mitigates the risk of expired TLS certificates—a common failure mode in both personal labs and corporate production networks."

Conclusion

By combining Docker networks, Nginx virtual host routing, and Let's Encrypt automation, we've created a zero-maintenance ingress stack for wadhwas.org. It's performant, lightweight, and ensures all of our applications remain secure by default.