Caddy - zbrewer/homelab GitHub Wiki
Installation
Follow the install instructions on the Caddy website. The static binary method using the Cloudflare binary will be needed if a DNS ACME challenge with Cloudflare will be needed. The specific instructions for manual installation include steps to set up Caddy as a systemd service so it starts at boot.
Building with Xcaddy
Recently, the download for the static binary with the Cloudflare module hasn't been working. This affects not only fresh installs but also upgrades using the caddy upgrade
command. Fortunately, the Caddy binary can be easily built using the xcaddy tool instead.
Do this by installing the golang package (apt install golang
on Debian) and then following the xcaddy install instructions on Github.
Note, however, that if you are using the Cloudsmith repo instructions to install xcaddy you end up creating a .list
file defining the repository. This is fine on Ubuntu and Debian versions before 13 but Debian 13 and later use the deb822 format (.sources
) instead. The easiest way to make sure the new sources format is used (if the instructions have not been updated) is to run apt modernize-sources
after /etc/apt/sources.list.d/caddy-xcaddy.list
is created. This will create /etc/apt/sources.list.d/caddy-xcaddy.sources
and move /etc/apt/sources.list.d/caddy-xcaddy.list
to /etc/apt/sources.list.d/caddy-xcaddy.list.bak
(which can be deleted). Now you can run apt update
and apt install xcaddy
as per the instructions.
Once xcaddy has been installed, create a new directory for building Caddy (such as caddy-build
) and cd to that directory. Now run the following command to build Caddy with the Cloudflare module:
xcaddy build --with github.com/caddy-dns/cloudflare
The resulting caddy
binary can be checked with ./caddy version
and ./caddy list-modules
before being copied to /usr/bin/caddy
(per the normal install instructions).
Configuration
Changes made to the Caddyfile
can be applied by running systemctl reload caddy
. Cloudflare configuration instructions can be found on GitHub and general documentation can be found on the Caddy website. My specific config can be found here but the API key placeholder must be replaced by a valid Cloudflare API key before use.
Update
Run caddy upgrade
to update. Is building with xcaddy, run xcaddy build --with github.com/caddy-dns/cloudflare
to build a new version and replace the binary at /usr/bin/caddy
with the newly built version. Run systemctl restart caddy
to restart caddy using the new version.
Short Links
Short links let you type things like truenas/
in your browser URL bar in order to bring up your TrueNAS web interface.
Under the hood, this is http://truenas
and it needs to be able to resolve to a host through DNS. Because it isn't a FQDN (there is no domain part) this can't be done with a simple DNS override. Instead, one of a few different options has to be used. This could be a browser plugin, editing the hosts file of your computer, etc. but I chose to do this by specifying a DNS search suffix. This is a DHCP setting that tells clients on the network to try certain suffixes when making DNS queries if the DNS query could not initially be resolved. In other words, the client will make a DNS query for truenas
. When that can't be resolved, it will try truenas.brew.foo
, assuming that brew.foo
is configured as a search suffix. You can create a DNS A entry for truenas.brew.foo
so this will now resolve to the IP address it is supposed to.
OPNsense, which is what I use as my primary firewall and router, requires that you specify a domain name that is used for your network. This is then used as the primary DNS search suffix advertised by your DHCP servers (unless you specifically override this). This is what often lets you use hostname
in the URL bar to reach other local hosts. In my case, this is a different domain than the one I use for my reverse proxy/internal services in order to avoid name collisions. As a result, I need to be able to add to the list of DNS search suffixes advertised to clients. This can be done in your DHCP server by adding your desired domain to the Domain search list
(or a similarly named setting) in your DHCP config. Make sure that your clients are using DHCP (potentially with a reservation instead of a static IP) and re-connect them to make sure they receive this setting correctly. Once they do (and you have an appropriately configured A record) you can make sure the name is correctly resolved by using nslookup
from the command line. You can also use the chrome://net-internals/#dns
page in Chrome (use that as your URL) to check DNS resolution within the browser.
Note that some clients (such as Android) do not respect DNS search suffixes so you may need a workaround (like using a VPN) to support short links.
If you would like short links to work over a Wireguard tunnel (a potential solution for short links on Android), you need to specify the search suffix as part of the Wireguard config. This is done as a comma separated list after the DNS server address as part of the DNS parameter. In other words, this might look like:
DNS = 10.0.10.10, brew.foo, another-domain.example
Once the short links are resolving to the correct host, make sure that your firewall is configured to allow HTTP (not just HTTPS) traffic to your Caddy instance. This is important because initial requests to Caddy will take the form http://truenas
and therefore won't ever make it to Caddy if HTTP is not allowed.
At this point, you should be able to use the short link to hit Caddy but Caddy won't know what to do with it since the host is just truenas
(instead of truenas.brew.foo
). To address this, a host matcher needs to be added for the host truenas
that redirects to truenas.brew.foo
. This matcher should also match on HTTP (rather than trying to auto-redirect to HTTPS, the default Caddy behavior). See this forum thread for this solution. This looks like:
http://truenas {
redir https://truenas.brew.foo
}
The {host}
placeholder can also be used in the redirect statement and will be replaced by the hostname that matched. This allows you to handle multiple short links more compactly like in the following snippet:
http://truenas,
http://guacamole {
redir https://{host}.brew.foo
}
Finally, if you want the path to be maintained, you can use the {uri}
placeholder making this look like:
http://truenas,
http://guacamole {
redir https://{host}.brew.foo{uri}
}
This will ensure that things like truenas/ui/dashboard
will redirect to http://truenas.brew.foo/ui/dashboard
. This is particularly important when using short links with a URL shortener (a.k.a "go links" so that go/foo
can redirect to a preconfigured URL).
See my Caddyfile for an example of how I have this setup.