Adam Crampton
Posted on February 15, 2021
Setting up Varnish with SSL can be tricky, largely because there isn't any one place to get all the information you need in a straightforward manner.
Having gone through the frustration of piecing it all together myself, I decided to write a quick guide that details the process from start to finish.
Initially, I attempted the SSL portion of the job by using Hitch - which ended up being a complete waste of time (mostly because of really poor documentation). HAProxy on the other hand ended up being a great solution, as well as having other really great features like load balancing included.
Let's get straight to it. Here's the stack I'm working through in this article:
- Ubuntu 18.04
- PHP 7.4
- Nginx
- Varnish 5.2.1
- Letsencrypt SSL
- HAProxy
- Laravel 8
You can ignore the PHP and Laravel bits if you're using a different stack.
0. Getting Started
You will need:
- Ubuntu 18.04 installation + sudo SSH access
- DNS configured for the server block you are going to add to Nginx (it'll be example.com in this article)
1. Set Up Nginx
Install nginx using:
sudo apt update
sudo apt install nginx
Set the default ports:
-
sudo vim /etc/nginx/sites-available/default
server {
listen 8080 default_server;
listen [::]:8080 default_server;
...
}
Note: Don't create the server block for your site just yet, we'll get to that shortly.
2. Install PHP 7.4 + Required Extensions
If PHP isn't already installed, run the following commands to get PHP 7.4 along with extensions required for a Laravel (and most modern PHP apps) project:
sudo apt install software-properties-common
sudo add-apt-repository ppa:ondrej/php
sudo apt update
sudo apt install php7.4 php7.4-cli php7.4-fpm php7.4-json php7.4-common php7.4-mysql php7.4-zip php7.4-gd php7.4-mbstring php7.4-curl php7.4-xml php7.4-pear php7.4-bcmath
3. Install FPM + Composer
Install FPM and Composer if you require it:
sudo apt install php7.4-fpm
sudo apt install composer
4. Create Nginx server block
Now we can create the Nginx server block for our site:
sudo vim /etc/nginx/sites-available/example.com
- Paste this in (or use your preferred boilerplate):
server {
listen 8080;
server_name example.com www.example.com;
root /var/www/example.com/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
index index.html index.htm index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
- Save the file, then create the symlink by running:
sudo ls -n /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
- Restart Nginx:
sudo service nginx restart
5. Install Cerbot
Certbot needs to be installed to request a Let's Encrypt certificate for our site. Ensure your DNS records are pointing to this server and run the following:
sudo add-apt-repository ppa:certbot/certbot
sudo apt install python-certbot-nginx
sudo certbot --nginx -d example.com -d www.example.com
- Select No Redirect option
- Edit
/etc/nginx/sites-available/example.com
and remove SSL lines added by Certbot at the bottom of the file - it will look something like this:
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
6. Prepare PEM File
Next we will need to create a PEM file for our SSL proxy to use further down the track. To do so, we'll append the private key and fullchain key values to a single file:
Switch to root (sudo su
), then:
sudo cat /etc/letsencrypt/live/example.com/privkey.pem /etc/letsencrypt/live/example.com/fullchain.pem > /etc/ssl/private/exampledotcom.pem
exit
7. Install + Configure Varnish
Varnish can now be installed and configured:
sudo apt -y install varnish
- Edit
/lib/systemd/system/varnish.service
and change the default port from 6081 to 80:
ExecStart=/usr/sbin/varnishd -j unix,user=vcache -F -a :80 -T localhost:6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m
- Edit
/etc/varnish/default.vcl
and ensure thebackend default
port is set to8080
- Run
sudo systemctl daemon-reload && sudo service varnish restart
Varnish should now be working for your site for HTTP.
8. Install + Configure HAProxy
- Install HAProxy:
sudo apt-get install haproxy
- Open for editing:
sudo vim /etc/haproxy/haproxy.cfg
- Add a front end binding, pointing towards PEM file created earlier:
frontend haproxynode
bind *:443 ssl crt /etc/ssl/private/exampledotcom.pem
mode http
default_backend backendnodes
- Add back end config + node:
backend backendnodes
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
server example.com 172.1.35.35:80 check
Important: IP address above must be that of the server this host sits on. use ifconfig
to determine that address.
To test the config for errors, run sudo haproxy -c -f /etc/haproxy/haproxy.cfg
:
9. Restart Everything
sudo service nginx restart && sudo service varnish restart && sudo service haproxy restart
10. Trust Proxy Config (Laravel only)
- Add the server IP from step 8 to the
$proxies
property inApp\Http\Middleware\TrustProxies
:
protected $proxies = ['172.1.35.35'];
Note: If you are behind a load balancer where you cannot reliably determine the IP, you can do this:
protected $proxies = '*';
Useful Links
- Ubuntu 18.04 + Nginx install guide: https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-18-04
- Let's Encrypt Nginx Tutorial: https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-18-04
- VCL Reference: https://varnish-cache.org/docs/5.2/users-guide/vcl.html
- An excellent VCL configuration template can be found here: https://github.com/mattiasgeniar/varnish-5.0-configuration-templates
Thanks!
Hopefully this guide was helpful for you, thanks for taking a look.
If there are any corrections to the above, please leave a comment and I will update the article.
Posted on February 15, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.