Complete Guide to Using Nginx as a Reverse Proxy for Apache Servers

You are currently viewing Complete Guide to Using Nginx as a Reverse Proxy for Apache Servers

Complete Guide to Using Nginx as a Reverse Proxy for Apache Servers

Image by: panumas nikhomkhai

Why choose a hybrid Nginx and Apache architecture?

Did you know websites using a hybrid server architecture can handle up to 2.5x more concurrent users while reducing page load times by 40%? This performance boost is why tech giants like Netflix and WordPress.com combine Nginx’s lightning-fast static content delivery with Apache’s robust dynamic processing. This hybrid approach leverages Nginx’s event-driven architecture to serve static assets (images, CSS, JavaScript) at 25,000 requests per second, while Apache’s .htaccess flexibility and mod_rewrite capabilities handle PHP and other dynamic content. The result? A best-of-both-worlds solution that maximizes throughput while minimizing resource consumption.

Feature Nginx Apache
Static content throughput 2.5x higher Baseline
Dynamic content flexibility Limited Excellent (mod_rewrite, .htaccess)
Memory usage per connection ~2.5MB ~8-12MB
SSL/TLS termination efficiency Optimal Higher overhead
Concurrent connection handling Event-driven Process/thread-based

When to implement this architecture

Consider this setup when:

  • Your site serves high volumes of static assets (e-commerce product images, media files)
  • You require Apache-specific modules like mod_security or mod_php
  • Server memory is constrained (Nginx uses 60% less RAM for static files)
  • You need advanced load balancing with zero downtime deployments

Setting up the environment: prerequisites and initial setup

Before configuring, ensure you have:

  1. Two Ubuntu 22.04 servers (or similar Linux distribution)
  2. Sudo privileges on both machines
  3. Domain name with DNS pointing to your Nginx server
  4. Firewall access (ports 80, 443, 8080)

Installation commands:

On Nginx server:

sudo apt update && sudo apt install nginx

On Apache server:

sudo apt install apache2 libapache2-mod-php

Configure firewall rules using UFW:

  • Allow HTTP/HTTPS on Nginx: sudo ufw allow 'Nginx Full'
  • Restrict Apache to internal network: sudo ufw allow from 10.0.0.0/24 to any port 8080

For PHP processing, install required modules on Apache: follow our PHP optimization guide to configure opcache and script timeouts.

Configuring Nginx as the front-end reverse proxy

First, implement SSL termination at Nginx:

  1. Obtain certificates via Certbot: sudo snap install --classic certbot && sudo certbot certonly --nginx
  2. Edit /etc/nginx/sites-available/yourdomain.conf:

server {
  listen 443 ssl;
  ssl_certificate /etc/letsencrypt/live/yourdomain/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/yourdomain/privkey.pem;

  # Static asset handling
  location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 30d;
    add_header Cache-Control “public, no-transform”;
    root /var/www/static;
  }

  # Proxy dynamic requests
  location / {
    proxy_pass http://apache_backend;
  }
}

Enable HTTP/2 for performance gains: add listen 443 ssl http2; in server block. Set strong SSL protocols: ssl_protocols TLSv1.2 TLSv1.3; and modern ciphers following Mozilla’s TLS guidelines.

Connecting Nginx to Apache for dynamic content

Modify Apache’s configuration to accept proxied requests:

  1. Edit /etc/apache2/ports.conf: Change Listen 80 to Listen 8080
  2. Update virtual hosts: <VirtualHost *:8080>
  3. Enable required modules: sudo a2enmod remoteip rewrite

In Nginx’s proxy configuration, add header forwarding:

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;

On Apache, configure /etc/apache2/conf-available/remoteip.conf:

RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 10.0.0.0/24 # Your internal network

This preserves client IP addresses in Apache logs. Test with curl -I https://yourdomain.com and verify headers appear correctly.

Load balancing with Nginx

For high-traffic sites, distribute requests across multiple Apache servers:

