Hexinverter ¬ Setup Kanboard + Caddy on Debian

This is just a quick runthrough of my experiences today setting up Kanboard underneath Caddy on a fresh Debian box.

I assume you can get your box to the state where you can install packages and ssh to it and be root somehow (through sudo or whatever).

I also leave out all of the various chowns and chmods you need to do to get things correct. Mostly it's just making sure some directories under the kanboard checkout are owned by www-data and things.

In this entire post, I use the domain name "test.com", needless to say, this is not my actual domain name.

Basics and Background

The first thing I did was dist-upgrade to Buster. This is pretty unnecessary, but I felt like for this application it was reasonable to chase the latest in Debian (my VPS provider only had a Stretch image available, so I installed this image, set the sources to buster and dist-upgraded).

The next thing I did was install the ferm and sshguard packages. These are pretty important if you're running a site that is exposed to the internet because they give a lot of passive resistance to various attacks. The defaults are fine as they come, and will block all ports (except ssh), and ssh will be blocked on multiple failures of login. You may want to look at the sshguard configuration to set the pace out a little because the defaults will lock you out after essentially one failed login attempt.

This step is totally skippable if you aren't running an internet-visible site.

Setup Caddy

Caddy is a go-based web server that has some neat features, so I took the opportunity to try it out.

Two things that make me an old man yelling at clouds are Go (because of the way it needs its own directory to work from rather than acting like a C complier) and the Magic Downloads that are so friggin common with Go-based projects, and course I needed to compile this on my own (partially because the "community" version is weirdly restricted in a way that rubbed me the wrong way even if it didn't affect me personally, and partially because I just like compiling things that aren't packaged on Debian).

Setup Golang

First I made a director /usr/src/go. Since Debian doesn't ship a new enough Go to compile Caddy, I had to install it. I did this by getting the binary tar.gz file for my platform (such an zgo1.12.5.linux-amd64.tar.gz from the Golang download page), and untarring it in /usr/src/go (yes yes compile compile, I'm just one person). This creates a directory go/. I also then created a /usr/src/go/build directory to hold all of the Golang dependencies and whatnot for actually building Caddy.

Since I'm a Python pleb, I next created a small shell script in /usr/src/go/activate to set the environment variables needed to compile Caddy:

export PATH=$PATH:/usr/src/go/go/bin/
export GOPATH=/usr/src/go/build/
export GO111MODULE=on

Next, I created a tiny shell script to actually build and install Caddy in /usr/src/go/build-caddy so that upgrading will be straight forward when inevitably there are security alerts for it:

. activate
go get -v  github.com/mholt/caddy/caddy
cp  build/bin/caddy /usr/local/sbin/caddy

Now to compile and install Caddy, I simply go into /usr/src/go and run ./build-caddy and I end up with /usr/local/sbin/caddy, ready to go. Test by running caddy and seeing that it runs. Control-c to exit.

Next we need to setup systemd to run caddy and keep it alive. I stared with the example systemd unit file at https://github.com/mholt/caddy/tree/master/dist/init/linux-systemd, following the instructions in the README there almost exactly (Debian does not require that one create the www-data user or groups, since they already exist). I customized the unit file to fix the path to the caddy binary (which is in /usr/local/sbin instead of /usr/local/bin), but otherwise left it unchanged. In terms of the Caddyfile, I did somewhat diverge.

My /etc/caddy/Caddyfile is simply:

import sites/*

Then, there is a directory /etc/caddy/sites, that contains additional Caddyfiles, which I named for the sites. The first thing I did was create a simple site setup with some static content to test Caddy. Since the machine had two names (test and kanban), test could contain the static test content.

So /etc/caddy/sites/test contains:

https://test.test.com http://test.test.com {
        root /srv/www/test/

You also need to open the http and https ports in Ferm. Add proto tcp dport (http https) ACCEPT; to /etc/ferm/ferm.conf near the line that says proto tcp dport ssh ACCEPT;, and do a service ferm restart.

After restarting the caddy service with service, anything in /srv/www/test would be served from test.test.com. Note that I have included an 'https' address also, this causes Caddy to automatically attempt to ask LetsEncrypt for a certificate - if you aren't making an internet addressable site I believe you must leave this out (but i haven't tested it).

Get the Kanboard code

As with many PHP project, this is simply checking out the code into a directory that will be served. In this case, I went to /srv/www, and git cloned https://github.com/kanboard/kanboard/.

Setup php-fpm

Since Kanboard is written in PHP, and Caddy supports PHP only indirectly through fastcgi, we need the PHP fast CGI application server thing. This is contained in the Debian package php7.3-fpm. Install this package, along with Kanboard's dependencies php7.3-sqlite3, php7.3-gd, php7.3-mbstring and php7.3-dom. If you want to allow in-browser installation of Kanboard plugins you also need php7.3-zip.

Once the panoply of php packages are procured, it's time to actually configure FPM. This is done by creating a file in /etc/php/7.3/fpm/pool.d/, which I called kanboard.conf and copied the contents from the default www.conf, so accepting most of the defaults and customizing for my application:

user = www-data
group = www-data
listen =
listen.owner = www-data
listen.group = www-data
listen.allowed_clients =
pm = dynamic
pm.max_children = 100
pm.start_servers = 6
pm.min_spare_servers = 3
pm.max_spare_servers = 12
access.log = /var/log/$pool.access.log
rlimit_files = 65536
chdir = /srv/www/kanboard
security.limit_extensions = .php .php3 .php4 .php5 .php7

In summary, it makes the fpm worker listen to port 9000 on localhost, and ups the worker counts. We now restart the the php7.3-fpm service with service.

Setup Kanboard in Caddy

The next step is setting up the Caddyfile for our new Kanboard, which I put in /etc/caddy/sites/kanboard and filled with thus:

https://kanban.test.com http://kanban.test.com {
        root /srv/www/kanboard/
        fastcgi / localhost:9000 php

This basically makes Caddy's magic php fastcgi defaults point at the path we checked the Kanboard code to, and use the FPM fastcgi interface on port 9000 to run the code. Now (after restarting Caddy) I can navigate to https://kanban.test.com/ and get to the Kanboard login page! The default login is admin with the password admin.

Now the rest is up to you, although one thing I learned is to enable in-system plugin installation, you need to copy the file config.default.php to config.php in the source directory, and set the PLUGIN_INSTALLER variable to true (in addition to installing the php7.3-zip package as noted above). Hit me up on mastodon if you have any questions or comments.