Skip to content
-
Subscribe to our newsletter & never miss our best posts. Subscribe Now!
Devnix Blog

Tech Trends, Software Engineering & Cloud Insights

Devnix Blog

Tech Trends, Software Engineering & Cloud Insights

  • Home
  • Privacy Policy
  • Home
  • Privacy Policy
Close

Search

Subscribe
Server Security

Step‑by‑Step Guide to Configure Nginx as a Secure Reverse Proxy for Dockerized Apps on a Linux VPS

By Devnix
May 27, 2026 4 Min Read
0


Step‑by‑Step Guide to Configure Nginx as a Secure Reverse Proxy for Dockerized Apps on a Linux VPS

Prerequisites: A fresh Linux VPS (Ubuntu 22.04 LTS recommended), root or sudo access, a domain name pointing to the server’s public IP, basic familiarity with SSH and Docker commands.

1. Provision the VPS and Update the System

Start by logging into your server via SSH. Run a full package update to ensure you’re working with the latest security patches.

ssh root@your.vps.ip

# Update package lists and upgrade existing packages
apt update && apt upgrade -y

# Install essential utilities
apt install -y curl wget gnupg2 ca-certificates lsb-release apt-transport-https

If you need a reliable environment for this tutorial, you can rely on DevNix Cloud VPS to provide a clean Ubuntu installation with predictable performance.

2. Install Docker Engine and Docker Compose

Docker will host the application containers, while Docker Compose simplifies multi‑container orchestration.

# Add Docker’s official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -

# Set up the stable repository
add-apt-repository \
   "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) stable"

# Install Docker Engine
apt update
apt install -y docker-ce docker-ce-cli containerd.io

# Verify Docker installation
docker run --rm hello-world

# Install Docker Compose (v2 plugin)
apt install -y docker-compose-plugin

# Verify Docker Compose
docker compose version

3. Create a Sample Dockerized Application

For demonstration, we’ll use a simple Node.js “Hello World” app. Create a project directory and a Dockerfile.

mkdir -p /opt/webapp
cd /opt/webapp

cat > app.js <<'EOF'
const http = require('http');
const port = 3000;
http.createServer((req, res) => {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello from Docker!\n');
}).listen(port);
EOF

cat > package.json <<'EOF'
{
  "name": "hello-docker",
  "version": "1.0.0",
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "^4.18.2"
  }
}
EOF

cat > Dockerfile <<'EOF'
FROM node:20-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["npm", "start"]
EOF

cat > docker-compose.yml <<'EOF'
version: "3.9"
services:
  web:
    build: .
    restart: unless-stopped
    ports:
      - "3000:3000"
EOF

Build and launch the container:

docker compose up -d --build
# Verify it’s running
docker ps

4. Install Nginx and Harden Its Configuration

Nginx will accept traffic on ports 80/443, forward HTTP requests to the Docker container, and terminate TLS.

apt install -y nginx

# Remove the default site to avoid conflicts
rm /etc/nginx/sites-enabled/default

Create a new server block for your domain:

cat > /etc/nginx/sites-available/example.com <<'EOF'
server {
    listen 80;
    server_name example.com www.example.com;

    # Redirect all HTTP to HTTPS
    return 301 https://$host$request_uri;
}
EOF

ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx

5. Obtain Free TLS Certificates with Let’s Encrypt

We’ll use Certbot’s Nginx plugin, which automatically updates the Nginx configuration.

apt install -y certbot python3-certbot-nginx

# Request a certificate (replace with your domain)
certbot --nginx -d example.com -d www.example.com --agree-tos --redirect --no-eff-email -m admin@example.com

Certbot creates a second server block that listens on port 443 and adds the SSL directives. Verify the configuration:

nginx -t && systemctl reload nginx

6. Wire Nginx to the Docker Container

Modify the SSL server block to proxy traffic to the internal Docker service. Open the file generated by Certbot (usually /etc/nginx/sites-available/example.com) and add a location block.

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # Proxy all requests to the Docker container
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Test the final configuration and reload Nginx:

nginx -t && systemctl reload nginx

7. Automate Certificate Renewal

Let’s Encrypt certificates are valid for 90 days. Certbot installs a systemd timer that runs twice daily. Verify it’s active:

systemctl list-timers | grep certbot

Optionally, perform a dry‑run to confirm renewal works:

certbot renew --dry-run

8. Verify End‑to‑End Functionality

Open a browser and navigate to https://example.com. You should see “Hello from Docker!”. Use curl to confirm the SSL handshake:

curl -I https://example.com
# Expected HTTP/2 200 OK response

If you encounter “502 Bad Gateway”, check that the Docker container is listening on the expected port and that Nginx’s proxy_pass address matches 127.0.0.1:3000.

9. Optional: Enable HTTP/2 and Security Headers

Adding a few headers improves security and performance.

add_header X-Content-Type-Options nosniff;
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "no-referrer-when-downgrade";

Place these directives inside the SSL server block, reload Nginx, and re‑test.

Conclusion

By following this guide you have transformed a plain Docker container into a production‑ready service behind a hardened Nginx reverse proxy with automatic TLS termination. The setup scales easily: add more services to docker-compose.yml, expose them on distinct internal ports, and extend Nginx with additional location blocks. Regularly monitor Docker health and keep your VPS patched to maintain a secure, high‑availability environment.

Tags:

docker deploymentlets encryptLinux VPSnginx reverse proxyssl termination
Author

Devnix

Follow Me
Other Articles
Previous

Step‑by‑Step Guide to Configure Automated Email Reminders for Overdue Invoices in Odoo 16

Next

Step‑by‑Step Guide to Configure Automatic Reordering Rules in Odoo 16 Inventory

No Comment! Be the first one.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • WordPress Image Optimization: Native Settings vs Plugins vs CDN vs Server‑Side Solutions
  • Understanding Database Connection Pooling in Cloud Deployments
  • Odoo User Access Rights Audit Checklist – Secure Your ERP Without Over‑Privileging
  • WordPress Caching Showdown: Built‑In, Plugins, Server‑Side, or CDN?
  • Cloud VPS vs Managed WordPress Hosting vs Static Site Hosting: Which Platform Delivers the Best Uptime and Security for Small‑Business Websites?

Archives

  • June 2026
  • May 2026

Categories

  • Backup Strategies
  • Cloud VPS Performance
  • Docker Compose Deployment
  • Odoo Email Configuration
  • Odoo Inventory
  • Odoo Invoicing
  • Odoo Multi-Company Configuration
  • Odoo Subscriptions
  • Odoo User Management
  • Server Security
  • WordPress Migration
  • WordPress Performance Optimization

About Devnix Blog

A forward-thinking tech publication covering software engineering, cloud infrastructure, and modern digital transformation. Built for developers and tech enthusiasts.

Our Services

  • Cloud VPS Hosting
  • Managed ERP Solutions
  • DevOps Automation
  • Server Security & Optimization

Partners

  • Odoo Stack
  • Odoo Backup
  • Devnix Solutions
Copyright 2026 — Devnix Blog. All rights reserved. Devnix Solutions