Skip to main contentSkip to navigation
[email protected]
Client AreaSupport
Hosting Mammoth
HostingMammothYour Data, Our Responsibility
Home
Solutions
Hosting Services
Store
Pricing
About
Blog
API
Contact

Stay Ahead of the Curve

Get the latest insights on cybersecurity, AI innovations, and enterprise data solutions delivered to your inbox.

Hosting Mammoth
HostingMammothEnterprise Solutions

Enterprise-grade data solutions. Hosting, recovery, cybersecurity, and AI-powered services for businesses worldwide.

[email protected]
Sun - Fri, 9:00am - 5:00pm

Services

  • Cloud Hosting
  • Data Recovery
  • Cybersecurity
  • Legal Support
  • MSP Services
  • Web Development
  • AI Services
  • Free Server Migration

Hosting

  • VPS Hosting (NVMe SSD)
  • VDS Hosting (NVMe)
  • Storage VPS (High SSD)
  • GPU Servers
  • Managed Services
  • Cloud Firewall
  • Load Balancer
  • One-Click Apps
  • n8n Hosting
  • Object Storage
  • FAQ

Company

  • Store
  • Pricing
  • About Us
  • Locations
  • Blog
  • Testimonials
  • Contact
  • Affiliate Program
  • White-Label
  • Terms of Service
  • Privacy Policy
  • Browser Cookies
  • SLA

Support

  • Client Area
  • Submit Ticket
  • Knowledge Base
  • Server Status
  • API Documentation

© 2026 Hosting Mammoth. All rights reserved.

Knowledge Base
Getting StartedAccount ManagementVPS HostingGPU ServersStorage VPSCloud FirewallLoad BalancerServer ManagementBilling & PaymentsSupport & TicketsAffiliate ProgramReseller ProgramMarketplace & Appsn8n HostingManaged ServicesServer MigrationAPI & DevelopersSecurityTroubleshootingGlossaryInstall Guides
  1. Home
  2. /
  3. Support
  4. /
  5. Install Guides
  6. /
  7. How To Install Varnish Ubuntu
GUIDEInstall Guides

How to Install Varnish Cache on Ubuntu 24.04 VPS: Full-Page HTTP Accelerator

20 min read

How to Install Varnish Cache on Ubuntu 24.04 VPS: Full-Page HTTP Accelerator

Varnish Cache turns a modest VPS into a response machine. By serving cached HTML straight from RAM, a single 4 vCPU instance can answer tens of thousands of requests per second while the origin application sleeps. This guide walks you through installing Varnish Cache 7.4 LTS on Ubuntu 24.04, layering it behind an Nginx TLS terminator, writing a production VCL for WordPress, wiring up cache purging, and troubleshooting the failure modes you are most likely to hit.

Need a cache-ready VPS? Our CloudCore Professional plans ship with the RAM headroom Varnish loves -- deploy in 60 seconds and point your domain at it.

