Adding Single Sign On (SSO) to Caddy
Table of Contents
I’d previously used Authelia to have SSO on my Traefik setup so was looking for something similar to this on Caddy. This led me to caddy-security and the associated https://authp.github.io, however nothing was very clear as to where to go with this. Fortunately I found this blog post which went a long way to explaining things!
Install #
Rather than messing about with any downloads, initially I simply swapped out the image:
line in my docker-compose.yml
:
# image: caddy:2
image: "ghcr.io/authp/authp:v1.0.1"
caddy:latest
, so doesn’t pin a specific version of Caddy. Copying the Dockerfile
from https://github.com/authp/authp/blob/main/Dockerfile and updating for your requirements could be a better option and one that I will investigate at a later date.
Running docker compose up -d --build caddy
pulled and built a new image, which I verified had the extra modules:
$ docker compose exec -w /etc/caddy caddy caddy list-modules
[...]
dns.providers.cloudflare
http.authentication.providers.authorizer
http.handlers.authenticator
http.handlers.trace
security
security.secrets.aws_secrets_manager
Non-standard modules: 6
I checked at this point that everything was still working.
Configuration #
Trying to keep things simple I wanted to just secure some sites for just me using a local user database. To start with I didn’t want any external authentications, signups or service listings, but these are all possible.
I started with adding the following to the global section of my Caddyfile
, just underneath the email
setting (shown here for completeness):
{
email example@example.com
order authenticate before respond
order authorize before reverse_proxy
security {
local identity store localdb {
realm local
path /etc/caddy/auth/local/users.json
}
authentication portal auth {
enable identity store localdb
cookie domain example.com
cookie lifetime 86400 # 24 hours in seconds
transform user {
match origin local
action add roll authp/user
}
}
authorization policy user_policy {
set auth url https://auth.example.com
allow rolls authp/user
}
}
}
(Update example.com
to your domain)
I reloaded caddy to check things were still working and to generate the local identity store and secrets:
$ docker compose exec -w /etc/caddy caddy caddy reload
Everything looked good and was still working.
$ sudo tree caddy
caddy
├── auth
│ └── local
│ └── users.json
└── Caddyfile
I then updated the users.json
to change the default user to my details and change the password hash appropriately.1
Finally I added the auth
endpoint and a test site to the Caddyfile
:
auth.example.com {
authenticate with myportal
}
test.example.com {
authorize with users_policy
root * /sites/test.example.com
file_server
}
Et volia! Navigating to my test site requires now requires me to log in via my SSO portal. 🎉
Changing Passwords #
I never worked this out in Authelia, but with one extra line in the transform user
section, a link is added for logged in users at your portal site to change their settings including their password:
ui link "Portal Settings" /settings icon "las la-cog"
Multi Factor Authentication (MFA) #
When I was running Authelia, I set up MFA using TOTP in my password manager, fortunately this is quite easy to add to Caddy!
After adding the Settings link as above, add a further line to the transform user
section:
require mfa
Reload Caddy and use the Settings page on the portal to add your MFA app. Thats it!
Final thoughts #
Now that I’ve got past the first barrier of the authp docs where the Getting Started section was a bit sparse, it seems pretty easy to get this working. Hopefully this write up will help others make this work!
Please go to this post on Mastodon to add any comments or suggestions!
-
I used the info from the authp site here: https://authp.github.io/docs/authenticate/local/password-management With the
bcrypt-cli
binary ending up at~/go/bin/bcrypt-cli
after using thego install
command. ↩︎