Add HTTPS to anything easily with Caddy


After @FLnelson noticed that HTTPS is not enabled when using a public IPv4 address with a custom domain in the WordPress solution from the Playground, I thought I’d share a quick guide on how to work around that in an easy way. Actually this method can be used pretty much anytime you want to augment some existing deployment or web service with HTTPS/SSL.

We’re going to use Caddy, since it’s essentially developed with an obsession for making HTTPS really easy. We’ll just layer Caddy as a reverse proxy on top of whatever existing web server is running. Caddy is so slick for this use case that we won’t even need a config file!

Installing Caddy

Alright, let’s get to it. While Caddy is getting included in the official Ubuntu repos for releases 23.04 and later, we’ll need to install it another way for earlier version of Ubuntu (and Debian, which our WordPress solution is based on). An easy way to do this is to add the repositories provided by Caddy.

Here’s a slightly modified version of the official install instructions, accounting for the fact that we’re already root and thus don’t need sudo. Connect to your instance using SSH and issue these commands:

apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf '' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf '' > /etc/apt/sources.list.d/caddy-stable.list
apt update
apt install caddy

Open port 443

Our WordPress solution image comes with the ufw firewall, and the HTTPS port, 443, is blocked from inbound traffic by default. To open it, just run:

ufw allow 443

Test run

Before making the permanent set up, we can do a test run to make sure Caddy will start up, obtain an SSL certificate, and enable HTTPS for our site. Like I said before, we don’t even need a configuration file, just invoke Caddy in reverse proxy mode like this (replacing the example URL with your site’s domain):

caddy reverse-proxy -r --from --to :80

This initiates a reverse proxy to port 80 on the local host. By default Caddy listens for incoming traffic on port 443 and handles everything needed for HTTPS. The -r flag here disables the default behavior of attempting to redirect all regular HTTP traffic on port 80 to HTTPS on 443. Since our web server is already listening on port 80 this part will fail. Since web browsers default to HTTPS anyway when it’s available, this isn’t a bit deal, but it is possible with a few more steps to get an HTTPS only setup with this approach.

You should see in the logs that it successfully obtains an SSL certificate, and after that you can try navigating to your site’s domain again to verify it’s working. Using a private window or adding https:// specifically might be necessary until your browser drops its cache.

When you’re satisfied that everything looks good, hit ctl-c to exit Caddy and we’ll proceed to making this persistent.

Manage with Zinit

Inside our solution images, zinit is usually included as the process manager, and that’s the case for the WordPress solution. By creating a configuration file for Caddy, we can instruct Zinit to start up Caddy automatically if our VM is ever rebooted.

I guess I lied about not needed a config file. Well, we didn’t need a Caddy config file anyway :slight_smile:

For this step we need to write a file. This solution image doesn’t come with much in the way of text editors, so install your favorite editor (or get clever with cat, if that’s up your alley):

apt install nano

Open the file for editing:

nano /etc/zinit/caddy.yaml

Insert these contents (fill your domain again):

exec: caddy reverse-proxy -r --from --to :80

Save the file and exit your editor. Now tell Zinit about the new file:

zinit monitor caddy

Zinit will start up Caddy immediately, restart it if it ever crashes, and start it up automatically after any reboots. Assuming you tested the Caddy invocation above and used the same form here, that should be all there is to it. If you have any issue though, here are some other Zinit commands that could be helpful:

# See status of all services (same as "zinit list")

# Get logs for a service
zinit log caddy

# Restart a service (to test configuration changes, for example)
zinit stop caddy
zinit start caddy

Wrapping up

Hope you liked this guide on how to use Caddy to add HTTPS very easily to an existing service. While some parts of this guide are specific to ThreeFold solutions, Caddy can be used in just about any environment with some tweaks to the steps shown.

Once you get Caddy running, everything relating to HTTPS/SSL will be handled automatically, including certificate renewal. You can now just sit back and enjoy encrypted communication with your web server :tropical_drink: