Set up Varnish Cache on a HTTPS optional Laravel site

Some notes only, not a full article:

Download and install Varnish, move your Apache ports

https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-varnish-with-apache-on-ubuntu-12-04–3

Above link explains that you make Varnish listen to 80, and Apache to 8080. After fixing below issue, make sure both work. If so, block 8080 in your iptables if you wish.

Varnish does not listen to port 80

You noticed running netstat -tulnp

There’s an issue with Debian, systemd, daemons and what not in actually configuring the port to listen to. Follow http://stackoverflow.com/a/30618749

sudo grep -R 'ExecStart=/usr/sbin/varnishd' /etc/

so you can actually find the other place where daemon options for Varnish are set (in my case it was /etc/systemd/system/multi-user.target.wants/varnish.service). Open file in vim,nano or whatever and set “ExecStart” in that file as fallows:

-a :80 -T localhost:.... -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m

Save and exit. After that do:

systemctl daemon-reload
systemctl restart varnish.service

Configure Varnish Cache

Set up your /etc/varnish/default.vcl file

backend default {
.host = "127.0.0.1";
.port = "8080";
}

sub vcl_recv {
# Happens before we check if we have this in cache already.
#
# Typically you clean up the request here, removing cookies you don't need,
# rewriting the request, etc.

# Remove Piwik cookies everywhere
if (req.http.Cookie) {
set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(_pk_(ses|id)[\.a-z0-9]*)=[^;]*", "");
}
# Remove the cookie when it's empty
if (req.http.Cookie == "") {
unset req.http.Cookie;
}
}

sub vcl_backend_response {
# Happens after we have read the response headers from the backend.
#
# Here you clean the response headers, removing silly Set-Cookie headers
# and other mistakes your backend does.
set beresp.ttl = 120s;
unset beresp.http.Cache-Control;
}

sub vcl_deliver {
# Happens when we have all the pieces we need, and are about to send the
# response to the client.
#
# You can do accounting or modifying the final object here.
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";
}
}

This caches everything with a 120sec ttl. Ignores all with a PHPSESSIONID cookie. Static files still have long TTL

SSL termination, make your HTTPS site work with Varnish

Terminate at 443 and proxy to Varnish:


ServerAdmin ..
ServerName ..

ProxyPreserveHost On
ProxyPass / http://127.0.0.1:80/
RequestHeader set X-Forwarded-Port "443"
RequestHeader set X-Forwarded-Proto "https"

SSLCertificateFile ....
SSLCertificateKeyFile ...
Include /etc/letsencrypt/options-ssl-apache.conf

You need Apache mods: a2enmod proxy and a2enmod proxy_http

Restart apache and varnish.

Let your application know about your setup, e.g. fix broken http vs https issues and hosts

There is a Laravel package for that https://github.com/fideloper/TrustedProxy

But maybe you can just use apt-get install libapache2-mod-rpaf ?? Not checked

Extra

Keep an eye on your memory ps aux --sort -rss | head

Pass static files instead of keeping in memory? https://ma.ttias.be/stop-caching-static-files-in-varnish/

The angry maintainer’s practical git guidelines – for small teams, topic branches, frequent releases

This is one way to do git, you might disagree.

Some guidelines:

The master contains all work that should be live on the next deploy

Therefore:

  • master can only contain reviewed code
  • Junior developers are not allowed to put work on master

All work is done on ‘feature branches’

When you start new work, create a new branch based on the master branch. Name it after yourself and the desired feature:


# base the work on master
git checkout master
# make sure it is up to date
git pull
# create the new branch
git checkout -b yourname/feature-x
# this is now the active branch

This branch is yours, you are the only one committing to it.

Commits are for free, use it to your advantage

Commit frequently. I want to see at least five commits per day.

Make sure commits are atomic. They should implement/change/abandon a coherent featureset. Try to make sure this snapshot of the code does not break. Partial implementations or uncovered edge cases are perfectly acceptable.

The description will tell what the commit is supposed to do, you can leave out the ‘how’, unless you think that is important.


# check what's up
git status
# check the actual changes, note you will not see newly added files here:
git diff
# stage the work you want to commit
git add path1 path2
# check what's staged
git diff --staged
# remove those pesky leftover var_dumps and console.logs
# edit edit
# stage those files again
git status
git add path/to/changed/file
# final check
git status
git diff --staged
# happy? commit!
git commit
# now your editor opens, write the summary, two newlines, and the description

Push your branch every now and then, it’s added safety. In case the development server burns down, your commits will still be available. And it’s harder to destroy already pushed commits yourself. Pushing is easy:

git push
# if this is the first time you push your branch,
# git will tell you to set the remote tracking.
# Simply follow the advise that is shown

In Summary

You only need 7 commands:

git checkout branchname # switch to branch
git checkout -b yourname/feature-x # create new branch
git diff # check work
git add files #stage files
git diff --staged #check staged work
git commit
git push

I do not want to see any of the following:

  • the word origin in any of your commands
  • the --track options
  • any destructive option: --force, --hard
  • push or pull with an argument
  • merge (read below) with more than one argument

Merging upstream work

Your maintainer might ask you to merge in master frequently, so you will not deviate too much from the next release. This eases the process of merging your branch back in to master (this is the work of the maintainer).


# make sure your working dir is clean
# so do this right after a commit
git checkout master
git pull
git checkout yourname/feature-x # the branch you were working on
git merge master

That’s all. Apply the same procedure if you work together with another dev on a feature. There’s two branches now: you/feature-x and colleague/feature-x. Check out their branch, pull it, switch back to yours and merge in.

You might run in a merge conflict if your changes collide with changes on the branch you are merging. Git will tell you which files to fix, and has put markers around the troubled sections. Usually this is an easy fix. Combine the code in the markers, save the files, and continue merging:

# stage the colliding files
git add conflictFile1 conflictFile2
# the other files were staged already
git commit
# leave the merge description

In case the merge is too complicated do the following:

git merge --abort
# notify your maintainer