1. The problem I’m having:
Hi !
I’m trying to configure a Caddy server behind a ngnix acting as a reverse proxy (HTTPS to HTTPS).
I tried several configurations but I cannot figure out the correct one, I’m always getting SSL errors.
2. Error messages and/or full log output:
2023/06/09 01:10:01 [error] 448#448: *1 SSL_do_handshake() failed (SSL: error:0A000438:SSL routines::tlsv1 alert internal error:SSL alert number 80) while SSL handshaking to upstream, client: 192.168.1.254, server: staging.dolium.*, request: "GET / HTTP/2.0", upstream: "https://172.18.0.13:443/", host: "staging.dolium.leverbeux.eu"
2023/06/09 01:10:01 [error] 448#448: *1 SSL_do_handshake() failed (SSL: error:0A000438:SSL routines::tlsv1 alert internal error:SSL alert number 80) while SSL handshaking to upstream, client: 192.168.1.254, server: staging.dolium.*, request: "GET /favicon.ico HTTP/2.0", upstream: "https://172.18.0.13:443/favicon.ico", host: "staging.dolium.leverbeux.eu", referrer: "https://staging.dolium.leverbeux.eu/"
3. Caddy version: v2.6.4
4. How I installed and ran Caddy:
a. System environment:
Docker with Docker-Compose
b. Command:
# Build Caddy with the Mercure and Vulcain modules
# Temporary fix for https://github.com/dunglas/mercure/issues/770
FROM caddy:2.7-builder-alpine AS app_caddy_builder
RUN xcaddy build v2.6.4 \
--with github.com/dunglas/mercure/caddy \
--with github.com/dunglas/vulcain/caddy
# Caddy image
FROM caddy:2-alpine AS app_caddy
WORKDIR /srv/app
COPY --from=app_caddy_builder /usr/bin/caddy /usr/bin/caddy
COPY --from=app_php /srv/app/public public/
COPY docker/caddy/Caddyfile /etc/caddy/Caddyfile
c. Service/unit/compose file:
version: "3.4"
services:
php:
image: registry.gitlab.com/myPhpImage
networks:
- backend
restart: unless-stopped
volumes:
- php_socket:/var/run/php
environment:
...
caddy:
image: registry.gitlab.com/myCaddyBuiltImage
networks:
- backend
depends_on:
- php
environment:
SERVER_NAME: ${SERVER_NAME:-staging.dolium.leverbeux.eu}
MERCURE_PUBLISHER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!}
MERCURE_SUBSCRIBER_JWT_KEY: ${CADDY_MERCURE_JWT_SECRET:-!ChangeThisMercureHubJWTSecretKey!}
restart: unless-stopped
volumes:
- php_socket:/var/run/php
- caddy_data:/data
- caddy_config:/config
volumes:
php_socket:
caddy_data:
caddy_config:
networks:
backend:
name: proxy
external: true
d. My complete Caddy config:
{
# Debug
{$CADDY_DEBUG}
}
{$SERVER_NAME}
log
# Matches requests for HTML documents, for static files and for Next.js files,
# except for known API paths and paths with extensions handled by API Platform
@pwa expression `(
header({'Accept': '*text/html*'})
&& !path(
'/docs*', '/graphql*', '/bundles*', '/contexts*', '/_profiler*', '/_wdt*',
'*.json*', '*.html', '*.csv', '*.yml', '*.yaml', '*.xml'
)
)
|| path('/favicon.ico', '/manifest.json', '/robots.txt', '/_next*', '/sitemap*')`
route {
root * /srv/app/public
mercure {
# Transport to use (default to Bolt)
transport_url {$MERCURE_TRANSPORT_URL:bolt:///data/mercure.db}
# Publisher JWT key
publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {env.MERCURE_PUBLISHER_JWT_ALG}
# Subscriber JWT key
subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {env.MERCURE_SUBSCRIBER_JWT_ALG}
# Allow anonymous subscribers (double-check that it's what you want)
anonymous
# Enable the subscription API (double-check that it's what you want)
subscriptions
# Extra directives
{$MERCURE_EXTRA_DIRECTIVES}
}
vulcain
# Add links to the API docs and to the Mercure Hub if not set explicitly (e.g. the PWA)
header ?Link `</docs.jsonld>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation", </.well-known/mercure>; rel="mercure"`
# Disable Topics tracking if not enabled explicitly: https://github.com/jkarlin/topics
header ?Permissions-Policy "browsing-topics=()"
# Comment the following line if you don't want Next.js to catch requests for HTML documents.
# In this case, they will be handled by the PHP app.
reverse_proxy @pwa http://{$PWA_UPSTREAM}
php_fastcgi unix//var/run/php/php-fpm.sock
encode zstd gzip
file_server
}
e. My complete NGNIX Reverse proxy config:
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name staging.dolium.*;
include /config/nginx/ssl.conf;
location / {
include /config/nginx/proxy.conf;
include /config/nginx/resolver.conf;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
set $upstream_app dolium-caddy-1;
set $upstream_port 443;
set $upstream_proto https;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
}
}