Why Caddy + Nginx?

Edit: This should actually be a reply to this thread. It’s still somewhat relevant to the discussion about custom SSL termination here, though.

Hi @regis and @iamCristYe, something that may be of interest is Caddy’s tls directive. I have had some success using this.

By changing the Caddyfile to something like:

your.lms.domain {
    tls /etc/ssl/yourcert.cer /etc/ssl/yourcert.pem
    reverse_proxy nginx:80 {
        header_up X-Forwarded-Port 443
    }
}

for each of your domains, you can keep the Nginx configuration the same, and still use custom certificates. You will have to mount your certificate files to the Caddy container at the appropriate locations.

Arguably this is a bit redundant since you could just have Nginx handle TLS at that point. Though, Caddy’s succinct configuration and security-focused updates mean you still get some of the benefits of Caddy (as security and encryption best-practices change over time).

One problem is that it isn’t possible to achieve this configuration, as far as I’m aware, using Tutor plugins’ template patching alone.

To partially address this (along with a few other use-cases), I’ve been developing a Tutor plugin, tutor-contrib-recon (short for “reconfigure”), which allows for direct overrides of settings and templates in your Tutor environment during development. The goal is to ultimately make it easy to roll such changes either into a plugin or a modification to Tutor.

Right now it is a work in progress, but the template-override functionality is more-or-less implemented (though unstable). After installing and enabling the plugin, you can do this:

tutor recon replace-template apps/caddy/Caddyfile

Tutor’s template for the Caddyfile is then copied into $(tutor config printroot)/env_overrides/templates/apps/caddy/Caddyfile) (note: $(tutor recon printroot) is short for $(tutor config printroot)/env_overrides, so you can use that here instead).

You can then change it to something like:

{{ LMS_HOST }} {
    tls {{ TLS_CERTS.public.container }} {{ TLS_CERTS.private.container }}
    reverse_proxy nginx:80 {
        header_up X-Forwarded-Port 443
    }
}

{{ PREVIEW_HOST }} {
    reverse_proxy nginx:80
}

{{ CMS_HOST }} {
    reverse_proxy nginx:80
}

{{ patch("caddyfile") }}

and add settings to Tutor’s config.yml like:

TLS_CERTS:
  private:
    container: /etc/ssl/yourcert.pem
    local: /wherever/your/cert/is/locally/yourcert.pem
  public:
    container: /etc/ssl/yourcert.cer
    local: /wherever/your/cert/is/locally/yourcert.cer

With that finished, you’ll just need to use tutor recon save to render your new template. You will need to continue using tutor recon save instead of tutor config save in the future to allow the correct template to be rendered.

You’d also want to modify your docker compose template(s) to bind-mount your cert files by adding to the volumes key in the Caddy service like:

- {{ TLS_CERTS.public.local }}:{{ TLS_CERTS.public.container }}
- {{ TLS_CERTS.private.local }}:{{ TLS_CERTS.private.container }}

If you want to try to do this, let me know how it goes! The project is definitely in early phases, so I’d be interested to see if you find it usable for this purpose.