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
- 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 nginxandsudo systemctl enable nginx. - 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.
- 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.
- 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 usesystemctl edit varnish) and setExecStartto include-a :80. Then reload systemd and restart Varnish:sudo systemctl daemon-reload sudo systemctl restart varnish
On CentOS, edit
/etc/varnish/varnish.paramsand setVARNISH_LISTEN_PORT=80. - 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.
- 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 insidevcl_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.
- Enable caching (optional but recommended). By default, Varnish will cache responses that have a valid
Cache-ControlorExpiresheader. To cache static files aggressively, you can add rules invcl_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.
- Test the configuration. Run
sudo varnishd -C -f /etc/varnish/default.vclto 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). - 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.
- 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
varnishstatto see cache hit rates and backend health. - Implement cache purging (e.g., using
PURGErequests) for content updates. - For sticky sessions (if needed), use Varnish’s
client.iphashing 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
varnishlogorvarnishstat. - Varnish not starting: Run
varnishd -C -f /etc/varnish/default.vclto 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_recvusesreq.backend_hint. - Cache not working: Check response headers with
curl -I. If you seeX-Varnish: 0andAge: 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
- Valheim Server Not Showing in Community List Fixes
- Soundbar vs 2.1 Speaker System: Which Is Better?
- DisplayPort vs HDMI: Which Cable Should You Use?
- Survive Lava for Brainrot Tier List170 points
- MySQL Dump Import: Fix Common Errors
- Mouse Moving on Its Own? Causes & Fixes