Speed Up Web with Varnish Cache on VPS Nginx
Varnish Cache is an HTTP accelerator that stores entire page content in RAM. When a visitor requests a cached page again, Varnish serves it directly from memory without touching PHP or the database at all. This reduces response time from 200–500ms to 1–5ms. In practice, Varnish can handle significantly more traffic than Nginx alone.
Architecture: Nginx (443) → Varnish (80) → Nginx (8080)
# Nginx handles HTTPS on port 443
# Varnish listens on port 80 (or behind Nginx proxy)
# Backend Nginx/Apache on port 8080
# In this tutorial we'll use:
# Client → Nginx:443 (SSL termination) → Varnish:6081 → Nginx:8080 (backend)
Install Varnish
sudo apt update
sudo apt install varnish -y
# Verify installation
varnishd -V
Change Nginx Backend Port
# Change Nginx to listen on port 8080 instead of 80
sudo nano /etc/nginx/sites-available/yourdomain.com
server {
listen 8080; # Change from 80 to 8080
server_name yourdomain.com;
# ... rest of your config
}
sudo nginx -t && sudo systemctl reload nginx
Configure Varnish (VCL)
sudo nano /etc/varnish/default.vcl
vcl 4.0;
backend default {
.host = "127.0.0.1";
.port = "8080";
}
sub vcl_recv {
# Don't cache requests with cookies (logged-in users)
if (req.http.Cookie) {
if (req.http.Cookie !~ "wordpress_logged_in") {
unset req.http.Cookie;
}
}
# Don't cache admin pages
if (req.url ~ "^/wp-admin|^/wp-login.php") {
return(pass);
}
# Don't cache POST requests
if (req.method == "POST") {
return(pass);
}
}
sub vcl_backend_response {
# Cache HTML for 1 hour
if (beresp.http.Content-Type ~ "text/html") {
set beresp.ttl = 1h;
set beresp.grace = 24h;
}
# Don't cache if backend says no-store
if (beresp.http.Cache-Control ~ "no-store|private") {
set beresp.uncacheable = true;
}
}
sub vcl_deliver {
# Add header to show cache hit or miss (for debugging)
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT";
} else {
set resp.http.X-Cache = "MISS";
}
}
Set Varnish to Listen on Port 6081
sudo nano /etc/varnish/varnish.params
VARNISH_VCL_CONF=/etc/varnish/default.vcl
VARNISH_LISTEN_PORT=6081
VARNISH_STORAGE="malloc,256m" # Use 256MB of RAM
VARNISH_TTL=120
sudo systemctl restart varnish
Configure Nginx to Forward to Varnish
sudo nano /etc/nginx/sites-available/yourdomain.com
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate ...;
ssl_certificate_key ...;
location / {
proxy_pass http://127.0.0.1:6081;
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 https;
}
}
sudo nginx -t && sudo systemctl reload nginx
varnishstat -1 and focus on cache_hit and cache_miss. Hit rate should be 80%+ for typical content websites.
Verify Varnish is Working Correctly
# Check service status
sudo systemctl status varnish
# View hit/miss headers
curl -I https://yourdomain.com | grep X-Cache
# First request: X-Cache: MISS
# Second request: X-Cache: HIT
# View statistics
varnishstat -1 | grep cache_hit
# View real-time logs
varnishlog -i ReqURL,ReqHeader,RespHeader
curl -X PURGE http://127.0.0.1:6081/path/to/page. Use this in WordPress plugins or deploy scripts to invalidate cache when updating content.
Common Issues & Troubleshooting
Cache hit rate is very low (below 50%)
This is usually caused by cookies preventing Varnish from caching. Check which cookies are being sent:
varnishlog -g request -q "RespHeader:X-Cache eq MISS" -i ReqHeader
WordPress admin pages are slow (through Varnish)
Your VCL must pass admin pages without caching. Check your VCL rules:
if (req.url ~ "^/wp-admin|^/wp-login.php|^/wp-cron.php") {
return(pass);
}
HTTPS doesn't work through Varnish
Varnish doesn't support SSL directly. You must terminate SSL at Nginx first, then proxy to Varnish over HTTP.
Error "503 Backend fetch failed"
The backend (Nginx on port 8080) is not responding. Check the port:
ss -tlnp | grep 8080
sudo systemctl status nginx
Frequently Asked Questions
How is Varnish different from Nginx FastCGI cache?
Nginx FastCGI cache stores cache on disk, while Varnish stores it in RAM. This makes Varnish 10–100x faster. However, restarting Varnish clears the cache and requires warm-up time.
How much RAM does Varnish need?
It depends on your site size. Typically allocate 25–50% of your VPS RAM for caching. For medium-sized websites, 256–512 MB is usually sufficient. If you run out of RAM, Varnish automatically evicts old pages.
Can I use Varnish with Cloudflare?
Yes. Cloudflare caches at the edge CDN, while Varnish caches at your server. They work well together. Cloudflare misses will reach your origin, and Varnish will serve the response from RAM instead of going to PHP, further reducing origin load.