DEV Community

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

Posted on • Edited on

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

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; ... } 
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/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; } } 
Enter fullscreen mode Exit fullscreen mode
  • 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 
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/example.com/privkey.pem /etc/letsencrypt/live/example.com/fullchain.pem > /etc/ssl/private/exampledotcom.pem exit 
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 example.com 172.1.35.35:80 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 = ['172.1.35.35']; 
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

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.

Top comments (0)