1. The problem I’m having:
I have a series of docker containers set up on my Synology NAS (using Synology’s Reverse Proxy tool), and I’m trying to replace that with Caddy. The other containers are currently running and accessible over <container_name>.<my_domain>.synology.me:444. For example, I have Beszel accessible at https://beszel.cherringshaw.synology.me:444, and I’m trying to use Caddy to make it accessible at https://beszel.cherringshaw.synology.me.
I use Synology’s DDNS to manage my domain name, and I have port forwarding rules in my local router for 443 and 444 to go my NAS’ local address (192.168.50.4). I’ve also made sure that Synology’s default nginx is no longer listening on port 443 by following: Free Ports 80 and 443 on Synology NAS: The Definitive Guide | SimpleHomelab
I’m having a hard time finding logs for exactly what’s going wrong - I’m not great with networking or proxies in general, and I’ve sorta muddled my way through to this point by reading forum posts and googling the errors in the logs. But the only logs I can see now just say “connection refused,” with no other indication of what might be going wrong.
Thanks in advance for any help!
2. Error messages and/or full log output:
When I run
curl -vL https://beszel.cherringshaw.synology.me
I get this output in the terminal:
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET / HTTP/2
> Host: beszel.cherringshaw.synology.me
> user-agent: curl/7.86.0
> accept: */*
>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 502
< alt-svc: h3=":443"; ma=2592000
< server: Caddy
< content-length: 0
< date: Wed, 12 Mar 2025 14:08:23 GMT
<
and this entry in the docker logs for Caddy:
{"level":"error","ts":1741788307.5427284,"logger":"http.log.error","msg":"dial tcp 192.168.160.3:80: connect: connection refused","request":{"remote_ip":"192.168.160.1","remote_port":"33064","client_ip":"192.168.160.1","proto":"HTTP/2.0","method":"GET","host":"beszel.cherringshaw.synology.me","uri":"/","headers":{"User-Agent":["curl/7.86.0"],"Accept":["*/*"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"beszel.cherringshaw.synology.me"}},"duration":0.000590436,"status":502,"err_id":"8643f24m3","err_trace":"reverseproxy.statusError (reverseproxy.go:1373)"}
With curl -vL https://beszel.cherringshaw.synology.me:444
(which uses Synology’s Reverse Proxy), I get a successful result with the page contents:
[cam@SynologyNAS caddy (master) ]$ curl -vL https://beszel.cherringshaw.synology.me:444
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
> GET / HTTP/2
> Host: beszel.cherringshaw.synology.me:444
> user-agent: curl/7.86.0
> accept: */*
>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 200
< date: Wed, 12 Mar 2025 14:33:57 GMT
< content-type: text/html; charset=utf-8
< content-length: 551
< vary: Origin
< x-content-type-options: nosniff
< x-frame-options: SAMEORIGIN
< x-xss-protection: 1; mode=block
< strict-transport-security: max-age=15768000; includeSubdomains; preload
<
<!doctype html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<link rel="manifest" href="/static/manifest.json" />
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Beszel</title>
<script>window.BASE_PATH = "/"</script>
<script type="module" crossorigin src="/assets/index-aVukMUSG.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Sz60ABYj.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
* TLSv1.2 (IN), TLS header, Supplemental data (23):
curl -vL http://192.168.50.4:8090
also succeeds and shows the page contetnts.
3. Caddy version: 2.9.1
4. How I installed and ran Caddy:
a. System environment:
Synology NAS (some flavor of Linux), with Caddy running via docker-compose.
b. Command:
sudo docker-compose docker-compose.yml up --force-recreate -d
c. Service/unit/compose file:
services:
caddy:
image: caddy:2.9.1
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- caddy_data:/data
- caddy_config:/config
networks:
- nas_docker_compose_default
volumes:
caddy_data:
caddy_config:
networks:
nas_docker_compose_default:
external: true
My other container is on the same docker network:
services:
beszel:
image: henrygd/beszel
container_name: beszel
restart: unless-stopped
extra_hosts:
- host.docker.internal:host-gateway
ports:
- 8090:8090
volumes:
- ./beszel_data:/beszel_data
networks:
- nas_docker_compose_default
beszel-agent:
image: "henrygd/beszel-agent"
container_name: "beszel-agent"
restart: unless-stopped
network_mode: host
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
# monitor other disks / partitions by mounting a folder in /extra-filesystems
# - /mnt/disk/.beszel:/extra-filesystems/sda1:ro
environment:
KEY: "REDACTED"
PORT: 45876
networks:
nas_docker_compose_default:
external: true
And I’ve verified this with docker network inspect
:
[cam@SynologyNAS caddy (master) ]$ sudo docker network inspect nas_docker_compose_default
[
{
"Name": "nas_docker_compose_default",
"Id": "d2e55f7d818b0f8d4f5418a839dbff1e8c327a28ae49a66e3399cf72348653bf",
"Created": "2025-02-28T06:08:04.094188572-06:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "192.168.160.0/20",
"Gateway": "192.168.160.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"b5a30bcb29caf732ede2e31bf2a7dcad51ac2709db739552464f1411d34ea93b": {
"Name": "caddy-caddy-1",
"EndpointID": "e970ad5dff1ec2b34f9b356e102660ed0ac587383a512c96351f4a9f5de8d22a",
"MacAddress": "02:42:c0:a8:a0:02",
"IPv4Address": "192.168.160.2/20",
"IPv6Address": ""
},
"d3a7478d9d2e50cf246b22883faf18a6046fdebf2db7f1cd61ae5da173fc0a7d": {
"Name": "beszel",
"EndpointID": "224eab30c9159345b2cf5f2fd5494ad924c2b3ddaeb3d55270a022c65a204d1a",
"MacAddress": "02:42:c0:a8:a0:03",
"IPv4Address": "192.168.160.3/20",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "default",
"com.docker.compose.project": "nas_docker_compose",
"com.docker.compose.version": "2.9.0"
}
}
]
d. My complete Caddy config:
caddy.cherringshaw.synology.me {
respond "Hello, world!"
}
beszel.cherringshaw.synology.me {
reverse_proxy http://beszel:8090
}
localhost {
respond "Hi there"
}
I’ve also tried the following variations, with similar results:
reverse_proxy http://beszel
reverse_proxy beszel
reverse_proxy beszel:8090
5. Links to relevant resources:
Referenced this post to get to where I currently am: How do I reverse-proxy to diffirent docker containers