keepcalculator

06 Numbers and Powers

Varnish & Nginx Cluster Setup Guide

Card No. 06·39637 · Updated · Standard formula, shown below

This guide walks you through setting up a clustered web server architecture using Varnish as a caching reverse proxy in front of multiple Nginx web servers. You’ll configure a load-balanced, highly available setup that distributes traffic across backend nodes, with Varnish caching content to reduce server load and improve response times. By the end, you’ll have a working cluster with health checks and basic failover.

What You’ll Need

  • At least two servers (or VMs) running Linux (Ubuntu/Debian or CentOS/RHEL recommended). One will act as the Varnish load balancer/cache; the others will run Nginx as web backends.
  • Root or sudo access on all servers.
  • Basic familiarity with the command line and editing files (nano or vim).
  • All servers should have network connectivity to each other (private network recommended).
  • Optional: a domain name pointing to the Varnish server’s public IP.

Step-by-Step

  1. Install Nginx on each backend server. On each backend, run:
    sudo apt update && sudo apt install nginx -y   # Debian/Ubuntu
    sudo yum install nginx -y                # RHEL/CentOS

    Ensure Nginx is running: sudo systemctl start nginx and sudo systemctl enable nginx.

  2. Create a test page on each backend. To verify load balancing later, create a simple page that shows the server’s hostname or IP:
    echo "Backend: $(hostname)" | sudo tee /var/www/html/index.html

    Adjust the path if your Nginx document root is different.

  3. Install Varnish on the frontend server. On the server designated as the load balancer:
    sudo apt update && sudo apt install varnish -y   # Debian/Ubuntu
    sudo yum install varnish -y                # RHEL/CentOS

    Varnish will be the entry point for all client requests.

  4. Configure Varnish to listen on port 80. By default, Varnish listens on port 6081. Edit the systemd service file (or the default config) to change the listening port to 80. On Ubuntu, edit /lib/systemd/system/varnish.service (or use systemctl edit varnish) and set ExecStart to include -a :80. Then reload systemd and restart Varnish:
    sudo systemctl daemon-reload
    sudo systemctl restart varnish

    On CentOS, edit /etc/varnish/varnish.params and set VARNISH_LISTEN_PORT=80.

  5. Define your backend servers in Varnish. Edit the Varnish configuration file, typically /etc/varnish/default.vcl. Add a backend block for each Nginx server. For example:
    backend web1 {
        .host = "192.168.1.10";
        .port = "80";
    }
    backend web2 {
        .host = "192.168.1.11";
        .port = "80";
    }

    Replace the IPs with your actual backend addresses.

  6. Set up load balancing and failover. In the same default.vcl, create a director (or use Varnish’s round-robin) to distribute requests. Add this inside vcl_init:
    sub vcl_init {
        new cluster = directors.round_robin();
        cluster.add_backend(web1);
        cluster.add_backend(web2);
    }

    Then in vcl_recv, direct traffic to the director:

    sub vcl_recv {
        set req.backend_hint = cluster.backend();
    }

    This gives basic load balancing and automatic failover if a backend goes down.

  7. Enable caching (optional but recommended). By default, Varnish will cache responses that have a valid Cache-Control or Expires header. To cache static files aggressively, you can add rules in vcl_backend_response:
    sub vcl_backend_response {
        if (bereq.url ~ "\.(css|js|png|jpg|jpeg|gif|ico)$") {
            set beresp.ttl = 1h;
        }
    }

    Adjust TTL as needed. Be careful not to cache HTML pages that change frequently unless you have a purging strategy.

  8. Test the configuration. Run sudo varnishd -C -f /etc/varnish/default.vcl to check for syntax errors. If OK, restart Varnish: sudo systemctl restart varnish. Then from a client, access the Varnish server’s IP. You should see the test page from one of the backends. Refresh multiple times to see the other backend (if round-robin is working).
  9. Configure Nginx to use real IPs (optional). Since Varnish forwards requests, Nginx logs will show Varnish’s IP as the client. To log the real client IP, add to each Nginx server block:
    set_real_ip_from 127.0.0.1;
    real_ip_header X-Forwarded-For;

    Replace 127.0.0.1 with Varnish’s IP if it’s on a different host.

  10. Set up health checks (advanced). Varnish can actively probe backends. Define a probe in each backend block:
    backend web1 {
        .host = "192.168.1.10";
        .port = "80";
        .probe = {
            .url = "/";
            .interval = 5s;
            .timeout = 1s;
            .window = 5;
            .threshold = 3;
        }
    }

    This will mark the backend as down if it fails 3 out of 5 probes.

Common Mistakes

  • Forgetting to change Varnish’s listening port. If you don’t change it from 6081 to 80, clients can’t reach your site on the standard port.
  • Backend IP misconfiguration. Using the wrong IP or port for backends will cause 503 errors.
  • Not restarting Varnish after config changes. Varnish loads config at startup; you must restart the service for changes to take effect.
  • Caching dynamic content too aggressively. If you cache pages that should be personalized, users may see other users’ data. Use cache rules carefully.
  • Ignoring firewall rules. Ensure the firewall allows traffic on port 80 (and 6081 if you test directly).

Tips

  • Use a private network for backend communication to reduce latency and avoid exposing backend IPs.
  • Monitor Varnish statistics with varnishstat to see cache hit rates and backend health.
  • Implement cache purging (e.g., using PURGE requests) for content updates.
  • For sticky sessions (if needed), use Varnish’s client.ip hashing instead of round-robin.
  • Consider using a load balancer like HAProxy in front of Varnish if you need SSL termination or more advanced routing.

Troubleshooting

  • 503 Service Unavailable: This usually means Varnish can’t reach any backend. Check backend IPs, ports, and that Nginx is running. Verify with varnishlog or varnishstat.
  • Varnish not starting: Run varnishd -C -f /etc/varnish/default.vcl to see syntax errors. Common issues: missing semicolons, incorrect director syntax.
  • Clients see only one backend: If round-robin isn’t working, check that the director is correctly defined and that vcl_recv uses req.backend_hint.
  • Cache not working: Check response headers with curl -I. If you see X-Varnish: 0 and Age: 0, caching isn’t happening. Ensure the backend sends cacheable headers.
  • High CPU on Varnish: This could be due to excessive purging or overly complex VCL. Simplify rules and check for infinite loops.

Frequently Asked Questions

Can I use more than two backends?

Yes, simply add more backend blocks and add them to the director.

Does Varnish support SSL/HTTPS?

Varnish itself doesn’t terminate SSL. You need a TLS terminator like Nginx or HAProxy in front of Varnish.

How do I purge cached content?

You can send a PURGE request to Varnish for a specific URL, but you must define an ACL in vcl_recv to allow it.

What happens if a backend goes down?

With the director, Varnish will automatically stop sending requests to the failed backend and use the remaining ones.

Can I use Varnish with WordPress or other CMS?

Yes, but you need to be careful about caching dynamic content. Use plugins or custom VCL to bypass caching for logged-in users.

How do I update Nginx configuration after changes?

Run sudo nginx -t to test, then sudo systemctl reload nginx to apply changes without downtime.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →