Ideally, a single Caddyfile could handle the following use cases without relying on different files for development and production:
- When running locally, develop using the
localhost
hostname without having to provision certificates. - When running in production, automatically provision TLS certificates for the appropriate hostnames.
- Redirect
www
to non-www
or vice versa.
Using an environment variable in the site address allows Caddy to support all of these use cases with a single Caddyfile.
{$SITE_HOSTNAME:localhost:80} {
# bind allows access to containers from host when running Caddy in Docker
bind 0.0.0.0
respond "Hello, world!"
}
# Handle redirects from www to non-www
www.{$SITE_HOSTNAME:localhost:80} {
# bind allows access to containers from host when running Caddy in Docker
bind 0.0.0.0
redir {scheme}://{$SITE_HOSTNAME:localhost:80}{uri}
}
During development, no value is needed for the $SITE_HOSTNAME
environment variable: it will default to localhost:80
. Because the default http
port :80
is specified, Caddy will serve the site strictly over http
without attempting to provision a certificate.
In production, the $SITE_HOSTNAME
environment variable should be set to the appropriate domain (example: yoursite.com
). Caddy will then automatically provision the TLS certificates, allowing you to run the same Caddyfile in both development and production.
The {scheme}
placeholder will ensure that if the request used http
(like http://www.locahost
), it will redirect to its non-www
counterpart with the correct scheme.
If you instead wanted to redirect from non-www
to www
, you could use the following configuration.
www.{$SITE_HOSTNAME:localhost:80} {
# bind allows access to containers from host when running Caddy in Docker
bind 0.0.0.0
respond "Hello, world!"
}
# Handle redirects from non-www to www
{$SITE_HOSTNAME:localhost:80} {
# bind allows access to containers from host when running Caddy in Docker
bind 0.0.0.0
redir {scheme}://www.{$SITE_HOSTNAME:localhost:80}{uri}
}
Gotchas
There are a few things you need to watch out for if you use this configuration.
The www
to non-www
redirect won’t work correctly if you’re mapping to a different port on the host when running inside a container. If Caddy is running on port :80
in a container but it is mapped to :8080
on the host, the example above would redirect http://www.localhost:8080
to http://localhost:80
. This is because Docker maps the host port :8080
to :80
before Caddy ever sees it, so inside the container Caddy is actually redirecting http://www.localhost:80
to http://localhost:80
.
You can’t use the environment variable $HOSTNAME
if you’re running inside of a Docker container. The Caddy container already has an environment variable called $HOSTNAME
, and it cannot be overwritten.
Testing the www.localhost
redirect may require changes to your computer’s hosts
file. The www.localhost
address worked fine on my MacBook with no additional configuration, but your mileage may vary.