Skip to content
Daniel Krol edited this page Dec 28, 2024 · 36 revisions

This is a WIP sorry for dust

Caddy is a web server written in Go. It is known for being simple to install, and has batteries included. It won't hurt to look over the documentiation but here I'm going to give us a "quick start" as it pertains to Sandstorm. I will say that while I did have frustrations in the process of figuring this out, it was less than with Nginx.

Batteries include very useful things like load balancing. That sounds like overkill but it's actually useful for us. They also include things like automatic HTTPS and Let's Encrypt, which are very cool but only get in our way for Sandstorm development, so we disable them.

Caddy is known for being "fast enough" but not quite as fast as Nginx. This is no problem for Sandstorm. Easy is what we're going for, even for developers.

Installation

You can install in setup.sh like Nginx:

apt install caddy
service caddy stop
systemctl disable caddy

If you want a more updated version, you can look at options here appropriate for build.sh or setup.sh.

Configuration

Caddyfile

For Sandstorm, we will configure Caddy with what's called a Caddyfile. (Other config options offered by Caddy include an admin json API [for some reason] and mere command line options for common use cases)

Here's a basic Caddyfile that works for Sandstorm:

# This is the "global options block". Certain options only belong here.
{
	# Caddy by default supports https (and even handles ACME certs). For our
	# purposes this is annoying at best.
	auto_https off

	# The admin API would let you edit this config over http (!) at localhost:2019
	# Sandstorm presumably wouldn't allow outside requests to hit it but who knows.
	admin off
}

# This is a "site block" which handles requests to port :8080 (See ":8080 questions" below)
:8080 {
	log {
		output stdout
		format json

		# If you want to log every request, remove this line or replace it with "level info"
		level error
	}

	# our app
	reverse_proxy :8081 {
		# See: https://caddyserver.com/docs/caddyfile/directives/reverse_proxy#load-balancing
		
		# If Caddy starts before our app does, we want it to stall any incoming
		# requests instead of returning an error. We can do this using Caddy's
		# built-in load balancer (this may be overkill but it's a very simple
		# solution).

		# Retry for up to 5 seconds if the app hasn't started yet.
		lb_try_duration 5s

		# By default lb_try_interval is .250. To match 5 seconds we want 20 retries.
		lb_retries 20
	}
}

Again, for your specific needs, you will likely want to consult the documentiation.

For this example, we will place the Caddyfile in the .sandstorm directory, but you can put it anywhere.

TODO: :8080 questions

A few things that I'm unsure of related to this (that I would like to sort out and remove from this doc)

  • It's not 100% clear to me why this is expecting http rather than https, but that is what we want and it's less verbose than http://:8080
  • If you put localhost:8080, the server will receive requests from Sandstorm, but the page does not show up in the browser
  • I hope omitting localhost is still safe.

launcher.sh

As with Nginx, we run the app on the port that Caddy expects. We run the app in the background and run caddy in the foreground.

However, unlike with Nginx, we have no need to have a retry loop to wait for the app to start before starting Caddy. Caddy's built-in load balancer does this job for us!

#!/bin/bash
set -euo pipefail

# App configs go here

# Set your app to work on port 8081. How it is done depends on your
# app of course, but in our example we'll pretend that it's an
# environmental variable.
export MY_APP_PORT=8081

cd /opt/app
my-app&

# Caddy saves certs and admin-API generated configs in the home
# directory. We don't care about either of these things.
FAKE_CADDY_HOME=/tmp/fake-caddy-home
mkdir $FAKE_CADDY_HOME

# Don't export the fake HOME; only apply it to caddy.
# By default caddy looks for `Caddyfile` in the current directory, but
# we are currently in /opt/app so we pass it in explicitly.
HOME=$FAKE_CADDY_HOME caddy run --config .sandstorm/Caddyfile

exit 0

Future ideas

Vagrant-SPK

If we decide that it's useful, we can update vagrant-spk to use this instead of Nginx.

Perhaps we'll want the Caddyfile in the service-configs directory, but unlike Nginx I don't think we'll need a separate mime.types file.

Turning off "persist"

One global option we could add is turning off "persisting" configs.

persist_config off

This appears to be unavailable in Debian Bookworm, but if you use a newer version it might be worth considering.

This setting would stop Caddy from wanting to save the admin API config to disk (see above). Since we use the "fake home" trick anyway, this would amount to one less log entry for us. Still if we could also stop Caddy from wanting to save the cert, perhaps we could do away with the "fake home" hack. Something to consider.

Clone this wiki locally