Caddy is a powerful, flexible web server that is able to automatically obtain and renew TLS certificates from Let's Encrypt; provide a secure, sensible TLS configuration by default; and provide a reverse proxy for other network services. It is noted for its simple configuration syntax. This page describes how to install Caddy on Ubuntu 18 and configure it as a reverse proxy for Kotori. These instructions should apply to any Linux version running systemd, as long as you can install Go v1.14 or newer on it.
Kotori is assumed to be installed and running.
Unfortunately, Caddy doesn't appear to be available to install as a .deb package in Ubuntu, so you'll need to build it from source. To do that, first install Go using snap install go –classic
. Once that's installed, use it to build xcaddy
, which you'll use to build Caddy itself. Run go get -u github.com/caddyserver/xcaddy/cmd/xcaddy
followed by go build -o /usr/local/bin/xcaddy github.com/caddyserver/xcaddy/cmd/xcaddy
.
Finally, build Caddy itself. If you aren't adding any plugins (such as for DNS validation), run xcaddy build –output /usr/bin/caddy
. If you're going to expose this system to the Internet, you won't need any plugins. If you're going to run this on a private network, you'll need to use DNS validation instead, and you'll need one of the plugins to do that. In that case, the build command would look like xcaddy build –output /usr/bin/caddy –with github.com/caddy-dns/cloudflare
(or whichever other plugin you'd chosen).
The remainder of the installation process follows the Caddy documentation, and assumes you're the root user.
Create a user and group for Caddy: groupadd –system caddy
, useradd –system –gid caddy –create-home –home-dir /var/lib/caddy –shell /usr/sbin/nologin –comment “Caddy web server” caddy
.
Download the systemd unit. Run wget -O /etc/systemd/system/caddy.service https://raw.githubusercontent.com/caddyserver/dist/master/init/caddy.service
.
Create a Caddyfile and set its ownership by running mkdir /etc/caddy
, touch /etc/caddy/Caddyfile
, and chown -R caddy:caddy /etc/caddy/
.
Then activate this unit by running systemctl daemon-reload
followed by systemctl enable caddy
.
Now that you have Caddy installed, you need to prepare a Caddyfile. This is Caddy's configuration file, the equivalent of Apache's httpd.conf or Nginx's nginx.conf–but much shorter, clearer, and simpler. Edit /etc/caddy/Caddyfile
using your preferred text editor, and consult the relevant section below for its contents and discussion.
If you just want to use Caddy to avoid needing to specify port 3000, the Caddyfile will be very simple:
*:80 { root * /usr/local/www/html file_server reverse_proxy localhost:3000 }
Save this, and you're ready to go.
If you intend your Kotori installation to be open to the public Internet, start with this example:
{ email [email protected] acme_ca https://acme-staging-v02.api.letsencrypt.org/directory } kotori.yourdomain.tld { root * /usr/local/www/html file_server reverse_proxy localhost:3000 }
The first block isn't strictly necessary, but it's a good idea to give Let's Encrypt your email address so you can be notified in the event your cert is about to expire–under normal circumstances you shouldn't get any traffic from this. The second directive tells Caddy to try to obtain your certificate from the staging server, rather than from Let's Encrypt's production servers. This is recommended in order to avoid running into the Let's Encrypt rate limits while testing things out. Once you're sure things are working properly, you can remove this line and run systemctl reload caddy
to obtain a trusted certificate.
I have Kotori running on my LAN, and don't intend to expose it to the public Internet, which means the Caddyfile above won't work. Instead, I tell Caddy to validate the certificate using DNS. I use Cloudflare for my DNS, and the instructions below will work without modification there. If you're using a different DNS host, you'll need to adjust things; consult the Caddy documentation for details. Your Caddyfile will look like this:
{ email [email protected] acme_ca https://acme-staging-v02.api.letsencrypt.org/directory } kotori.yourdomain.tld { tls { dns cloudflare long_api_token } root * /usr/local/www/html file_server reverse_proxy localhost:3000 }
You'll notice this is identical to the one above, with the addition of the tls
block. That block tells Caddy (1) to use DNS validation to obtain the certificate, (2) to use Cloudflare's DNS (which you'll need to have built into Caddy during the installation), and (3) what credential to use to authenticate to Cloudflare. Please note, for Cloudflare, this is an API Token, not an API Key. API tokens can be narrowly scoped, limiting the risk of their exposure. You'll need to create one through the Cloudflare interface. As above, this example uses the staging server to avoid exhausting the rate limits–you can remove that line once you're sure things are working properly.
Now that you've created the Caddyfile, start Caddy with systemctl start caddy
. You should now be able to browse to the hostname you've chosen–Caddy will redirect to HTTPS, obtain and maintain the certificate, and have a secure TLS configuration.