Paragon Initiative Enterprises Blog

The latest information from the team that develops cryptographically secure PHP software.

HTTPS Made Easy: Setting up Caddy for PHP 7 on Debian Jessie

Caddy is a modern open source HTTP/2 webserver written in Go. One of its most attractive features over other webservers (Apache, nginx, lighttpd, etc.) is that Caddy integrates with the free LetsEncrypt certificate authority to ensure all of your websites support HTTPS, out of the box.

(Caveat: localhost and IP address virtual hosts are excluded from this automatic HTTPS, which also makes Caddy suitable for local development environments.)

What follows is a step-by-step guide for getting the latest version of Caddy (0.8.3) set up on a freshly installed Debian Linux 8.5 (Jessie) server. Please note that this was written on July 17, 2016; if you are reading this in the distant future, some of the steps may be incorrect. (In all likelihood, it will become easier.)

First Step: Hardening your Linux Kernel

Before you do anything else, make sure you're running the latest version of everything. This ensures you're not running vulnerable software.

sudo apt-get update
sudo apt-get dist-upgrade

Next, we generally recommend installing a Linux kernel with the grsecurity/PaX kernel patches. This adds a strong layer of exploit mitigation to the software running on your environment. This step is not required, but we highly recommend everyone use a hardened Linux kernel.

sudo apt-get install linux-image-grsec-amd64

Restart to boot into the new kernel, then proceed to install PHP 7.

Setting up PHP 7 with the FastCGI Process Manager (FPM)

Debian doesn't ship with PHP 7.0 by default. Fortunately, there's dotdeb for that. Verify then install their GPG public key, then add those entries as an apt source, like so:

echo "deb http://packages.dotdeb.org jessie all" > /etc/apt/sources.list.d/dotdeb.list
echo "deb-src http://packages.dotdeb.org jessie all" >> /etc/apt/sources.list.d/dotdeb.list

wget https://www.dotdeb.org/dotdeb.gpg
# SHA-384 is not vulnerable to length-extension attacks. However, this is a weak
# verification that only stops transmission errors.
#
# You should verify the full fingerprint manually.
echo "ac6336bcd3883126c9976bd1e4aeff45be1a24e430be575c197954ce0b9288d0f4b35dfa675d72fb94bd35fd073aec27  dotdeb.gpg" | sha384sum -c
if [ $? -eq 0 ]; then
    sudo apt-key add dotdeb.gpg
else
    echo "Wrong public key"
    exit 1
fi

sudo apt-get update
sudo apt-get install php7.0-fpm

This is also a good point to install any PHP extensions (e.g. libsodium from PECL) that you may need.

Setting up the Caddy web server

The best place to get Caddy is from the Caddy website, which allows you to customize which features you need. However, if you just need the core features accessible from wget, then the Github releases are your destination. (There is a freshly opened ticket to request Caddy releases be cryptographically signed. Once that's implemented, we will update this post with specific instructions.)

After you download and extract the release, you'll need to delve into systemd configuration. This can get complicated quickly, and the instructions provided in the init/ directory target a newer version than Debian provides. Through trial and error, we managed to get the following instructions to work reliably:

mkdir /tmp/caddy && cd /tmp/caddy
wget https://github.com/mholt/caddy/releases/download/v0.8.3/caddy_linux_amd64.tar.gz

# Extract:
tar zxvf caddy_linux_amd64.tar.gz

# Place the caddy binary in a standard location:
sudo mv caddy_linux_amd64 /usr/bin/caddy

# Remove newer systemd token (%I) from the caddy.service file and change the group
# from 'http' to 'www-data':
sed -e 's/%I//' init/linux-systemd/caddy\@.service | \
    sed -e 's/=http/=www-data/' > \
    /lib/systemd/system/caddy.service

# Make a global configuration directory:
sudo mkdir /etc/caddy

systemctl daemon-reload

The above commands set up the systemd service (in /lib/systemd/system/), create a directory /etc/caddy for placing your Caddyfile and any other configuration files, then reloads the systemd configuration.

Next, you'll need to create a Caddyfile and store it at /etc/caddy/Caddyfile. Note that you can edit /lib/systemd/system/caddy.service if you want to change the location of the Caddyfile. An example Caddyfile follows:

example.com:80, example.com:443 {
  log /var/log/www_access.log
  fastcgi / /run/php/php7.0-fpm.sock php
  root /var/www/my_project/public
  rewrite {
    to {path} {path}/ /index.php?{query}
  }
}

Once this is all done, enable then start the Caddy service and you're all set:

systemctl enable caddy.service
systemctl start caddy.service

Next Steps

Read the documentation to learn how to better configure your website. If you're connecting to a domain name, it should automatically be served over HTTPS with a fresh LetsEncrypt certificate. It is for this reason that we highly recommend everyone use Caddy for web development in 2016 and beyond.

About the Author

P.I.E. Staff

Paragon Initiative Enterprises

Paragon Initiative Enterprises is a Florida-based company that provides software consulting, application development, code auditing, and security engineering services. We specialize in PHP Security and applied cryptography.


Need Technology Consultants?

Will tomorrow bring costly and embarrassing data breaches? Or will it bring growth, success, and peace of mind?

Our team of technology consultants have extensive knowledge and experience with application security and web/application development.

We specialize in cryptography and secure PHP development.

Let's Work Together Towards Success

Our Security Newsletters

Want the latest from Paragon Initiative Enterprises delivered straight to your inbox? We have two newsletters to choose from.

The first mails quarterly and often showcases our behind-the-scenes projects.

The other is unscheduled and gives you a direct feed into the findings of our open source security research initiatives.

Quarterly Newsletter   Security Announcements