1. The problem I’m having:
Sorry, I’m new to Caddy and Caddy Security, but I’m missing something.
My goal is to have a reverse proxy that redirects traffic to another Docker container where there is a web app. In the reverse proxy, I would like to implement simple authentication where registered users can log in, just to keep the site under control in terms of access.
I created a Caddy file by entering the portal and the policy, but I can never get it to accept me and it always tells me “token error, user role is valid, but not allowed by access list.”
I can’t figure it out. Can you help me?
2. Error messages and/or full log output:
This is the debug log file after reload configuration
```{"level":"info","ts":1760128566.7289324,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1760128566.7289743,"logger":"admin.api","msg":"load complete"}
{"level":"info","ts":1760128566.7573738,"logger":"admin","msg":"stopped previous server","address":"localhost:2019"}
{"level":"debug","ts":1760128582.1740208,"logger":"events","msg":"event","name":"tls_get_certificate","id":"ba029244-bc79-4d84-b86a-1843b95f7b40","origin":"tls","data":{"client_hello":{"CipherSuites":[4865,4867,4866,49195,49199,52393,52392,49196,49200,49162,49161,49171,49172,156,157,47,53],"ServerName":"my.app.it","SupportedCurves":[4588,29,23,24,25,256,257],"SupportedPoints":"AA==","SignatureSchemes":[1027,1283,1539,2052,2053,2054,1025,1281,1537,515,513],"SupportedProtos":["h2","http/1.1"],"SupportedVersions":[772,771],"RemoteAddr":{"IP":"0.0.0.0","Port":60990,"Zone":""},"LocalAddr":{"IP":"172.27.0.4","Port":443,"Zone":""}}}}
{"level":"debug","ts":1760128582.1742702,"logger":"tls.handshake","msg":"choosing certificate","identifier":"my.app.it","num_choices":1}
{"level":"debug","ts":1760128582.1742873,"logger":"tls.handshake","msg":"custom certificate selection results","identifier":"my.app.it","subjects":["my.app.it","www.my.app.it"],"managed":false,"issuer_key":"","hash":"HASHHASHHASHHASH"}
{"level":"debug","ts":1760128582.174303,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"0.0.0.0","remote_port":"60990","subjects":["my.app.it","www.my.app.it"],"managed":false,"expiration":1784876471,"hash":"HASHHASHHASHHASH"}
{"level":"debug","ts":1760128582.1878037,"logger":"security","msg":"Redirect served","session_id":"AAAAAAAAA","request_id":"17230e39-08fc-467f-9791-67c23c45b6f6","redirect_url":"https://my.app.it/login","status_code":302}
{"level":"debug","ts":1760128582.3505251,"logger":"security","msg":"static assets","session_id":"AAAAAAAAA","request_id":"c9ce13e3-b2e3-490d-a6de-d3f854f75a62","url_path":"/assets/google-webfonts/roboto.css","request":{"session_id":"AAAAAAAAA","base_url":"https://my.app.it","base_path":"/","content_type":"text/css,*/*;q=0.1"},"source_address":"0.0.0.0"}
{"level":"debug","ts":1760128582.3514946,"logger":"security","msg":"static assets","session_id":"AAAAAAAAA","request_id":"0df1e227-8cd8-4271-bbde-cb2099403fb1","url_path":"/assets/line-awesome/line-awesome.css","request":{"session_id":"AAAAAAAAA","base_url":"https://my.app.it","base_path":"/","content_type":"text/css,*/*;q=0.1"},"source_address":"0.0.0.0"}
{"level":"debug","ts":1760128582.3530962,"logger":"security","msg":"static assets","session_id":"AAAAAAAAA","request_id":"c6f46656-ff29-410b-bb6c-d6b2fc6f6382","url_path":"/assets/css/login.css","request":{"session_id":"AAAAAAAAA","base_url":"https://my.app.it","base_path":"/","content_type":"text/css,*/*;q=0.1"},"source_address":"0.0.0.0"}
{"level":"debug","ts":1760128582.3540547,"logger":"security","msg":"static assets","session_id":"AAAAAAAAA","request_id":"aff3ae97-33bf-4f4c-8dfd-b7d1aba59139","url_path":"/assets/images/logoUni.png","request":{"session_id":"AAAAAAAAA","base_url":"https://my.app.it","base_path":"/","content_type":"image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5"},"source_address":"0.0.0.0"}
{"level":"debug","ts":1760128582.3547368,"logger":"security","msg":"static assets","session_id":"AAAAAAAAA","request_id":"908cf26b-c87e-4262-9452-371ee09839d2","url_path":"/assets/js/login.js","request":{"session_id":"AAAAAAAAA","base_url":"https://my.app.it","base_path":"/","content_type":"*/*"},"source_address":"0.0.0.0"}
{"level":"debug","ts":1760128582.3996556,"logger":"security","msg":"static assets","session_id":"AAAAAAAAA","request_id":"bdacb532-16a3-47b3-beff-b8dd628a8c71","url_path":"/assets/google-webfonts/fonts/roboto-v20-latin-500.woff2","request":{"session_id":"AAAAAAAAA","base_url":"https://my.app.it","base_path":"/","content_type":"application/font-woff2;q=1.0,application/font-woff;q=0.9,*/*;q=0.8"},"source_address":"0.0.0.0"}
{"level":"debug","ts":1760128582.4013267,"logger":"security","msg":"static assets","session_id":"AAAAAAAAA","request_id":"da177e40-813c-4213-8332-c6954d4939bf","url_path":"/assets/google-webfonts/fonts/roboto-v20-latin-regular.woff2","request":{"session_id":"AAAAAAAAA","base_url":"https://my.app.it","base_path":"/","content_type":"application/font-woff2;q=1.0,application/font-woff;q=0.9,*/*;q=0.8"},"source_address":"0.0.0.0"}
{"level":"debug","ts":1760128582.403835,"logger":"security","msg":"static assets","session_id":"AAAAAAAAA","request_id":"4ba2d4c2-7ce2-49bf-9e3e-a8e98efe9181","url_path":"/assets/line-awesome/fonts/la-solid-900.woff2","request":{"session_id":"AAAAAAAAA","base_url":"https://my.app.it","base_path":"/","content_type":"application/font-woff2;q=1.0,application/font-woff;q=0.9,*/*;q=0.8"},"source_address":"0.0.0.0"}
{"level":"debug","ts":1760128582.4402635,"logger":"security","msg":"static assets","session_id":"AAAAAAAAA","request_id":"2ab3cdf8-dd3b-4908-bc08-3363fba8f7ed","url_path":"/assets/images/favicon.png","request":{"session_id":"AAAAAAAAA","base_url":"https://my.app.it","base_path":"/","content_type":"image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5"},"source_address":"0.0.0.0"}
{"level":"debug","ts":1760128602.681911,"logger":"security","msg":"user transformation ended","session_id":"AAAAAAAAA","request_id":"7f901c17-9a6f-4389-ae43-fba7eb5c94f3","user":{"addr":"0.0.0.0","email":"test@email.it","exp":1760128607,"iat":1760128602,"iss":"https://my.app.it/login","jti":"AAAAAAAAA","nbf":1760128542,"origin":"local","realm":"local","roles":["org/FirstUser","admin"],"sub":"Diego"}}
{"level":"debug","ts":1760128602.6914377,"logger":"security","msg":"user authorization sandbox","sandbox_id":"SANDBOXID","sandbox_secret":"SANDBOXSECRET","sandbox_partition":"","checkpoints":[{"name":"Authenticate with password","type":"password"}]}
{"level":"debug","ts":1760128602.691649,"logger":"security","msg":"next user authorization checkpoint","session_id":"AAAAAAAAA","request_id":"28b662a5-de45-46f5-8aab-3388f96876ff","data":{"action":"auth","title":"Authentication","view":"password_auth"}}
{"level":"debug","ts":1760128602.7369454,"logger":"security","msg":"static assets","session_id":"AAAAAAAAA","request_id":"6aca7ae9-d076-4a83-ac16-74539145ea5a","url_path":"/assets/google-webfonts/montserrat.css","request":{"session_id":"AAAAAAAAA","base_url":"https://my.app.it","base_path":"/","content_type":"text/css,*/*;q=0.1"},"source_address":"0.0.0.0"}
{"level":"debug","ts":1760128602.73774,"logger":"security","msg":"static assets","session_id":"AAAAAAAAA","request_id":"f3a321da-0cb7-43aa-8b1b-774ddcb1ad87","url_path":"/assets/css/sandbox.css","request":{"session_id":"AAAAAAAAA","base_url":"https://my.app.it","base_path":"/","content_type":"text/css,*/*;q=0.1"},"source_address":"0.0.0.0"}
{"level":"debug","ts":1760128602.7387612,"logger":"security","msg":"static assets","session_id":"AAAAAAAAA","request_id":"43987f97-8732-4d7a-8f20-68626b738782","url_path":"/assets/images/logo.svg","request":{"session_id":"AAAAAAAAA","base_url":"https://my.app.it","base_path":"/","content_type":"image/avif,image/webp,image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5"},"source_address":"0.0.0.0"}
{"level":"debug","ts":1760128602.739862,"logger":"security","msg":"static assets","session_id":"AAAAAAAAA","request_id":"8dc79d3d-cd2f-4cfd-879c-4a3e996e3184","url_path":"/assets/js/sandbox.js","request":{"session_id":"AAAAAAAAA","base_url":"https://my.app.it","base_path":"/","content_type":"*/*"},"source_address":"0.0.0.0"}
{"level":"debug","ts":1760128629.4147058,"logger":"security","msg":"user authorization sandbox","sandbox_id":"SANDBOXID","sandbox_secret":"SANDBOXSECRET","sandbox_partition":"password-auth","checkpoints":[{"name":"Authenticate with password","type":"password"}]}
{"level":"info","ts":1760128631.7633078,"logger":"security","msg":"user authorization checkpoint passed","session_id":"AAAAAAAAA","request_id":"2a2f6eed-620b-4b57-9c37-75c3b04a0f27","checkpoint_id":0,"checkpoint_name":"Authenticate with password","checkpoint_type":"password"}
{"level":"debug","ts":1760128631.763352,"logger":"security","msg":"next user authorization checkpoint","session_id":"AAAAAAAAA","request_id":"2a2f6eed-620b-4b57-9c37-75c3b04a0f27","data":{"view":"redirect"}}
{"level":"debug","ts":1760128631.7633955,"logger":"security","msg":"Redirect served","session_id":"AAAAAAAAA","request_id":"2a2f6eed-620b-4b57-9c37-75c3b04a0f27","redirect_url":"https://my.app.it/sandbox/SANDBOXID","status_code":303}
{"level":"debug","ts":1760128631.7750463,"logger":"security","msg":"user authorization sandbox","sandbox_id":"SANDBOXID","sandbox_secret":"SANDBOXSECRET","sandbox_partition":"","checkpoints":[{"name":"Authenticate with password","type":"password","passed":true}]}
{"level":"debug","ts":1760128631.775201,"logger":"security","msg":"next user authorization checkpoint","session_id":"AAAAAAAAA","request_id":"0ca1b1ca-39fb-4ef2-84fd-50349bc8e720","data":{"authorized":true}}
{"level":"info","ts":1760128631.7752187,"logger":"security","msg":"user passed all authorization checkpoints","session_id":"AAAAAAAAA","request_id":"0ca1b1ca-39fb-4ef2-84fd-50349bc8e720","checkpoints":[{"name":"Authenticate with password","type":"password","passed":true}]}
{"level":"debug","ts":1760128631.7845957,"logger":"security","msg":"token error","session_id":"AAAAAAAAA","request_id":"de308c90-a4ab-47ca-9118-14ffa856ee79","error":"user role is valid, but not allowed by access list"}
{"level":"debug","ts":1760128631.784669,"logger":"security","msg":"Redirect served","session_id":"AAAAAAAAA","request_id":"de308c90-a4ab-47ca-9118-14ffa856ee79","redirect_url":"https://my.app.it/login","status_code":302}```
3. Caddy version:
v2.10.2
4. How I installed and ran Caddy:
I use DockerFile and Docker compose
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
xcaddy build --with github.com/greenpau/caddy-security
FROM caddy:latest
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
USER 1000:1000
EXPOSE 80 443```
### a. System environment:
<!-- OS, architecture, relevant versions, systemd? Docker? etc. -->
Docker
### b. Command:
<!--
Commands are what you type into a terminal, i.e. the command you use to run Caddy.
Please read https://caddyserver.com/docs/running to understand the recommended commands to run Caddy, depending on your installation method.
-->
````bash
```docker compose up -d```
c. Service/unit/compose file:
```services:
db:
image: mariadb:latest
container_name: db_container
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${DB_NAME}
MYSQL_USER: ${DB_USER}
MYSQL_PASSWORD: ${DB_PASSWORD}
volumes:
- ./docker_vol/db_data:/var/lib/mysql
restart: unless-stopped
networks:
- app-net
app:
image: some_app_image:latest
container_name: docker_container_app
depends_on:
- db
expose:
- "80"
environment:
DB_TYPE: mysql
DB_HOST: db
DB_PORT: ${DB_PORT}
DB_USER: ${DB_USER}
DB_PASSWORD: ${DB_PASSWORD}
DB_NAME: ${DB_NAME}
ADMIN_USER: ${ADMIN_USER}
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
ADMIN_NAME: ${ADMIN_NAME}
ADMIN_EMAIL: ${ADMIN_EMAIL}
volumes:
- ./docker_vol/plugins:/var/www/html/plugins
- ./docker_vol/upload:/var/www/html/upload
- ./docker_vol/config:/var/www/html/application/config
restart: unless-stopped
networks:
- app-net
caddy:
build:
context: .
dockerfile: Dockerfile_Caddy
container_name: caddy_reverse_proxy
user: 1000:1000
cap_add:
- NET_BIND_SERVICE
ports:
- "80:80"
- "443:443"
volumes:
- ./docker_vol/caddy_config:/etc/caddy
- ./docker_vol/caddy_data:/data
- ./docker_vol/caddy_config/config:/config/caddy
depends_on:
- app
networks:
- app-net
restart: unless-stopped
networks:
app-net:
driver: bridge
```
d. My complete Caddy config:
```{
debug
log {
output stdout
format json
level DEBUG
}
security {
local identity store localdb {
realm local
path /etc/caddy/users.json
}
authentication portal survey_portal {
crypto default token lifetime 3600
crypto key sign-verify {env.JWT_SHARED_KEY}
enable identity store localdb
cookie domain my.app.it
ui {
links {
"Home" https://my.app.it/
}
}
transform user {
match realm local
action add role admin
}
}
authorization policy anonymous_access {
set auth url https://my.app.it/
crypto key verify {env.JWT_SHARED_KEY}
allow roles admin
}
}
}
https://my.app.it {
tls /etc/caddy/cert.crt /etc/caddy/cert.key
route {
authenticate with survey_portal
authorize with anonymous_access
reverse_proxy docker_container_app:80
}
log {
output file /data/access.log {
roll_size 10mb
roll_keep 5
roll_keep_for 720h
}
format json
}
header {
Strict-Transport-Security "max-age=31536000;"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
Referrer-Policy "no-referrer"
}
}
http://my.app.it{
redir https://my.app.it{uri}
}
:443 {
tls /etc/caddy/catchall.crt /etc/caddy/catchall.key
respond "Connessione HTTPS generica (SNI mancante o IP diretto)" 200
}
```