1. Caddy version (caddy version
): 2.5.1
2. How I run Caddy: Using a Docker container with caddy-security (latest versions)
a. System environment:
Ubuntu 20.04
Docker 20.10.16
Docker Compose 2.5.0
b. Command:
docker compose up -d
c. Service/unit/compose file:
(interpolation stuff is Ansible)
caddy:
build: "../../{{ app_dir }}/caddy"
container_name: caddy
ports:
- 80:80
- 443:443
volumes:
- "{{ app_dir }}/caddy/config:/config"
- "{{ app_dir }}/caddy/data:/data"
- "{{ app_dir }}/caddy/Caddyfile:/etc/caddy/Caddyfile"
- "{{ app_dir }}/caddy/auth:/auth"
environment:
- "DOMAIN={{ domain_name }}"
- CADDY_AUTH_USERS_PATH=/auth/users.json
restart: unless-stopped
d. My complete Caddyfile or JSON config:
$DOMAIN is redacted.stream
{
order authenticate before reverse_proxy
log
security {
local identity store localdb {
realm local
path {$CADDY_AUTH_USERS_PATH}
}
authentication portal myportal {
enable identity store localdb
cookie domain {$DOMAIN}
cookie lifetime 86400
crypto default token lifetime 43200
ui {
links {
"Sonarr" https://sonarr.{$DOMAIN} icon "las la-tv"
"Radarr" https://radarr.{$DOMAIN} icon "las la-film"
"Bazarr" https://bazarr.{$DOMAIN} icon "las la-closed-captioning"
"Deluge" https://deluge.{$DOMAIN} icon "las la-water"
"Prowlarr" https://prowlarr.{$DOMAIN} icon "las la-file-download"
"WUD" https://wud.{$DOMAIN} icon "las la-toolbox"
"Duplicati" https://duplicati.{$DOMAIN} icon "las la-copy"
"Portainer" https://portainer.{$DOMAIN} icon "lab la-docker"
"Overseerr" https://overseerr.{$DOMAIN} icon "las la-edit"
"Portal Settings" /settings icon "las la-cog"
}
}
}
authorization policy admin_policy {
set auth url https://{$DOMAIN}
allow roles authp/admin
acl rule {
comment allow admins
match role authp/admin
allow stop log info
}
acl rule {
comment default deny
match any
deny log warn
}
}
}
}
(protected_route) {
{args.0}.{$DOMAIN} {
route {
authorize with admin_policy
reverse_proxy {args.1}
}
}
}
(cors) {
@origin{args.0} header Origin {args.0}
header @origin{args.0} Access-Control-Allow-Origin "{args.0}"
header @origin{args.0} Access-Control-Allow-Headers "*"
header @origin{args.0} Vary Origin
header @origin{args.0} Access-Control-Allow-Methods "*"
header @origin{args.0} Access-Control-Allow-Credentials "true"
}
{$DOMAIN} {
route {
import cors https://sonarr.{$DOMAIN}
import cors https://radarr.{$DOMAIN}
import cors https://bazarr.{$DOMAIN}
import cors https://deluge.{$DOMAIN}
import cors https://prowlarr.{$DOMAIN}
import cors https://wud.{$DOMAIN}
import cors https://portainer.{$DOMAIN}
import cors https://duplicati.{$DOMAIN}
import cors https://overseer.{$DOMAIN}
@options method OPTIONS
handle @options {
respond 204
}
handle {
authenticate * with myportal
}
}
}
overseerr.{$DOMAIN} {
route {
reverse_proxy overseerr:5055
}
}
import protected_route duplicati duplicati:8200
import protected_route sonarr sonarr:8989
import protected_route radarr radarr:7878
import protected_route bazarr bazarr:6767
import protected_route deluge deluge:8112
import protected_route prowlarr prowlarr:9696
import protected_route wud wud:3000
import protected_route portainer portainer:9000
3. The problem I’m having:
As you can see I have all my apps behind Caddy. Using Caddy-Security (CS) I authenticate myself and I can access all of them no problem in HTTPS. One app is different though : Overseerr. I want it reverse proxied but NOT protected behind CS authentication. When I go to overseer.redacted.stream
I get SSL_ERROR_INTERNAL_ERROR_ALERT in my browser and you can see the logs below when that happens. If I first authenticate with CS though it goes through fine and I can access the app in HTTPS.
4. Error messages and/or full log output:
{"level":"debug","ts":1653244238.3464756,"logger":"tls.handshake","msg":"no matching certificates and no custom selection logic","identifier":"overseer.redacted.stream"}
{"level":"debug","ts":1653244238.3465316,"logger":"tls.handshake","msg":"no matching certificates and no custom selection logic","identifier":"*.redacted.stream"}
{"level":"debug","ts":1653244238.3465464,"logger":"tls.handshake","msg":"no matching certificates and no custom selection logic","identifier":"*.*.stream"}
{"level":"debug","ts":1653244238.3465593,"logger":"tls.handshake","msg":"no matching certificates and no custom selection logic","identifier":"*.*.*"}
{"level":"debug","ts":1653244238.3465748,"logger":"tls.handshake","msg":"all external certificate managers yielded no certificates and no errors","sni":"overseer.redacted.stream"}
{"level":"debug","ts":1653244238.3465924,"logger":"tls.handshake","msg":"no certificate matching TLS ClientHello","server_name":"overseer.redacted.stream","remote":"92.89.89.167:63044","identifier":"overseer.redacted.stream","cipher_suites":[4865,4867,4866,49195,49199,52393,52392,49196,49200,49162,49161,49171,49172,156,157,47,53],"cert_cache_fill":0.001,"load_if_necessary":true,"obtain_if_necessary":true,"on_demand":false}
{"level":"debug","ts":1653244238.3467653,"logger":"http.stdlib","msg":"http: TLS handshake error from 92.89.89.167:63044: no certificate available for 'overseer.redacted.stream'"}
5. What I already tried:
I did enable proxy support in Overseerr because apparently it’s needed. I tried replicating their Nginx config (see below) but to no avail. So I’m not sure if something’s wrong in CS or if I’m missing something.