Skip to content

Instantly share code, notes, and snippets.

@EricZimmerman
Last active April 11, 2025 01:00
Show Gist options
  • Save EricZimmerman/3015b94ab027d0597e0e55e93f0466c3 to your computer and use it in GitHub Desktop.
Save EricZimmerman/3015b94ab027d0597e0e55e93f0466c3 to your computer and use it in GitHub Desktop.
Caddy and Authcrunch working example

After pulling everything together, I thought it would be a good idea to document what ended up working for me with the following setup:

  1. *darr apps
  2. Some 3d printers
  3. MobilRaker
  4. NZB360

This stack requires the following

  • Protecting the sites from unauthorized access
  • Allowing the usage of BASIC auth to get to the sites when not using a web browser (items 3 and 4 above)
  • Use cloudflare (free is fine) for your DNS, etc.

This is how i ended up making all this work. While Cloudflare would manage all the SSL, I have caddy pull SSL certificates too.

Caddy and Docker

  1. Install docker and get it working. I use dockge
  2. Create a new site for caddy with the following config:
services:
  caddy:
    container_name: caddy
    image: ghcr.io/authcrunch/authcrunch:latest
    restart: always
    environment:
      - ACME_EMAIL="<your email to use for domain stuff>"
      - CLOUDFLARE_API_TOKEN=<your cloudflare api token>
      - ACME_AGREE=true
      - JWT="<Some 32 char random string>"
    ports:
      - 80:80
      - 443:443
      - 443:443/udp
    volumes:
      - /data/Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
      - /<local path>/:/srv
volumes:
  caddy_data: null
  caddy_config: null
networks: {}

The /srv mapping is to serve static websites (see the Caddy config file later)

  1. Start up the docker instance and make sure nothing explodes
  2. Download and extract the latest from https://github.com/shoenig/bcrypt-tool/releases
  3. Usage
./bcrypt-tool hash SomeFunkyPassword 10
  1. Take the resulting string and save it for now. We will use it later where it says <bcryptpw> (including removing the <>)
  2. In my setup, my configs all live under /data, so create /data/Caddyfile and make it look like the following. Note that you can adjust the YourDefaultUser value to be whatever you want your username to be. If you jack this up, delete /data/CaddyUsers.json from the docker volume and restart the container to reset things.
{
        # debug
        acme_dns cloudflare {$CLOUDFLARE_API_TOKEN}
        email {$ACME_EMAIL}

        servers {
                trusted_proxies static 173.245.48.0/20 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 141.101.64.0/18 108.162.192.0/18 190.93.240.0/20 188.114.96.0/20 197.234.240.0/22 198.41.128.0/17 162.158.0.0/15 104.16.0.0/13 104.24.0.0/14 172.64.0.0/13 131.0.72.0/22 2400:cb00::/32 2606:4700::/32 2803:f800::/32 2405:b500::/32 2405:8100::/32 2a06:98c0::/29 2c0f:f248::/32
                client_ip_headers CF-Connecting-IP X-Forwarded-For
        }


# authcrunch security start

        order authenticate before respond
        order authorize before basicauth

        security {
                local identity store localdb {
                        realm local
                        path /data/CaddyUsers.json
                        user YourDefaultUser {
                                name DefaultUser
                                email [email protected]
                                password "bcrypt:10:<bcryptpw>" overwrite
                                roles authp/admin authp/user
                        }
                }

                authentication portal myportal {
                        #value is in seconds. This value is 3 months
                        crypto default token lifetime 7884000
                        crypto key sign-verify {$JWT}
                        enable identity store localdb
#                       enable identity provider github
                        cookie domain yourdomain.com
                        # If you want session only (ie when browser closes they are gone), comment out the line below.
                        # Keep cookie around for 3 months
                        cookie lifetime 7884000

                        # find other icons at https://icons8.com/line-awesome
                        ui {
                                links {
                                        "Sonarr" https://sonarr.yourdomain.com icon "las la-tv"
                                        "Radarr" https://radarr.yourdomain.com icon "las la-video"
                                        "Sabnzb" https://nzb.yourdomain.com icon "las la-cloud-download-alt"
                                        "Voron02" https://vtl.yourdomain.com icon "las la-bookmark"
                                }
                        }
                        transform user {
                                match origin local
                                action add role authp/user
                                ui link "My Identity" "/auth/whoami" icon "las la-id-badge"
                                ui link "My Profile" "/auth/profile/" icon "las la-user"
                        }

                }


                authorization policy users_policy {
                        #Allow basic and api key auth
                        with basic auth portal myportal realm local
                        with api key auth portal myportal realm local

                        #This url is set below. This is where Authcrunch will be
                        set auth url https://auth.yourdomain.com/
                        allow roles authp/admin authp/user
                        crypto key verify {$JWT}
                        acl rule {
                                comment allow users
                                match role authp/user
                                allow stop log info
                        }
                        acl rule {
                                comment default deny
                                match any
                                deny log warn
                        }
                }

        }
}

