How to Tango with Varnish, Nginx, and SSL—Without Stepping on Your Own Toes

In the world of website performance, Varnish and Nginx are the dynamic duo you never knew you needed. They’re like Batman and Robin—one speeds up your site (Varnish), while the other manages incoming traffic and SSL encryption like a boss (Nginx). But when you throw SSL into the mix, it can feel like inviting a third person to your dance routine. Let’s take a deep breath and dive into configuring Varnish with Nginx and SSL without tripping over ourselves!
Step 1: Why Do You Need Varnish and Nginx Together?
Good question. You might be wondering, “Why not just use one or the other?” Well, Nginx handles SSL (because Varnish doesn’t speak SSL—yet). But Varnish excels at caching and can dramatically reduce load times. Nginx is the chaperone that ensures secure communication (SSL), while Varnish is the speedster in the background, handing out cached pages like candy.
Let’s break down this setup. In simple terms:
Nginx will handle incoming HTTPS (SSL-encrypted) requests and decrypt them.
Varnish will handle the caching of HTTP content to speed up your site.
Nginx will then send those cached HTTP responses back as secure HTTPS.
Now, that sounds like a perfect three-way partnership.
Step 2: Installing Varnish and Nginx
Before we start pairing them up, you need to make sure both Varnish and Nginx are installed on your server. A quick installation command for Ubuntu is below:
Install Varnish:
sudo apt update
sudo apt install varnish
Install Nginx:
sudo apt install nginx
With the superheroes installed, let’s get them working together.
Step 3: Nginx Configuration (SSL Setup)
Nginx is in charge of handling SSL termination. This means it will accept HTTPS requests and decrypt them before passing them on to Varnish. Here’s how to configure Nginx for SSL:
1. Get your SSL certificates – You can either buy one or use Let’s Encrypt to get a free SSL certificate. Let’s Encrypt is recommended for ease of use.
2. Edit your Nginx configuration – You’ll want to configure Nginx to listen on port 443 (the default port for HTTPS). Open the configuration file for your site:
sudo nano /etc/nginx/sites-available/yourdomain.com
3. Add the SSL configuration – Add the following SSL-related code:
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
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;
}
}
This config tells Nginx to listen for HTTPS requests, decrypt them, and pass them to Varnish on port 8080 (because Varnish works with HTTP, not HTTPS).
Step 4: Configuring Varnish
Now that Nginx is decrypting the SSL, we’ll need to adjust Varnish to handle the non-encrypted (HTTP) traffic. Out of the box, Varnish listens on port 6081 for HTTP traffic. We’ll need to change that so it works on port 8080 instead (since Nginx is passing traffic to that port).
1. Edit Varnish’s default configuration file:
sudo nano /etc/varnish/default.vcl
2. Update the backend definition to point to the default web server port (where your app is running, likely 8080):
backend default {
.host = "127.0.0.1";
.port = "8080";
}
Change the listening port for Varnish. To do this, you’ll need to modify the ExecStart
parameter in the systemd service file to listen on port 8080 instead of 6081.
Open the Varnish service file:
sudo nano /etc/systemd/system/varnish.service
Then, look for the line that starts with ExecStart
and modify the port:
ExecStart=/usr/sbin/varnishd -a :8080 -T localhost:6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m
Reload systemd and restart Varnish:
sudo systemctl daemon-reload
sudo systemctl restart varnish
Step 5: Nginx Handling HTTP for Varnish
Once Varnish has done its caching magic, Nginx needs to deliver the content to the user. Configure another server block in Nginx for non-SSL requests, which Varnish handles.
1. Open the Nginx config file again:
sudo nano /etc/nginx/sites-available/yourdomain.com
2. Add the following configuration to handle the HTTP traffic:
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://127.0.0.1:8080;
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 http;
}
}
This block will listen for HTTP requests on port 80 and pass them through to Varnish.
Step 6: Wrapping It All Up
Nginx handles SSL, decrypts HTTPS requests, and forwards them as HTTP.
Varnish caches these HTTP requests, improving performance.
Nginx finally delivers the cached content to the end user securely.
Restart both services to apply changes:
sudo systemctl restart nginx
sudo systemctl restart varnish
Bonus Step: Dance Moves for Extra Credit
If you want to go the extra mile (and who doesn’t love a little extra flair?), you can tweak Varnish’s caching policies in the default.vcl
file to fine-tune what content gets cached and for how long. You can also configure load balancing, security headers, and more.
Final Thoughts
Now you’ve got Varnish, Nginx, and SSL dancing together like a well-choreographed trio. Varnish handles your caching, Nginx secures the show with SSL, and your website users get the benefit of blazing-fast load times, all wrapped in a secure HTTPS bow.
And the best part? No toes were stepped on in the making of this guide (we hope).
Happy configuring!