upstream apache_backend {
  least_conn;
  server 10.0.0.101:8080 max_fails=3 fail_timeout=30s;
  server 10.0.0.102:8080 max_fails=3 fail_timeout=30s;
  keepalive 32;
}

Key parameters:

  • least_conn: Distributes traffic to the server with fewest active connections
  • max_fails: Mark server unavailable after 3 failed health checks
  • keepalive: Maintains 32 persistent connections to backends

Configure health checks:

location /nginx-health {
  access_log off;
  return 200 “healthy\n”;
}

For session persistence, use ip_hash directive when applications require sticky sessions. Consider implementing our advanced load balancing strategies for zero-downtime deployments.

Security hardening for production

Nginx hardening measures

  • Disable server tokens: server_tokens off;
  • Implement security headers:

    add_header X-Frame-Options “SAMEORIGIN”;
    add_header X-Content-Type-Options “nosniff”;
    add_header Content-Security-Policy “default-src ‘self'”;

  • Limit request methods: if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 405; }

Apache hardening techniques

  1. Disable TRACE method: TraceEnable off
  2. Reduce timeout to 45 seconds: Timeout 45
  3. Install mod_security: sudo apt install libapache2-mod-security2

Set resource limits in php.ini:

max_execution_time = 30
memory_limit = 128M
post_max_size = 32M

Enable OWASP Core Rule Set for mod_security following official documentation. Monitor for false positives during initial rollout.

Testing and monitoring the hybrid setup

Validate configuration with:

  • Nginx syntax check: sudo nginx -t
  • Apache config test: sudo apachectl configtest

Performance benchmark using wrk:

wrk -t12 -c400 -d30s https://yourdomain.com/static/image.jpg
wrk -t4 -c100 -d30s https://yourdomain.com/dynamic-script.php

Monitor key metrics:

Metric Nginx target Apache target Tool
CPU utilization <60% <75% htop
Memory usage <250MB <500MB per process free -m
Active connections <80% worker limit <MaxRequestWorkers nginx_status
Request latency <100ms static <300ms dynamic New Relic

Set up log aggregation with ELK stack or Grafana Loki to track 5xx errors and traffic patterns. Configure alerts for connection queue overflows using Prometheus.

Frequently asked questions

Does this architecture introduce single point of failure?

No, you can implement high availability by deploying multiple Nginx instances behind a load balancer. Use keepalived for floating IP failover or cloud load balancers like AWS ALB. Apache backends should be stateless to allow horizontal scaling.

How do I handle WebSocket connections in this setup?

Add these directives to your Nginx location block: proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; Apache requires mod_proxy_wstunnel enabled. Route WebSocket traffic to dedicated upstream groups.

Can I use PHP-FPM with this architecture instead of Apache?

Absolutely. Replace Apache with PHP-FPM pools for dynamic processing. Configure Nginx with fastcgi_pass instead of proxy_pass. This often yields better performance but loses Apache’s .htaccess flexibility. Benchmark both approaches for your workload.

How do I debug 502 Bad Gateway errors?

First check: 1) Apache is running on the backend port, 2) Firewall allows traffic between servers, 3) proxy_pass URL is correct. Examine Nginx error logs (/var/log/nginx/error.log) and Apache access logs. Common causes include exhausted Apache workers or SELinux blocking connections.

Conclusion

Implementing this hybrid architecture delivers tangible performance gains: tests show 68% faster static asset delivery and 40% reduction in server memory consumption compared to standalone Apache setups. By letting Nginx handle SSL termination and static content while leveraging Apache’s rich module ecosystem for dynamic processing, you create a scalable foundation capable of handling traffic spikes without compromising security. Remember to continuously monitor key metrics like connection queue times and backend response latency. Ready to optimize further? Explore our server tuning services for custom performance profiling. Implement this architecture today to achieve enterprise-grade resilience while keeping infrastructure costs manageable.