How to Use Caddy Server 2 — [BEGINNER]

austin w
4 min readMar 19, 2022

--

All I wanted to do was create a multi-tenant, wildcard domain site as a 4 month learner of programming. It turns out that this was no small task. However it was doable. Thanks to Ruby on Rails fantastic routing configurations, routing for wildcard subdomains, custom domains and a root domain — all in the same app was a breeze.

Just a few constraints and it’s done.

BUT, when I tried to list this app on Heroku I ran into a couple of issues. First, Heroku doesn’t give automatic TLS certs for wildcard subdomains. You must know the subdomain to issue one. For the user experience to be the smoothest, I need the fastest possible subdomain wildcard certs. This is when I found out about Caddy. Caddy Server is a lightweight and production ready reverse-proxy server that can be run inplace of nginx.

However getting up and running on Caddy wasn’t as easy as I would have liked. Having tried anything and everything from the forums it took a long three days to finally get the config right for my server with dynamic & proxied TLS certs from Cloudflare and a Digital Ocean droplet where I host my app.

I opted to install Caddy on my server straight away with XCaddy. This is basically required if you want and external hosting like Cloudflare or other providers. Because certificates for HTTPS only get listed if you pass certain challenges. In my particular case with Cloudflare, they needed a DNS challenge that required a Cloudflare api key. But to do that you need to install a very specific version of Caddy.

In the docs and in the forums there isn’t a clear tutorial on how to actually do this so I will write briefly below for my future self and others:

0. Make sure Go is installed (Caddy is written in Go) https://www.digitalocean.com/community/tutorials/how-to-install-go-on-ubuntu-18-04
Note: You must make sure to update to the latest version of Go, I couldn’t figure out why my Xcaddy builds were failing and had to update to the latest version.

1. Follow this guide to install Xcaddy https://www.digitalocean.com/community/tutorials/how-to-host-a-website-with-caddy-on-ubuntu-18-04
2. In your terminal now you can simply run xcaddy build — with github.com/caddy-dns/cloudflare
3. Now your build file is done, make sure to move it to the caddy directory it should be in /usr/bin
4. Now you can start creating your Caddyfile

Caddy server uses a config file just named ‘Caddyfile’ with no additional extensions. The syntax is pretty simple. You can immediately open a reverse proxy by listening to our localhost:5000 with `reverse_proxy localhost:5000`

Easy.

Within a few seconds I was up & running. Note: for Ruby on Rails users I used Passenger as my server for this app, but you could use Puma or something else as well.

Also, PS: I love Heroku. It’s awesome to get started on creating apps. If theres a good solution to wildcard https domains without spending $$$ on a wildcard certificate over at Cloudflare I would love to know.

Below is my Caddyfile config I used for wildcard certs AND custom domains all with https.

```Go
example.xyz {
reverse_proxy localhost:5000
log {
format json
}
}

http:// {
redir https://{host}{uri}
}

*.example.xyz {
tls {
dns cloudflare {env.CLOUDFLARE_AUTH_TOKEN}
}

reverse_proxy localhost:5000

log {
format json
}
}

https:// {
reverse_proxy localhost:5000

tls {
on_demand
}

}
```

This config is pretty self-explanatory. The only tip I think worth mentioning though is the http -> https redirect. This will make sure any traffic hitting my app is encrypted which is nice. I also make sure to but tls on demand under the https flag so that custom domains get approved. Wildcard domains are then handled via DNS challenge with a Cloudflare api token. You can store env variables in .bashrc so that your Caddyfile can access them.

Yea this could probably be simplified and DRYed up, but it gets the job done, makes sure all http traffic gets conerted to https and the tls on demand works perfectly for my needs. As my application scales I can choose to add an endpoint to check if I need to issue a TLS cert to even further secure the traffic.

So far I’ve had 0 issues with Caddy and it’s been really easy to configure thanks to the Caddyfile syntax.

The last step to this process was to add Caddy to the system services by creating a service file. There’s tons of tutorials on the web to do that but hadn’t found one that details Caddy Server 2 syntax for custom domains and wildcard.

Note: This whole article is written for Caddy Server 2, if you have Caddy Server 1 installed or look at older tutorials for Caddy Server 1 they might not work, so keep that in mind.

PS: It turns out Hashnode itself uses Caddy for this exact problem. Wildcard Subdomains. This is a great read to understand more about it: https://engineering.hashnode.com/after-4-years-with-nginx-we-switched-to-caddy-here-is-why

There’s tons more to do but hopefully this can help someone who was struggling with the same issues I was when creating a multi-tenacy app.

Cheers!

--

--