Reverse Proxy - Trusted SSL to Backend (Docker)

1. The problem I’m having:

Apologies for my other deleted post, I managed to hit an unknown hotkey-combination to post the topic before I’d finished writing it, then couldn’t re-post as I hit rate limiting for new members.

I’m looking for pointers / advice / suggestions on what is good practise (or possible) when using Caddy (as a docker container) to reverse proxy to other docker containers as the backend but using HTTPS throughout with trusted certificates.

My theory was that Caddy would run in a Docker container and be part of two docker networks - public (Internet facing) and private. The containers behind Caddy would be a private network with no Internet access for security, so all public traffic would route through Caddy.My testing so far shows I can do most of this.

My query relates to the best way to have HTTPS from the Caddy container to the web servers behind it. Usingtls_insecure_skip_verify gets this working as Caddy obviously can’t trust a self-signed certificate on the other containers but is there recommended a way to get a certificate Caddy can trust on them? I’ve noted that a couple of articles in the Wiki specifically said the example was not putting Caddy in a container to make it easier to work with the certificates.

One thought is to use something like acme.sh to handle certificate generation at host level (which ignores one of the benefits of using Caddy) and use Docker volumes to put the trusted certificates into the relevant containers using docker volumes. A wildcard certificate would simplify things with just one certificate to renew. I’d also need to tie the reload of services in the docker containers as post-renewal actions with acme.sh.

I know the security risk of having HTTP or untrusted HTTPs for the traffic between the Docker Caddy and other containers is very low given it’s not even leaving the host VM but sometimes you it’s nice to figure out a challenge.

Thanks!

2. Error messages and/or full log output:

None

3. Caddy version:

Latest - 2.10 (not installed in production yet)

4. How I installed and ran Caddy:

N/A

a. System environment:

Docker running on Ubuntu 24 ARM

b. Command:

N/A

c. Service/unit/compose file:

d. My complete Caddy config:

No config yet

5. Links to relevant resources:

As one of the options, you can use OpenSSL to quickly create an internal CA and have Caddy trust the CA certificate. Then, depending on how often you want to renew the certificates for your backend containers, you can generate and sign new certificates using that CA with the appropriate expiry dates. This way, the backend containers will have certificates that Caddy can trust.

You can also just tell Caddy to trust the self-signed certificate on the backend container.

I’m not sure how you report a post but the above post is spam with a dodgy URL.

Thanks for your reply @timelordx

I’ve been busy learning / testing / troubleshooting and have a working setup which covers:

  • Caddy - public facing and reverse proxying onto a private Docker network

On the private network:

  • Nginx - web server duties
  • PHP-FPM - PHP content from Nginx
  • MariaDB - database
  • phpMyAdmin - self explanatory

I have generated my own LE certs with acme.sh on the host and map them in the Caddy, Nginx and phpMyAdmin (Apache) containers. Troubleshooting was fun with trying to figure out if I didn’t have the right settings in my caddyfile, was it an error in the SSL config Nginx / Apache that was breaking HTTPS requests or both!

I still need to handle what happens when acme.sh renews the certs. Belt and braces is just to down/up all the containers. Alternatively, I could use docker exec to execute the relevant command in each container.

I’ve just discovered that acme.sh can push certificates into Docker containers and then reload services, so this gives me another option rather than using volumes.

Also an option to have acme.sh in it’s own container so less to maintain on the host.