1. Output of caddy version
:
v2.5.1 h1:bAWwslD1jNeCzDa+jDCNwb8M3UJ2tPa8UZFFzPVmGKs=
2. How I run Caddy:
a. System environment:
Custom Docker image:
FROM caddy:builder AS builder
RUN xcaddy build \
--with github.com/caddy-dns/cloudflare
FROM caddy:latest
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
b. Command:
docker compose up -d
c. Service/unit/compose file:
services:
caddy:
build:
context: ./
dockerfile: Dockerfile
container_name: caddy
restart: unless-stopped
ports:
- 80:80
- 443:443
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- data:/data
- config:/config
environment:
- PUID=1000
- PGID=1000
- CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN}
- SMTP_PASSWORD=${SMTP_PASSWORD}
- PERSONAL_EMAIL=${PERSONAL_EMAIL}
volumes:
data:
config:
log:
networks:
default:
name: reverse_proxy
external: true
reverse_proxy
is an external Docker network that I put my other Docker services on, so Caddy can reverse proxy them.
PeerTube Docker compose file:
services:
# You can comment this webserver section if you want to use another webserver/proxy or test PeerTube in local
peertube:
image: chocobozzz/peertube:production-bullseye
container_name: peertube
hostname: peertube
env_file:
- .env
volumes:
- assets:/app/client/dist
- data:/data
- config:/config
depends_on:
- postgres
- redis
networks:
- default
- proxy
restart: "always"
postgres:
image: postgres:13-alpine
container_name: peertube-db
hostname: peertube-db
env_file:
- .env
volumes:
- db:/var/lib/postgresql/data
networks:
- default
restart: "always"
redis:
image: redis:6-alpine
container_name: peertube-redis
volumes:
- redis:/data
networks:
- default
restart: "always"
volumes:
data:
config:
assets:
db:
redis:
networks:
default:
proxy:
name: reverse_proxy
external: true
PeerTube .env
file:
# Database / Postgres service configuration
POSTGRES_USER=peertube
POSTGRES_PASSWORD=[REDACTED]
# Postgres database name "peertube"
POSTGRES_DB=peertube
# Editable only with a suffix :
#POSTGRES_DB=peertube_prod
#PEERTUBE_DB_SUFFIX=_prod
PEERTUBE_DB_USERNAME=peertube
PEERTUBE_DB_PASSWORD=[REDACTED]
PEERTUBE_DB_SSL=false
# Default to Postgres service name "postgres" in docker-compose.yml
PEERTUBE_DB_HOSTNAME=peertube-db
# PeerTube server configuration
# If you test PeerTube in local: use "peertube.localhost" and add this domain to your host file resolving on 127.0.0.1
PEERTUBE_WEBSERVER_HOSTNAME=haddock.cc
# If you just want to test PeerTube on local
#PEERTUBE_WEBSERVER_PORT=9000
#PEERTUBE_WEBSERVER_HTTPS=false
# If you need more than one IP as trust_proxy
# pass them as a comma separated array:
PEERTUBE_TRUST_PROXY=["127.0.0.1", "loopback", "172.18.0.0/16"]
# E-mail configuration
# If you use a Custom SMTP server
PEERTUBE_SMTP_USERNAME=apikey
PEERTUBE_SMTP_PASSWORD=[REDACTED]
# Default to Postfix service name "postfix" in docker-compose.yml
# May be the hostname of your Custom SMTP server
PEERTUBE_SMTP_HOSTNAME=smtp.sendgrid.net
PEERTUBE_SMTP_PORT=587
PEERTUBE_SMTP_FROM=noreply@haddock.cc
PEERTUBE_SMTP_TLS=false
PEERTUBE_SMTP_DISABLE_STARTTLS=false
PEERTUBE_ADMIN_EMAIL=[REDACTED]
# /!\ Prefer to use the PeerTube admin interface to set the following configurations /!\
#PEERTUBE_SIGNUP_ENABLED=true
#PEERTUBE_TRANSCODING_ENABLED=true
#PEERTUBE_CONTACT_FORM_ENABLED=true
d. My complete Caddy config:
(auth) {
forward_auth authelia:9091 {
uri /api/verify?rd=https://auth.haddock.cc
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
}
}
{ # Global configuration
acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}
email {env.PERSONAL_EMAIL}
}
auth.haddock.cc { # Auth portal
reverse_proxy authelia:9091
}
cloud.haddock.cc {
# import auth
encode zstd
reverse_proxy nextcloud:80 {
header_down Strict-Transport-Security "max-age=15552000; includeSubDomains"
header_down X-Content-Type-Options "nosniff"
header_down X-XSS-Protection "1; mode=block"
header_down X-Robots-Tag "none"
header_down X-Frame-Options "SAMEORIGIN"
header_down Referrer-Policy "no-referrer"
}
rewrite /.well-known/carddav /remote.php/dav
rewrite /.well-known/caldav /remote.php/dav
}
media.haddock.cc {
# authorize with mypolicy
reverse_proxy jellyfin:8096
}
photos.haddock.cc {
import auth
reverse_proxy photoprism:2342
}
prowl.haddock.cc { # Prowlarr
import auth
reverse_proxy prowlarr:9696
}
tv.haddock.cc { # Sonarr
import auth
reverse_proxy sonarr:8989
}
movies.haddock.cc { # Radarr
import auth
reverse_proxy radarr:7878
}
books.haddock.cc { # Readarr
import auth
reverse_proxy readarr:8787
}
guard.haddock.cc { # AdGuard Home
import auth
reverse_proxy adguard:80
}
cctv.haddock.cc { # Frigate
import auth
reverse_proxy frigate:5000
}
tube.haddock.cc { # PeerTube
reverse_proxy peertube:9000
}
localhost:8112 { # QBittorrent
reverse_proxy torrent:8080
}
3. The problem I’m having:
When I go to https://tube.haddock.cc, I get a box in the bottom left corner that says
Cannot retrieve OAuth Client credentials: undefined. Ensure you have correctly configured PeerTube (config/ directory), in particular the “webserver” section.
I also can’t login. When I try, I get this error in the PeerTube log:
[haddock.cc:443] 2022-09-29 18:28:02.601 error: Client log: Backend returned code 400, errorMessage is: Invalid client: client is invalid {
"userAgent": "Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0",
"url": "https://tube.haddock.cc/login"
}
4. Error messages and/or full log output:
The Caddy log made this post go way over the character limit, but here’s the part from when I get the error in PeerTube:
{"level":"debug","ts":1664477193.3474128,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"peertube:9000","duration":0.005960314,"request":{"remote_ip":"172.71.150.44","remote_port":"30510","proto":"HTTP/2.0","method":"POST","host":"tube.haddock.cc","uri":"/api/v1/server/logs/client","headers":{"Referer":["https://tube.haddock.cc/"],"Origin":["https://tube.haddock.cc"],"Accept-Encoding":["gzip"],"Cf-Ray":["7526e1da4b58c381-SEA"],"Accept-Language":["en-US,en;q=0.5"],"Content-Type":["application/json"],"Sec-Fetch-Site":["same-origin"],"Accept":["application/json"],"X-Forwarded-Host":["tube.haddock.cc"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-Proto":["https"],"Cf-Ipcountry":["US"],"X-Forwarded-For":["172.71.150.44"],"Content-Length":["316"],"Cookie":[],"Cf-Connecting-Ip":["63.231.52.232"],"Cf-Visitor":["{\"scheme\":\"https\"}"],"Cdn-Loop":["cloudflare"],"User-Agent":["Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0"],"Sec-Fetch-Mode":["cors"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"tube.haddock.cc"}},"headers":{"Access-Control-Expose-Headers":["Retry-After"],"X-Ratelimit-Limit":["10"],"Date":["Thu, 29 Sep 2022 18:46:33 GMT"],"X-Ratelimit-Reset":["1664477218"],"Etag":["W/\"2a-UpTsLJ74nYuiLgNgEwlQMxGqwrE\""],"Connection":["keep-alive"],"X-Frame-Options":["DENY"],"Tk":["N"],"Access-Control-Allow-Origin":["*"],"X-Ratelimit-Remaining":["0"],"Content-Length":["42"],"Retry-After":["600"],"Content-Type":["text/html; charset=utf-8"],"Access-Control-Allow-Credentials":["true"],"Keep-Alive":["timeout=5"]},"status":429}
{"level":"debug","ts":1664477193.3513138,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"peertube:9000","duration":0.007514071,"request":{"remote_ip":"172.71.150.44","remote_port":"30196","proto":"HTTP/2.0","method":"POST","host":"tube.haddock.cc","uri":"/api/v1/server/logs/client","headers":{"Sec-Fetch-Mode":["cors"],"X-Forwarded-Host":["tube.haddock.cc"],"Cookie":[],"User-Agent":["Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0"],"Content-Length":["251"],"Origin":["https://tube.haddock.cc"],"Content-Type":["application/json"],"Cf-Visitor":["{\"scheme\":\"https\"}"],"Referer":["https://tube.haddock.cc/"],"X-Forwarded-For":["172.71.150.44"],"Sec-Fetch-Dest":["empty"],"Cf-Connecting-Ip":["63.231.52.232"],"X-Forwarded-Proto":["https"],"Accept-Encoding":["gzip"],"Accept":["application/json"],"Cdn-Loop":["cloudflare"],"Cf-Ipcountry":["US"],"Accept-Language":["en-US,en;q=0.5"],"Sec-Fetch-Site":["same-origin"],"Cf-Ray":["7526e1da4b55c381-SEA"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"tube.haddock.cc"}},"headers":{"Access-Control-Allow-Credentials":["true"],"X-Ratelimit-Limit":["10"],"Retry-After":["600"],"Etag":["W/\"2a-UpTsLJ74nYuiLgNgEwlQMxGqwrE\""],"Connection":["keep-alive"],"X-Frame-Options":["DENY"],"Access-Control-Expose-Headers":["Retry-After"],"Tk":["N"],"Access-Control-Allow-Origin":["*"],"X-Ratelimit-Remaining":["0"],"X-Ratelimit-Reset":["1664477218"],"Content-Type":["text/html; charset=utf-8"],"Date":["Thu, 29 Sep 2022 18:46:33 GMT"],"Content-Length":["42"],"Keep-Alive":["timeout=5"]},"status":429}
{"level":"debug","ts":1664477193.3910909,"logger":"http.handlers.reverse_proxy","msg":"upstream roundtrip","upstream":"peertube:9000","duration":0.046735959,"request":{"remote_ip":"172.71.150.44","remote_port":"30504","proto":"HTTP/2.0","method":"GET","host":"tube.haddock.cc","uri":"/api/v1/videos?start=0&count=25&sort=-trending&skipCount=true&nsfw=false","headers":{"Sec-Fetch-Mode":["cors"],"Cf-Ray":["7526e1da5b65c381-SEA"],"Accept":["application/json, text/plain, */*"],"Sec-Fetch-Dest":["empty"],"X-Forwarded-For":["172.71.150.44"],"Referer":["https://tube.haddock.cc/"],"Cdn-Loop":["cloudflare"],"Accept-Encoding":["gzip"],"Cf-Connecting-Ip":["63.231.52.232"],"Accept-Language":["en-US,en;q=0.5"],"Cf-Ipcountry":["US"],"Cf-Visitor":["{\"scheme\":\"https\"}"],"If-None-Match":["0.760705541650023"],"Cookie":[],"X-Forwarded-Proto":["https"],"Sec-Fetch-Site":["same-origin"],"User-Agent":["Mozilla/5.0 (X11; Linux x86_64; rv:105.0) Gecko/20100101 Firefox/105.0"],"X-Forwarded-Host":["tube.haddock.cc"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"tube.haddock.cc"}},"headers":{"Tk":["N"],"Keep-Alive":["timeout=5"],"X-Frame-Options":["DENY"],"Access-Control-Allow-Origin":["*"],"Access-Control-Allow-Credentials":["true"],"Date":["Thu, 29 Sep 2022 18:46:33 GMT"],"X-Ratelimit-Reset":["1664477198"],"Content-Length":["11"],"X-Ratelimit-Limit":["50"],"Content-Type":["application/json; charset=utf-8"],"Etag":["W/\"b-EFAlOux7Kcr/ZEgGkn2r+oFAbu4\""],"Connection":["keep-alive"],"Access-Control-Expose-Headers":["Retry-After"],"X-Ratelimit-Remaining":["43"]},"status":200}
5. What I already tried:
This seems to be an issue other people have if they don’t use the included nginx webserver for PeerTube. This person had a similar problem, but they were using Apache. Their fix was using
ProxyPreserveHost On
ProxyRequests On
I tried finding an equivalent in Caddy, to no avail. That’s the reason I’m posting this here, instead of the PeerTube forum.