Basic Usage of Caddy
So what is caddy. Well it is, at the most basic level, a web server like nginx or httpd. Like other web servers, caddy can serve content, or it can intercept web traffic to serve other sites (this is the core feature of a reverse proxy).
Unlike other web servers, caddy has some nice features that make it more palatable as a host:
- Automatic SSL, whether you want to generate your own certs or use ACME servers
- very simple syntax for writing our configs. Most sites require a single directive.
- Based on go, a modern language with memory safety controls
- Sane defaults. By default caddy sets up sites securely and (usually) without any additional configuration
- A single, static binary. While our implementation will be docker focused, nothing is stopping you from installing caddy as a normal package or even as an executable on Windows.
Looking at the Environment
We are using a Fedora 37 server running as a docker host with relevant data in
/mnt/containers. We also have a web service (vaultwarden, but really it can be any web service) forwarded on port 8080.
vaultwarden is a bitwarden compatible password manager, designed to work automatically with bitwarden extensions.
This guide is representing the host using Visual Studio Code over SSH. You can read more on how that works here.
Awesome! Now how about our web service?
It’s working, but it’s being served on an IP and a port. Not ideal. It’s also not being served over HTTPS. Vaultwarden won’t even let you make an account without encryption (rightfully so):
Let’s fix that.
Routing by Hostname
Before we go any further, we need to stop using IP addresses and start using DNS. This allows us to leverage a reverse proxy to route based on the URL. The DNS hostname can be defined in:
- Your current computer’s host file (no)
- Your upstream router (sure)
- Your Domain/DNS provider (sure if you want to get publicly valid certificates)
If you use OpenWRT (for example), you can do so in the latest version under
- I am going to point my upstream router to route
warden.gurucomputing.comto my lab docker IP.
Creating a Caddy Config
Before we start up Caddy, we need to create a config. In caddy terms this uses a syntax called a Caddyfile.
You can read up more on the caddyfile syntax here
Getting started is easy.
- Create a folder called
caddy, a subfolder called
container-config, and a file called
Caddyfile(note the capitalization).
- Paste the following config
If that looks like it’s almost too simple, that’s just Caddyfiles for you. Very easy syntax
righto, let’s get the caddy service started.
- Place the following
We are using the
latest tag here for convenience. In production, you should pin the version of caddy you are using to prevent updates potentially introducing breaking changes.
If you are wondering what
label:disable does, it automatically sets SELinux folder permissions for volumes on a SELinux enabled distro, like fedora or centOS
- Bring it up with
docker-compose up -d
- If all goes well, you can now access your web service (vaultwarden) on your URL!
Alright, we’ve now managed to route a service by the URL (and potentially route many more services in the same fashion). However, we’re only halfway there. Let’s cover IP whitelisting, encryption, and leveraging docker networks in Advanced Usage of Caddy.