# this is the url for the authcrunch portal itself
auth.yourdomain.com {
        route {
                authenticate with myportal
        }
}


#authcrunch security end

#define all the hosts to protect

#Adjust this for your location of sonarr, or whatever else you need to reverse proxy
sonarr.yourdomain.com {
        route {
                authorize with users_policy
                reverse_proxy http://192.168.1.14:8989
        }
}

# here we see a static site, where the index.html or whatever is in a directory /<local path>/somehost.com
# We reference /srv because thats where /<local path>/ ends up on.
somehost.com {
        root * /srv/somehost.com
        encode gzip
        file_server {
                hide .git
        }

        log {
                output file /srv/somehost.com.log
        }

        header {
                ?Cache-Control "max-age=1800"
        }
}

somestaticsite.com {
        respond "Hello, World!"
}

#this site handles its own auth
plex.somedomain.com {
        reverse_proxy http://192.168.1.14:32400
}

  1. Restart Caddy and test things

Stand alone apps

For the apps that need to talk to these sites, but do not understand JWT tokens and all that, we have to do things a bit differently

For mobileRaker

  1. Add the url to your printer, https://voron.somewhere.com. This should obviously be one of the sites you set up in Caddy, like the sonarr.yourdomain.com example above
  2. Go to https://gchq.github.io/CyberChef and add the To Base64 recipe
  3. In the right box at the top, enter your username and password in the format username:password
  4. Note the resulting base64 encoded value in lower right
  5. In the Http-headers section, add a new header. Enter the following (do not include <> in the Value
  • Header: Authorization
  • Value: Basic <your base64 encoded info from step 4>
  1. Click Save in the header dialog
  2. Click Save in lower right

If it worked, you should see your printer's data

For NZB360

  1. Add a service, like Sonarr
  2. For the url, the format needs to include basic auth details. Example: https://user:[email protected]
  3. Enter the API key from your Sonarr instance
  4. Click Test Connection
  5. Optionally, set up Local connection handling

Repeat this for every other *arr or Sabnzb setup you have that is protected by Authcrunch.

Thats it! You should now be able to:

  1. Visit https://sonarr.somedomain.com and have Authcrunch redirect you to login, then redirect you back to Sonarr
  2. Use mobile apps that need basic auth
  3. ???
  4. Profit

You can also auth to your endpoints using an API key you can create in your Authcrunch profile, but theres some bugs as of 2025-03-31 that requires you to make sure your password is 72 characters long. When i tried it I ended up with a 66 character password. Add 8 random chars to the end and you should be able to save it.

You can then authenticate against the endpoint like this:

curl -H "X-Api-Key: <API_KEY>" -v https://app.yourdomain.com

Or any other method, where you pass a header value of

X-Api-Key and the api key <API_KEY> (do not include <> of course)

@EricZimmerman
Copy link
Author

authcrunch has cloudflare-dns included.

Current encryption mode: Full (strict)

all i have to do is add an entry in dns for say

demo.domain.com

in cloudflare, then add it in the caddy file

demo.domain.com {
respond "Hello, World!"
}

and then restart caddy. it then picks up the new host and does all the tls stuff

what errors are you getting?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment