Skip to content

Caddy JWT Authentication

Beau Barker edited this page Nov 5, 2025 · 13 revisions

Authenticating in the API gateway means you can protect non-PostgREST endpoints — such as static files or custom services — using the same authentication as PostgREST.

Create a JWT Secret

Note

Caddy can share the JWT secret with PostgREST.

Generate a secret:

openssl rand -base64 32

Important

caddy-jwt requires the secret to be base64 encoded.

Put the secret in the environment file:

app/.env

# JWT secret used by both Caddy and PostgREST
JWT_SECRET=(your secret)

Add the secret and other settings to the Compose file:

app/compose.yaml

caddy:
  environment:
    JWT_SECRET: ${JWT_SECRET:?}


## Install caddy-jwt

Build Caddy with [caddy-jwt](https://github.com/ggicci/caddy-jwt), a Caddy
module that facilitates JWT authentication:

**app/caddy/Dockerfile**

```Dockerfile
FROM caddy:2-builder AS builder

RUN xcaddy build \
  --with github.com/ggicci/caddy-jwt@v1.1.0

FROM caddy:2

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

# Copy our Caddyfile into the image
COPY Caddyfile /etc/caddy/Caddyfile

Build the image:

docker compose build caddy

Caddyfile

Split your Caddyfile into sections, Public (no auth) and JWT, where a valid access token is required:

app/caddy/Caddyfile

{$CADDY_SITE_ADDRESS}

# --- Public ---

# PostgREST's public RPC endpoints
@auth {
  path /rpc/login /rpc/logout /rpc/refresh_token
}
handle @auth {
  reverse_proxy http://postgrest:3000
}

# PostgREST's OpenAPI endpoint
handle_path /rest/ {
  reverse_proxy http://postgrest:3000
}

# --- JWT Protected Routes ---

route {

  jwtauth {
    sign_key {env.JWT_SECRET}
    sign_alg HS256
    from_cookies access_token
    from_header Authorization
  }

  # .. Private endpoints ..

}

Restart Caddy for the changes to take effect:

docker compose up -d --force-recreate caddy

Clone this wiki locally