Skip to main content

Adding Single Sign On (SSO) to Caddy

·3 mins

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"
I realise that this is possibly risky in that it uses 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!


  1. 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 the go install command. ↩︎