DEV Community

Cover image for 10 Step Guide: Varnish + Nginx + PHP On Ubuntu With SSL

10 Step Guide: Varnish + Nginx + PHP On Ubuntu With SSL

adam_crampton profile image Adam Crampton Updated on ・4 min read

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 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;
Enter fullscreen mode Exit fullscreen mode

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/
  • Paste this in (or use your preferred boilerplate):
server {
    listen 8080;;
    root /var/www/;

    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;
Enter fullscreen mode Exit fullscreen mode
  • Save the file, then create the symlink by running:

sudo ls -n /etc/nginx/sites-available/ /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 -d
  • Select No Redirect option
  • Edit /etc/nginx/sites-available/ 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/; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
Enter fullscreen mode Exit fullscreen mode

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/ /etc/letsencrypt/live/ > /etc/ssl/private/exampledotcom.pem
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
  • Edit /etc/varnish/default.vcl and ensure the backend default port is set to 8080
  • 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
Enter fullscreen mode Exit fullscreen mode
  • 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 check
Enter fullscreen mode Exit fullscreen mode

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 in App\Http\Middleware\TrustProxies:
protected $proxies = [''];
Enter fullscreen mode Exit fullscreen mode

Note: If you are behind a load balancer where you cannot reliably determine the IP, you can do this:

protected $proxies = '*';
Enter fullscreen mode Exit fullscreen mode

Useful Links


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.

Discussion (0)

Editor guide