3.3 KiB

Simple Auth

This is a stateless forward-auth provider. I tested it with Caddy, but it should work fine with Traefik.

Theory of Operation

This issues cryptographically signed authentication tokens to the client. Some JavaScript stores the token in a cookie.

When a client presents an authentication token in a cookie, they are allowed in if the token was properly signed, and has not expired.

Authentication tokens consist of:

  • Username
  • Expiration date
  • Hashed Message Authentication Code (HMAC)

Simpleauth also works with HTTP Basic authentication.


Simpleauth needs two (2) files:

  • A secret key, to sign authentication tokens
  • A list of usernames and hashed passwords

Create secret key

This will use /dev/urandom to generate a 64-byte secret key.

SASECRET=/run/secrets/simpleauth.key  # Set to wherever you want your secret to live
dd if=/dev/urandom of=$SASECRET bs=1 count=64

Create password file

It's just a text file with hashed passwords. Each line is of the format username:password_hash

alias sacrypt="docker run --rm --entrypoint=/crypt"
SAPASSWD=/run/secrets/passwd   # Set to wherever you want your password file to live
: > $SAPASSWD                  # Reset password file
sacrypt user1 password1 >> $SAPASSWD
sacrypt user2 password2 >> $SAPASSWD
sacrypt user3 password3 >> $SAPASSWD

Start it

Turning this into the container orchestration system you prefer (Docker Swarm, Kubernetes, Docker Compose) is left as an exercise for the reader.

docker run \
  --name=simpleauth \
  --detach \
  --restart=always \
  --port 8080:8080 \
  --volume $SASECRET:/run/secrets/simpleauth.key:ro \
  --volume $SAPASSWD:/run/secrets/passwd:ro \

Make your web server use it


You'll want a forward-auth section like this: {
  forward_auth localhost:8080 {
    uri /
    copy_headers X-Simpleauth-Username
    header_down X-Simpleauth-Domain    # Set cookie for all of
  respond "Hello, friend!"

The copy_headers directive tells Caddy to pass Simpleauth's X-Simpleauth-Username header along in the HTTP request. If you are reverse proxying to some other app, it can look at this header to determine who's logged in.

header_down sets the X-Simpleauth-Domain header in HTTP responses. The only time a client would get an HTTP response is when it is not yet authenticated. The built-in JavaScript login page uses this header to set the cookie domain: this way, you can protect multiple sites within a single cookie


I need someone to send me equivalent traefik configuration, to include here.


I need someone to send me equivalent nginx configuration, to include here.

Why not some other thing?

The main reason is that I couldn't get the WebDAV client code to work with anything else I found.

  • Authelia - I like it, but I couldn't get WebDAV to work. Also, it used 4.8GB of RAM and wanted a Redis server.
  • Authentik - Didn't try it, looked too complicated.
  • Keycloak - Didn't try it, looked way too complicated.


  • Performance testing: somehow this takes more CPU than caddy?

Project Home

The canonical home for this project is