Skip to Content

How to Set Up a Secure Reverse Proxy in Apache2 Virtual Hosts

When running multiple web applications or microservices, using Apache HTTP Server as a reverse proxy is a common approach to route traffic to backend applications (like a Node.js app, Python API, or Docker container). Additionally, securing your web server with proper HTTP security headers is essential to protect users and harden your infrastructure. 

In this blog, you’ll learn:

->  How to configure a reverse proxy in an Apache Virtual Host

-> How to add modern HTTP security headers in your Virtual Host

-> Example configurations you can copy and adapt immediately



Prerequisites

Before you start:

  • Apache installed (sudo apt install apache2​ on Ubuntu)
  • mod_proxy​ and mod_headers​ enabled:

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod headers
sudo systemctl restart apache2 

How Reverse Proxy Works in Apache 

A reverse proxy forwards client requests to a backend server.
For example: https://yourdomain.com​ ➜ Apache ➜ forwards to http://localhost:3000

Example Virtual Host with Proxy 

Let’s proxy traffic from https://example.com​ to an internal Node.js app running on port 3000​.

/etc/apache2/sites-available/example.conf:

    
    ServerName example.com
    ServerAlias www.example.com

    # Redirect HTTP to HTTPS
    Redirect permanent / https://example.com/



    ServerName example.com
    ServerAlias www.example.com

    SSLEngine on
    SSLCertificateFile /etc/ssl/certs/example.com.crt
    SSLCertificateKeyFile /etc/ssl/private/example.com.key

    # Proxy settings
    ProxyPreserveHost On
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/

    # Security headers
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-XSS-Protection "1; mode=block"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Content-Security-Policy "default-src 'self';"
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

    ErrorLog ${APACHE_LOG_DIR}/example_error.log
    CustomLog ${APACHE_LOG_DIR}/example_access.log combined


        

What this does:
  • Redirects all HTTP requests to HTTPS.
  • Proxies all HTTPS requests to your app on localhost:3000​.
  • Adds strong HTTP security headers.

Common HTTP Security Headers

Here’s why you need these headers:

  • X-Frame-Options: Prevents clickjacking.
  • X-Content-Type-Options: Blocks MIME type sniffing.
  • X-XSS-Protection: Enables XSS filter in older browsers.
  • Referrer-Policy: Controls what referrer info is sent.
  • Content-Security-Policy: Mitigates XSS by restricting content sources.
  • Strict-Transport-Security (HSTS): Enforces HTTPS connections only.

Enable the Site and Reload Apache

sudo a2ensite example.conf

sudo systemctl reload apache2

  • Always use HTTPS — get a free cert via Let’s Encrypt with Certbot.

  • Use a Content-Security-Policy tailored to your frontend assets.

  • Regularly audit your proxy config to avoid open proxy vulnerabilities.


Hope you find it helpful!!!

Automating Jobs using AWS Lambda: Real Use Cases & Python Examples