1. The problem I’m having:
We utilise caddy running a docker image as an ingress service router for our platform. As part of the update process, our CI/CD pipeline (Gitlab CI/CD) connects to the docker host, refreshes the project and then will run ‘caddy reload’ to ensure up to date config is loaded.
This is is done via:
docker exec -w /etc/caddy ingress-router-caddy-1 caddy reload
This has worked without issue on Caddy v2.10. After updating the image to Caddy v2.11.1 this morning, we now see the following problem:
$ docker exec -w /etc/caddy ingress-router-caddy-1 caddy reload
{"level":"info","ts":1772070489.923556,"msg":"using adjacent Caddyfile"}
{"level":"warn","ts":1772070489.945869,"msg":"The nested 'metrics' option inside `servers` is deprecated and will be removed in the next major version. Use the global 'metrics' option instead."}
{"level":"info","ts":1772070489.9707046,"msg":"adapted config to JSON","adapter":"caddyfile"}
Error: sending configuration to instance: caddy responded with error: HTTP 403: {"error":"client is not allowed to access from origin 'http://localhost:2019'"}
This occus both manually and in the Gitlab CI/CD pipeline.
2. Error messages and/or full log output:
$ docker exec -w /etc/caddy ingress-router-caddy-1 caddy reload
{"level":"info","ts":1772070489.923556,"msg":"using adjacent Caddyfile"}
{"level":"warn","ts":1772070489.945869,"msg":"The nested 'metrics' option inside `servers` is deprecated and will be removed in the next major version. Use the global 'metrics' option instead."}
{"level":"info","ts":1772070489.9707046,"msg":"adapted config to JSON","adapter":"caddyfile"}
Error: sending configuration to instance: caddy responded with error: HTTP 403: {"error":"client is not allowed to access from origin 'http://localhost:2019'"}
3. Caddy version:
$ docker exec -w /etc/caddy ingress-router-caddy-1 caddy version
v2.11.1 h1:C7sQpsFOC5CH+31KqJc7EoOf8mXrOEkFyYd6GpIqm/s=
4. How I installed and ran Caddy:
Installed and run as a custom docker image, using caddy:2.11-alpine as the base image
a. System environment:
OS sersion: Ubuntu 24.04.4 LTS
using Docker version: 29.2.1, build a5c7197
b. Command:
docker compose up -d --wait
c. Service/unit/compose file:
name: ingress-router
services:
# base 'caddy' app router
caddy:
image: $INTERNAL_REG_REMOVED/caddy:2.11-alpine
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "5"
compress: "true"
ports:
- 80:80
- 443:443
- 2019:2019
networks:
- caddy
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- caddy_data:/data
- caddy_config:/config
- /etc/caddy:/etc/caddy
- /var/log/caddy:/var/log/caddy
networks:
caddy:
external: true
volumes:
caddy_data: {}
caddy_config: {}
d. My complete Caddy config:
{
admin 0.0.0.0:2019
email operations@example.com
log access-json {
format json
include http.log.access.access-logs
output file /var/log/caddy/access-json.log
format filter {
request>headers>Cookie delete
resp_headers delete
}
}
log access-common {
format transform `{request>headers>X-Forwarded-For>[0]:request>remote_ip} - {user_id} [{ts}] {request>headers>X-Forwarded-Host:request>host} "{request>method} {request>uri} {request>proto}" {status} {size} "{request>headers>Referer>[0]}" "{request>headers>User-Agent>[0]}"` {
time_format iso8601
}
include http.log.access.access-logs
output file /var/log/caddy/access-common.log
}
servers {
metrics
}
}
(base-rm-resp-headers) {
header -server
header -x-commerce-core
header -x-drupal-cache
header -x-drupal-dynamic-cache
header -x-generator
header -x-powered-by
}
(base-transport-tls-insecure) {
transport http {
tls_insecure_skip_verify
}
}
(base-transport-tls-insecure-and-sni) {
transport http {
tls_insecure_skip_verify
tls_server_name {host}
}
}
import Caddyfile.d/*.caddyfile
5. Links to relevant resources:
N/A