1. My Caddy version (caddy version
):
Docker image caddy/caddy:alpine (2.0.0-beta.17)
2. How I run Caddy:
With Docker Compose.
a. System environment:
Ubuntu 18.04
Docker 19.03.8
docker-compose version 1.25.4
b. Command:
None, the Docker image as is.
c. Service/unit/compose file:
.env file:
GHOST=itsallsotireso.me
ISSO=marginalia.itsallsotireso.me
SHAARLI=normco.re
DEFAULT_NETWORK=firefly
Caddy docker-compose.yml:
version: "3.7"
services:
caddy:
container_name: caddy
image: caddy/caddy:alpine
restart: always
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./config:/config/caddy
- ./data:/data/caddy
ports:
- "80:80"
- "443:443"
environment:
- GHOST
- ISSO
- SHAARLI
networks:
default:
external:
name: $DEFAULT_NETWORK
Ghost docker-compose.yml:
version: "3.7"
services:
ghost:
container_name: ghost
image: ghost:alpine
restart: always
volumes:
- ./content:/var/lib/ghost/content
environment:
url: https://itsallsotireso.me
networks:
default:
external:
name: firefly
d. My complete Caddyfile or JSON config:
{
http_port 80
https_port 443
experimental_http3
debug
}
{$GHOST} {
reverse_proxy http://ghost:2368
}
{$ISSO} {
reverse_proxy http://isso:8080
}
{$SHAARLI} {
reverse_proxy http://shaarli:80
}
3. The problem Iâm having:
First of all, I am very new to Caddy (this is why my Caddyfile is very minimalist for now). I am still in a learning phase, and the v2 documentation is a bit tedious for me (I learnt Traefik v2 from scratch faster, imho) but I am really excited by all the Caddy features.
I used to run a Ghost blog in Docker alongside a couple of accessory services with nginx and acmesh (for the certificates), then with Traefik.
While randomly browsing though r/selfhosted at Reddit, I came across a few posts of Matt Holt defending Caddy v2 and he was very passionate and pretty convincing. Convincing enough to make me want to experiment Caddy on my VPS. In the near future, I would like to publish a few static files. I cannot do that with Traefik and I do not want to stack tons of services if one like Caddy can do everything I need.
Sorry for the off topic. Now back to my actual issue. It is pretty simple: when I access my Ghost url in a brower, it gets into an infinite loop of 301 redirects and it ends with a too many redirects error.
Which is weird to me, because this is the first time I encounter this issue, I have always managed to run Ghost either with nginx or Traefik with minimal config.
Thank you in advance for your kind help!
4. Error messages and/or full log output:
I have dozen of logs like that in a very short span:
caddy | 2020/03/15 16:07:08.919 DEBUG http.handlers.reverse_proxy upstream roundtrip {"request": {"method": "GET", "uri": "/", "proto": "HTTP/2.0", "remote_addr": "172.19.0.1:50194", "host": "itsallsotireso.me", "headers": {"Sec-Fetch-Site": ["none"], "Sec-Fetch-Mode": ["navigate"], "Accept-Encoding": ["gzip, deflate, br"], "X-Forwarded-For": ["172.19.0.1"], "Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"], "Sec-Fetch-User": ["?1"], "Accept-Language": ["fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,pt;q=0.6,es;q=0.5,pt-PT;q=0.4,it;q=0.3"], "Cache-Control": ["max-age=0"], "Upgrade-Insecure-Requests": ["1"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"], "Sec-Fetch-Dest": ["document"]}, "tls": {"resumed": false, "version": 772, "ciphersuite": 4865, "proto": "h2", "proto_mutual": true, "server_name": "itsallsotireso.me"}}, "headers": {"Cache-Control": ["public, max-age=31536000"], "Location": ["https://itsallsotireso.me/"], "Vary": ["Accept, Accept-Encoding"], "Content-Type": ["text/html; charset=utf-8"], "Content-Length": ["108"], "Date": ["Sun, 15 Mar 2020 16:07:08 GMT"], "Connection": ["keep-alive"], "X-Powered-By": ["Express"]}, "duration": 0.001513961, "status": 301}
5. What I already tried:
First thing I did was to remove the environment variable url: https://itsallsotireso.me from my Ghost docker-compose.yml. This is not a valid solution because then most of my internal links in Ghost became localhost:2368 instead of the actual URL. You can imagine this is not a very practical experience for visitors haha.
Then I googled, and I found out an old post (link below) about a similar issue.
After I had finished the Ghost Blog (https://ghost.org/) HTTPS setup on my server, an infinite redirection loop which prevented the blog from being displayed.
So I tried to transpose his solution into my Caddy context and I changed the initial Caddyfile to:
{$GHOST} {
reverse_proxy ghost:2368
header {
Strict-Transport-Security max-age=31536000; includeSubDomains; preload
Host {http.request.host}
X-Forwarded-Proto {http.request.scheme}
X-Forwarded-For {http.request.remote}
X-Real-IP {http.request.remote}
}
Now I do not have the infinite 301 loop anymore but I get a 502 error:
caddy | 2020/03/15 17:38:13.400 ERROR http.log.error dial tcp: lookup ghost on 127.0.0.11:53: no such host {"request": {"method": "GET", "uri": "/", "proto": "HTTP/2.0", "remote_addr": "172.19.0.1:50256", "host": "itsallsotireso.me", "headers": {"Cache-Control": ["max-age=0"], "Sec-Fetch-Site": ["cross-site"], "Sec-Fetch-User": ["?1"], "Accept-Encoding": ["gzip, deflate, br"], "Accept-Language": ["fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,pt;q=0.6,es;q=0.5,pt-PT;q=0.4,it;q=0.3"], "Upgrade-Insecure-Requests": ["1"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"], "Sec-Fetch-Dest": ["document"], "Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"], "Sec-Fetch-Mode": ["navigate"]}, "tls": {"resumed": false, "version": 772, "ciphersuite": 4865, "proto": "h2", "proto_mutual": true, "server_name": "itsallsotireso.me"}}, "status": 502, "err_id": "5ccqgm5m5", "err_trace": "reverseproxy.(*Handler).ServeHTTP (reverseproxy.go:363)"}
Additional remarks:
Regarding the other services, Isso is OK:
caddy | 2020/03/15 17:48:51.802 DEBUG http.handlers.reverse_proxy upstream roundtrip {"request": {"method": "GET", "uri": "/admin", "proto": "HTTP/2.0", "remote_addr": "172.19.0.1:50282", "host": "marginalia.itsallsotireso.me", "headers": {"Sec-Fetch-Dest": ["document"], "Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"], "Sec-Fetch-Site": ["none"], "Sec-Fetch-Mode": ["navigate"], "Accept-Encoding": ["gzip, deflate, br"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"], "Sec-Fetch-User": ["?1"], "Accept-Language": ["fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,pt;q=0.6,es;q=0.5,pt-PT;q=0.4,it;q=0.3"], "X-Forwarded-For": ["172.19.0.1"], "Upgrade-Insecure-Requests": ["1"]}, "tls": {"resumed": false, "version": 772, "ciphersuite": 4865, "proto": "h2", "proto_mutual": true, "server_name": "marginalia.itsallsotireso.me"}}, "headers": {"Access-Control-Allow-Credentials": ["true"], "Access-Control-Allow-Methods": ["HEAD, GET, POST, PUT, DELETE"], "Access-Control-Expose-Headers": ["X-Set-Cookie, Date"], "Server": ["gunicorn/20.0.4"], "Content-Type": ["text/html; charset=utf-8"], "Access-Control-Allow-Origin": ["https://itsallsotireso.me"], "Access-Control-Allow-Headers": ["Origin, Referer, Content-Type"], "Date": ["Sun, 15 Mar 2020 17:48:51 GMT"], "Connection": ["keep-alive"], "Content-Length": ["881"]}, "duration": 0.023124365, "status": 200}
caddy | 2020/03/15 17:48:51.947 DEBUG http.handlers.reverse_proxy upstream roundtrip {"request": {"method": "GET", "uri": "/img/isso.svg", "proto": "HTTP/2.0", "remote_addr": "172.19.0.1:50282", "host": "marginalia.itsallsotireso.me", "headers": {"If-Modified-Since": ["Thu, 04 Oct 2018 04:30:14 GMT"], "Accept": ["image/webp,image/apng,image/*,*/*;q=0.8"], "Accept-Encoding": ["gzip, deflate, br"], "If-None-Match": ["\"wzsdm-1538627414-11600-246809405\""], "Accept-Language": ["fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,pt;q=0.6,es;q=0.5,pt-PT;q=0.4,it;q=0.3"], "X-Forwarded-For": ["172.19.0.1"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"], "Sec-Fetch-Site": ["cross-site"], "Sec-Fetch-Mode": ["no-cors"]}, "tls": {"resumed": false, "version": 772, "ciphersuite": 4865, "proto": "h2", "proto_mutual": true, "server_name": "marginalia.itsallsotireso.me"}}, "headers": {"Access-Control-Allow-Origin": ["https://itsallsotireso.me"], "Access-Control-Allow-Credentials": ["true"], "Access-Control-Allow-Methods": ["HEAD, GET, POST, PUT, DELETE"], "Access-Control-Allow-Headers": ["Origin, Referer, Content-Type"], "Access-Control-Expose-Headers": ["X-Set-Cookie, Date"], "Server": ["gunicorn/20.0.4"], "Cache-Control": ["max-age=43200, public"], "Etag": ["\"wzsdm-1538627414-11600-246809405\""], "Date": ["Sun, 15 Mar 2020 17:48:51 GMT"], "Connection": ["keep-alive"]}, "duration": 0.00232259, "status": 304}
But Shaarli gets the same 502 issue as Ghost:
caddy | 2020/03/15 17:39:26.470 ERROR http.log.error dial tcp: lookup shaarli on 127.0.0.11:53: no such host {"request": {"method": "GET", "uri": "/", "proto": "HTTP/2.0", "remote_addr": "86.195.85.85:60073", "host": "normco.re", "headers": {"Upgrade-Insecure-Requests": ["1"], "Accept": ["text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"], "Accept-Encoding": ["gzip, deflate, br"], "Cookie": ["shaarli_staySignedIn=7ccd68afd09563710f6691fb1c0d6b6776e86d6c; shaarli=sgi7bt66r7n26l94e840pm1mj0"], "Sec-Fetch-User": ["?1"], "Accept-Language": ["fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,pt;q=0.6,es;q=0.5,pt-PT;q=0.4,it;q=0.3"], "Cache-Control": ["max-age=0"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"], "Sec-Fetch-Dest": ["document"], "Sec-Fetch-Site": ["none"], "Sec-Fetch-Mode": ["navigate"]}, "tls": {"resumed": false, "version": 772, "ciphersuite": 4865, "proto": "h2", "proto_mutual": true, "server_name": "normco.re"}}, "status": 502, "err_id": "94drhacpw", "err_trace": "reverseproxy.(*Handler).ServeHTTP (reverseproxy.go:363)"}