Table of Contents

  • What is Varnish Cache?
  • Why Use Varnish Instead of Nginx Microcache?
  • Architecture: Nginx → Varnish → Backend
  • Prerequisites
  • Step 1: Update System Packages
  • Step 2: Add the packagecloud.io Repository
  • Step 3: Install Varnish 7.4 LTS
  • Step 4: Configure the systemd Listen Parameters
  • Step 5: Write a Production VCL
  • Step 6: Put Nginx in Front of Varnish for TLS
  • Step 7: Move the Backend to Port 8080
  • Step 8: Verify the Cache is Working
  • Post-Install: Purging, Monitoring, and Tuning
  • Troubleshooting
  • FAQ
  • Next Steps
  • What is Varnish Cache?

    Varnish Cache is an HTTP reverse proxy designed from the ground up as a full-page cache. It sits in front of your application server (Apache, Nginx, Node.js, PHP-FPM via an intermediate web server), stores complete HTTP responses in memory, and serves subsequent identical requests without ever touching the origin. A Varnish process can push well over 100,000 requests per second on commodity hardware, which is one to two orders of magnitude more than a typical dynamic PHP stack can manage.

    The defining feature of Varnish is VCL (Varnish Configuration Language), a domain-specific language that compiles to C and then to a shared object loaded into the running daemon. VCL is not a list of key/value options -- it is a set of subroutines (vcl_recv, vcl_backend_response, vcl_deliver, and others) that you write to describe exactly how requests and responses flow through the cache. This makes Varnish extraordinarily flexible: you can strip cookies, rewrite URLs, pick backends by geolocation, enforce per-path TTLs, vary responses on custom headers, and invalidate cache entries over HTTP -- all in a few dozen lines of config.

    Typical production use cases include accelerating WordPress, Magento, and Drupal sites where rendered HTML is expensive to generate; fronting REST and GraphQL APIs to absorb read traffic spikes; caching static asset CDNs before they reach object storage; and protecting origin application servers from Slashdot-effect traffic bursts. Large publishers (The Guardian, The New York Times, Wikipedia) have used Varnish for more than a decade as the first tier after their TLS terminator.

    Why Use Varnish Instead of Nginx Microcache?

    Nginx includes a built-in proxy_cache module that can absolutely do full-page caching, and for small WordPress sites it is often enough. Varnish earns its place once traffic or cache complexity grows.

    • Much higher TPS on the same hardware -- Varnish's shared-memory log, epoll-based worker threads, and purpose-built storage engine consistently out-run Nginx microcache in head-to-head benchmarks, particularly under high cache-hit concurrency. Independent tests regularly show 2-5x more requests per second on identical VMs.
    • VCL is a real programming language -- Nginx cache rules are declarative directives. Varnish gives you conditionals, regexes, string manipulation, sub-routines, and a plugin system (VMODs). Complex cache keys, header-based routing, A/B testing logic, and edge-side includes are all straightforward.
    • Native cache invalidation -- Varnish has first-class support for PURGE and BAN HTTP verbs protected by ACLs. Nginx requires the third-party ngx_cache_purge module or shell tricks against the filesystem.
    • Per-object TTL based on backend response -- In VCL you decide caching policy after seeing the backend's headers, which makes it trivial to give /api/products a 30-second TTL while /blog/* gets 1 hour.
    • varnishlog is a superpower -- Every request emits a structured, queryable log stream in shared memory. You can filter by VCL tag, HTTP header, or client IP in real time without touching disk I/O.
    For a WordPress site doing 10 requests per second, Nginx microcache is fine. For a high-traffic content site, an e-commerce catalog, or an API that sees burst traffic, Varnish is the right tool.

    Architecture: Nginx → Varnish → Backend

    Varnish does not handle TLS natively. The recommended production topology is:

    text
    Client
          │  HTTPS :443
          ▼
      ┌─────────┐
      │  Nginx  │   TLS termination, HTTP/2, static files
      └────┬────┘
           │  HTTP :6081
           ▼
      ┌─────────┐
      │ Varnish │   Full-page HTTP cache (RAM)
      └────┬────┘
           │  HTTP :8080
           ▼
      ┌─────────┐
      │ Backend │   Apache / Nginx origin / PHP-FPM
      └─────────┘
    • Nginx on :443 handles TLS, HTTP/2, ACME renewals, and forwards cleartext HTTP to Varnish on the loopback.
    • Varnish on :6081 caches full HTTP responses in memory and, on miss, forwards the request to the origin on port 8080.
    • Backend on :8080 is your existing web server (Apache for WordPress, Nginx for a static site, Node.js, etc.). It is no longer directly exposed to the internet.
    This layering gives you TLS, caching, and origin flexibility without coupling them. You can swap the backend, upgrade Varnish, or move TLS to a separate host without touching the other layers.

    Prerequisites

    Before you begin, make sure you have:

    • A VPS running Ubuntu 24.04 LTS with root or sudo access
    • SSH access to your server
    • A working backend application (WordPress, a LEMP stack, or similar) currently listening on port 80 or 443
    • A domain name already pointing to the server's IP (A/AAAA records via Cloudflare or your DNS provider)
    • At least 2 GB of RAM -- Varnish is happiest when you can give it 1 GB or more of dedicated cache memory
    • At least 2 vCPU cores -- Varnish parallelises aggressively
    Recommended Plan: CloudCore Professional
    >
    Varnish's performance scales with RAM and CPU. For a cache in front of a medium-traffic WordPress or Magento site, we recommend the CloudCore Professional plan:
    >
    - 6 vCPU cores
    - 12 GB RAM (plenty for a 4 GB malloc cache plus the application stack)
    - 100 GB NVMe SSD
    - Unmetered bandwidth
    >
    The NVMe disk matters if you choose the file storage backend, and the extra RAM lets you keep both PHP-FPM and a sizeable cache warm simultaneously.

    Connect to your server via SSH:

    bash
    ssh root@your-server-ip

    Step 1: Update System Packages

    bash
    sudo apt update && sudo apt upgrade -y

    Install the helper packages we will need for the repository setup:

    bash
    sudo apt install -y curl gnupg debian-archive-keyring apt-transport-https ca-certificates

    If the kernel was upgraded, reboot before continuing:

    bash
    sudo reboot

    Step 2: Add the packagecloud.io Repository

    Ubuntu 24.04 ships with Varnish 7.5 in the universe repository, but the version stream on packagecloud.io is the one the Varnish project maintains officially. It gives you Varnish 7.4 LTS (supported until 2026) plus timely security patches.

    Import the repository signing key:

    bash
    curl -fsSL https://packagecloud.io/varnishcache/varnish74/gpgkey \
      | sudo gpg --dearmor -o /usr/share/keyrings/varnish74-archive-keyring.gpg

    Add the repository definition:

    bash
    sudo tee /etc/apt/sources.list.d/varnishcache_varnish74.list > /dev/null <<'EOF'
    deb [signed-by=/usr/share/keyrings/varnish74-archive-keyring.gpg] https://packagecloud.io/varnishcache/varnish74/ubuntu/ noble main
    deb-src [signed-by=/usr/share/keyrings/varnish74-archive-keyring.gpg] https://packagecloud.io/varnishcache/varnish74/ubuntu/ noble main
    EOF

    Pin the upstream packages so apt upgrade does not silently replace them with the Ubuntu version:

    bash
    sudo tee /etc/apt/preferences.d/varnish > /dev/null <<'EOF'
    Package: varnish varnish-*
    Pin: origin packagecloud.io
    Pin-Priority: 1000
    EOF

    Refresh the package index:

    bash
    sudo apt update

    Step 3: Install Varnish 7.4 LTS

    bash
    sudo apt install -y varnish

    Confirm the installed version:

    bash
    varnishd -V

    Expected output:

    text
    varnishd (varnish-7.4.3 revision ...)
    Copyright (c) 2006 Verdens Gang AS
    Copyright (c) 2006-2024 Varnish Software

    Check that the service is running:

    bash
    sudo systemctl status varnish

    The default configuration listens on port 6081 and proxies to a backend on 127.0.0.1:8080. That matches the architecture above, so we only need to tune a few parameters and write our VCL.

    Step 4: Configure the systemd Listen Parameters

    Varnish is controlled by systemd unit parameters rather than a config file -- you pass flags directly to varnishd. On Ubuntu the unit lives at /lib/systemd/system/varnish.service, but you should never edit that directly. Instead, create an override:

    bash
    sudo systemctl edit varnish

    In the editor, add:

    ini
    [Service]
    ExecStart=
    ExecStart=/usr/sbin/varnishd \
      -a :6081 \
      -a localhost:6082,PROXY \
      -p feature=+http2 \
      -f /etc/varnish/default.vcl \
      -s malloc,1g \
      -T localhost:6083 \
      -S /etc/varnish/secret

    Save and exit. The blank ExecStart= line is required -- it clears the inherited default before you set a new one.

    What each flag does:

    • -a :6081 -- Listen on port 6081 for plain HTTP from the Nginx TLS terminator.
    • -a localhost:6082,PROXY -- Additional listener that speaks the PROXY protocol. Useful if you later front Varnish with HAProxy or a load balancer that preserves client IPs.
    • -p feature=+http2 -- Enable HTTP/2 on the backend-facing connection.
    • -f /etc/varnish/default.vcl -- Path to the VCL file we will write in the next step.
    • -s malloc,1g -- The storage engine and size. malloc keeps the cache entirely in RAM, which is the fastest option and right for most sites. Use -s file,/var/lib/varnish/cache.bin,20g if you need a cache larger than your available RAM (the kernel page cache will still hold hot objects in memory).
    • -T localhost:6083 -- Admin/CLI port for varnishadm.
    • -S /etc/varnish/secret -- Shared secret file used to authenticate varnishadm sessions.

    malloc vs file storage

    • malloc,SIZE is RAM-backed. It is the fastest, simplest, and what you almost always want. The OS kernel is not involved in serving cached objects. If Varnish is killed, the cache is lost.
    • file,PATH,SIZE is disk-backed but mmap'd into memory. On an NVMe VPS with modest RAM, this lets you hold a 50 GB catalogue of rarely-changing pages. It is slower than malloc on a cold cache but fine once the working set is in page cache.
    • default,SIZE is a synonym for malloc in recent Varnish versions.
    Do not use file on a spinning disk -- the seek latency defeats the point of a cache.

    Reload systemd and restart Varnish:

    bash
    sudo systemctl daemon-reload
    sudo systemctl restart varnish

    Step 5: Write a Production VCL

    Varnish ships with a trivial default VCL at /etc/varnish/default.vcl. Replace it with a WordPress-tuned version that demonstrates the important subroutines.

    bash
    sudo cp /etc/varnish/default.vcl /etc/varnish/default.vcl.orig
    sudo tee /etc/varnish/default.vcl > /dev/null <<'EOF'
    vcl 4.1;

    import std;

    backend default { .host = "127.0.0.1"; .port = "8080"; .connect_timeout = 5s; .first_byte_timeout = 60s; .between_bytes_timeout = 30s; }

    ACL for clients allowed to issue PURGE requests.

    acl purge { "localhost"; "127.0.0.1"; "::1"; }

    sub vcl_recv { # Set the forwarded-for header for the backend. if (req.restarts == 0) { if (req.http.X-Forwarded-For) { set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip; } else { set req.http.X-Forwarded-For = client.ip; } }

    # Allow cache invalidation over HTTP PURGE. if (req.method == "PURGE") { if (!client.ip ~ purge) { return (synth(403, "Purge not allowed")); } return (purge); }

    # Only cache GET and HEAD. if (req.method != "GET" && req.method != "HEAD") { return (pass); }

    # Never cache the WordPress admin, login, or REST API writes. if (req.url ~ "^/wp-(login|admin|cron)" || req.url ~ "^/xmlrpc\.php" || req.url ~ "preview=true") { return (pass); }

    # Skip cache for logged-in users and commenters. if (req.http.Cookie ~ "wordpress_logged_in_" || req.http.Cookie ~ "comment_author_" || req.http.Cookie ~ "wp-postpass_" || req.http.Cookie ~ "woocommerce_items_in_cart") { return (pass); }

    # Strip tracking and analytics cookies so anonymous visitors share a cache key. set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_[_a-z]+|__utm[a-z]+|_ga|_gid|_fbp|wp-settings-\d+|wp-settings-time-\d+)=[^;]+", ""); set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");

    # If nothing useful is left, drop the Cookie header entirely. if (req.http.Cookie == "" || req.http.Cookie ~ "^\s*$") { unset req.http.Cookie; }

    # Normalise Accept-Encoding so we do not cache the same page twice. if (req.http.Accept-Encoding) { if (req.url ~ "\.(jpg|jpeg|png|gif|gz|mp3|mp4|zip|ico|webp|avif|pdf)$") { unset req.http.Accept-Encoding; } elsif (req.http.Accept-Encoding ~ "br") { set req.http.Accept-Encoding = "br"; } elsif (req.http.Accept-Encoding ~ "gzip") { set req.http.Accept-Encoding = "gzip"; } else { unset req.http.Accept-Encoding; } }

    return (hash); }

    sub vcl_backend_response { # Set a default TTL if the backend did not send Cache-Control. if (beresp.ttl <= 0s) { set beresp.ttl = 1h; set beresp.uncacheable = false; }

    # Cache static assets aggressively regardless of origin headers. if (bereq.url ~ "\.(css|js|png|jpg|jpeg|gif|ico|woff2?|svg|webp|avif)$") { unset beresp.http.Set-Cookie; set beresp.ttl = 7d; set beresp.http.Cache-Control = "public, max-age=604800"; }

    # Enable grace mode -- serve stale content for up to 6 hours while we refresh. set beresp.grace = 6h;

    # Do not cache responses that set cookies (login, checkout, etc.). if (beresp.http.Set-Cookie) { set beresp.uncacheable = true; }

    return (deliver); }

    sub vcl_deliver { # Debug header so you can tell from the client if a response was cached. if (obj.hits > 0) { set resp.http.X-Cache = "HIT"; set resp.http.X-Cache-Hits = obj.hits; } else { set resp.http.X-Cache = "MISS"; }

    # Remove headers that leak the backend stack. unset resp.http.X-Powered-By; unset resp.http.Server; unset resp.http.Via;

    return (deliver); } EOF

    Validate the VCL before reloading -- a syntax error leaves the old config running, but it is still good hygiene:

    bash
    sudo varnishd -C -f /etc/varnish/default.vcl > /dev/null

    If there is no output, the VCL compiled successfully. Reload Varnish live (no downtime):

    bash
    sudo varnishreload

    What this VCL does

    • vcl_recv runs on every incoming request. We check for PURGE, strip anonymous-visitor cookies, honour logged-in WordPress users, and normalise Accept-Encoding so we do not keep separate cache entries for gzip, deflate, br vs gzip, br.
    • vcl_backend_response runs after the backend answers a miss. We force a 1 hour default TTL, give static assets 7 days, mark any response with Set-Cookie as uncacheable, and enable 6 hours of grace mode so stale pages continue to serve while Varnish asynchronously refreshes them.
    • vcl_deliver runs just before we ship the response to the client. We add an X-Cache: HIT|MISS header that is invaluable for debugging, and strip server-fingerprint headers.

    Step 6: Put Nginx in Front of Varnish for TLS

    Varnish speaks cleartext HTTP only. For HTTPS you need a TLS-terminating frontend. Nginx is the pragmatic choice -- it handles HTTP/2, certificate renewal via Certbot, and can still serve static files directly if you want to bypass Varnish for specific paths.

    If you do not already have our dedicated article: How to Install Nginx on Ubuntu 24.04 walks through the initial Nginx setup. Assuming Nginx is already installed, install Certbot:

    bash
    sudo apt install -y certbot python3-certbot-nginx

    Create the site configuration:

    bash
    sudo tee /etc/nginx/sites-available/varnish-frontend > /dev/null <<'EOF'
    server {
        listen 80;
        listen [::]:80;
        server_name yourdomain.com www.yourdomain.com;
        return 301 https://$host$request_uri;
    }

    server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name yourdomain.com www.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers off;

    # Let Varnish see the real client IP and scheme. 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 $scheme; proxy_http_version 1.1; proxy_set_header Connection ""; } } EOF

    Enable the site and obtain a certificate with Let's Encrypt (see our Let's Encrypt guide if you are new to Certbot):

    bash
    sudo ln -s /etc/nginx/sites-available/varnish-frontend /etc/nginx/sites-enabled/
    sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
    sudo nginx -t && sudo systemctl reload nginx

    Step 7: Move the Backend to Port 8080

    Your origin application (Apache or a second Nginx vhost serving WordPress) is currently probably bound to :80 or :443. It needs to move to 127.0.0.1:8080 so Varnish can proxy to it.

    For an Apache backend

    Edit /etc/apache2/ports.conf:

    apache
    Listen 127.0.0.1:8080

    Edit your vhost in /etc/apache2/sites-available/*.conf:

    apache
    <VirtualHost 127.0.0.1:8080>
        ServerName yourdomain.com
        DocumentRoot /var/www/yourdomain.com
        ...
    </VirtualHost>

    Enable remoteip so Apache logs the real client IP from X-Forwarded-For:

    bash
    sudo a2enmod remoteip

    Add to your vhost:

    apache
    RemoteIPHeader X-Forwarded-For
    RemoteIPTrustedProxy 127.0.0.1

    Restart Apache:

    bash
    sudo systemctl restart apache2

    For a Nginx origin

    Change the listen directive on your origin vhost to listen 127.0.0.1:8080; and reload Nginx. If you are running WordPress, update WP_HOME and WP_SITEURL to use https:// since Nginx terminates TLS upstream.

    Step 8: Verify the Cache is Working

    Send two requests to your site and inspect the headers:

    bash
    curl -sI https://yourdomain.com/ | grep -Ei 'x-cache|age|cache-control'

    The first response should be a MISS:

    text
    x-cache: MISS
    cache-control: max-age=3600

    The second response should be a HIT:

    text
    x-cache: HIT
    x-cache-hits: 1
    age: 4
    cache-control: max-age=3600

    If you see X-Cache: MISS on every request, jump to the Troubleshooting section -- something in the request (usually a cookie) is forcing a pass.

    Post-Install: Purging, Monitoring, and Tuning

    Purging a specific URL

    With the ACL we defined in VCL, PURGE from the local host is allowed:

    bash
    curl -X PURGE http://localhost:6081/path/to/article/

    WordPress plugins like W3 Total Cache and WP Rocket can be pointed at http://localhost:6081 so that editing a post purges the relevant entries automatically.

    Banning a pattern

    PURGE removes one URL. To invalidate everything matching a pattern, use varnishadm with a ban expression:

    bash
    sudo varnishadm ban 'req.url ~ "^/blog/"'

    This marks every cached object whose URL starts with /blog/ as invalid. On the next request for a matching URL, Varnish fetches a fresh copy from the backend.

    Real-time traffic inspection with varnishlog

    bash
    sudo varnishlog

    This streams every transaction through the cache -- headers in, headers out, which VCL subroutine fired, how long the backend took. To filter for cache misses only:

    bash
    sudo varnishlog -q "VCL_call eq 'MISS'"

    To watch a single client IP:

    bash
    sudo varnishlog -q "ReqHeader:X-Forwarded-For eq '203.0.113.10'"

    Statistics with varnishstat

    bash
    sudo varnishstat

    Press h for help. The two counters you care about most are:

    • MAIN.cache_hit -- total cache hits
    • MAIN.cache_miss -- total cache misses
    Your hit ratio should ideally be above 80% on a well-tuned content site. Below 50% usually means cookies or unique query parameters are splitting the cache key.

    Admin console with varnishadm

    bash
    sudo varnishadm

    From the prompt you can list VCL versions, load a new one without a restart, inspect live config, and view the backend health:

    text
    varnish> vcl.list
    varnish> backend.list
    varnish> ban.list

    Troubleshooting

    ProblemCauseSolution
    varnishd[...]: Error: VCL compilation failed on restartSyntax error in default.vclRun sudo varnishd -C -f /etc/varnish/default.vcl to see the line number. Fix and sudo varnishreload.
    X-Cache: MISS on every requestA cookie or request header is forcing a passRun sudo varnishlog -q "VCL_call eq 'PASS'" and look at ReqHeader:Cookie. Add any missing tracking cookies to the strip regex in vcl_recv.
    Logged-in users see other users' contentLogged-in detection is not matchingConfirm the WordPress login cookie prefix (wordpress_logged_in_) in vcl_recv. For WooCommerce add woocommerce_cart_hash and woocommerce_items_in_cart.
    503 Backend fetch failedOrigin on :8080 is down or unreachableCheck sudo systemctl status apache2 (or nginx). Test directly: curl -v http://127.0.0.1:8080. Check firewall: sudo ufw status.
    Cache is being bypassed by query stringsTracking parameters (utm_*, fbclid) creating unique cache keysNormalise query strings in vcl_recv: set req.url = regsuball(req.url, "\?(utm_[^&]+</td><td>fbclid=[^&]+)&?", "?");
    Varnish restarts clear the cachemalloc storage is RAM-only and non-persistentThis is expected. Use -s file,/var/lib/varnish/cache.bin,20g if you need survival across restarts.
    Child (XXXX) died signal=9 (OOM kill)malloc size exceeds available RAMReduce -s malloc,Ng or upgrade RAM. Leave at least 2 GB for the OS and backend.
    PURGE returns 403Client IP is not in the purge ACLAdd the IP to the acl purge {} block in VCL and reload.

    Viewing Varnish logs

    bash
    sudo journalctl -u varnish -f

    Varnish's most useful log is the shared-memory log exposed via varnishlog, not systemd. The systemd journal mostly shows startup errors and VCL compile failures.

    FAQ

    How much RAM should I give Varnish?

    Give Varnish enough memory to hold your working set -- the subset of pages that get hit frequently. For a typical WordPress site with 1,000 cacheable pages averaging 50 KB each, that is 50 MB of actual content. Size -s malloc at 5-10x that because Varnish also stores headers, revalidation state, and some overhead per object. On a 12 GB VPS, a 2 GB malloc cache is a reasonable default. Always leave at least 2 GB free for the OS and your backend.

    Can I run Varnish on the same server as my WordPress site?

    Yes, and that is the most common deployment. The three-tier pipeline (Nginx TLS → Varnish → Apache/PHP-FPM on :8080) all lives on one VPS. Our CloudCore Professional plan is right-sized for this: 12 GB RAM lets you run a 2 GB Varnish cache, a PHP-FPM pool with 8-12 workers, and MySQL comfortably.

    Does Varnish handle HTTPS?

    Not natively. Varnish is strictly HTTP. Use Nginx (or HAProxy, or Caddy) in front for TLS termination. This is an intentional design choice -- Varnish focuses on caching and lets specialised tools handle encryption.

    How do I cache logged-in WordPress users?

    You usually should not -- the whole point of logged-in pages is that they are personalised. If you really need to (for example, a dashboard that shows the same data to everyone in the "subscriber" role), use Vary: Cookie from the backend and key on a specific cookie. This is advanced VCL and out of scope for a starter guide. For most sites, serve anonymous visitors from cache and let logged-in users hit the backend.

    How do I purge the whole cache?

    bash
    sudo varnishadm ban 'req.url ~ "."'

    This bans every URL. Varnish will re-fetch each one on its next request. For a full flush, restart the service: sudo systemctl restart varnish.

    Can I use Varnish with Cloudflare in front?

    Yes. Cloudflare terminates TLS at its edge, forwards to your Nginx on :443, which forwards to Varnish on :6081, which forwards to the origin on :8080. Two layers of cache with different roles: Cloudflare caches globally across data centres, Varnish caches at your origin. Make sure Nginx's real_ip_header is set to CF-Connecting-IP so Varnish and your backend see the true client IP.

    Next Steps

    Now that Varnish is sitting between Nginx and your origin, consider these follow-ups:

    • Tune WordPress cache plugins -- Install W3 Total Cache or WP Rocket and configure it to call PURGE http://localhost:6081/... when posts are updated. See our WordPress install guide for the baseline setup.
    • Add monitoring -- Ship varnishstat counters into Prometheus using the varnish_exporter and chart hit ratio, MAIN.n_lru_nuked, and backend latency.
    • Experiment with ESI -- Varnish supports Edge Side Includes. You can cache most of a page for hours while leaving a single fragment (like a personalised greeting) to be assembled per-request.
    • Try the file storage backend -- Switch -s malloc,1g to -s file,/var/lib/varnish/cache.bin,20g if your cacheable content is larger than RAM.
    • Read the official docs -- The Varnish Book and varnish-cache.org documentation are excellent and cover advanced topics like VMODs, probes, directors, and load balancing.

    Make Varnish Easier with the Right VPS
    >
    Varnish thrives on RAM, fast single-core performance, and NVMe disk. Our CloudCore Professional plan gives you 6 vCPU, 12 GB RAM, and 100 GB NVMe -- exactly the profile Varnish loves.
    >
    - Full root access for systemd and VCL tuning
    - Deploy in under 60 seconds
    - EUR 19.99/month, unmetered bandwidth
    >
    Launch a CloudCore Professional VPS and start accelerating your site today.

    Was this article helpful?

    ← Back to Install GuidesBrowse all categories →

    Still have questions?

    Contact Support →Submit a Ticket