Update TLS certificate with Reverse Proxy automatictly

Your question

Hi, I’ve installed my Stalwart environment as a Docker container behind a reverse proxy, but now Stalwart itself needs a TLS certificate. Currently, I’m adding it manually and then restarting the container. Is there a way to automate this? Does anyone have a workflow for this?

There is some documentation here:

What I like best is the systemd service that checks whenever the certificate file has changed to reload stalwart.

But that only applies if you install it directly on the host and not via Docker, because Docker can’t access the host’s directory.

You can share files from the container and the host.

And how does that work?

Assuming you are using docker volumes or bind mounts for your containers, this is how things could work. mailcerts-script runs via cron once a day. Just change the “<*-home>” entries with your values.

Note, that these are not bullet-proof fully grown scripts, just little helpers.

Hope that helps.

Cheers

Michael aka /Bytewurm

#!/bin/bash

#
# mailcerts - copy certificates from Caddy to Stalwart
#
# caddy bind-dir "acme" mounted into caddy:/data/acme
# stalwart bind-dir "certs" mounted into stalwart:/etc/mycerts
#
# referencing within stalwart as "/etc/mycerts/example1.{crt,key}", etc.
# stalwart-cli required (using docker container and wrapper script in /usr/local/bin)
#

certs_updated=0

caddy_dir="<caddy-home>/acme/certificates/acme-v02.api.letsencrypt.org-directory"
stalwart_dir="<stalwart-home>/certs"

for domain in example1.com mail.example1.com example2.com; do

  crt_file="${domain}.crt"
  md5_caddy=$(md5sum ${caddy_dir}/${domain}/${crt_file} | cut -d' ' -f1)
  md5_stalwart=$(md5sum ${stalwart_dir}/${crt_file} | cut -d' ' -f1)

  if [[ "$md5_caddy" != "$md5_stalwart" ]]; then

    cp ${caddy_dir}/${domain}/${domain}.{crt,key} ${stalwart_dir}
    let certs_updated++

  fi

done

if [[ $certs_updated -gt 0 ]]; then
  
  # fix permissions for new certs
  chown 2000:2000 ${stalwart_dir}/*.{crt,key}
  chmod 440 ${stalwart_dir}/*.{crt,key}

  # then reload them
  /usr/local/bin/stalwart-cli create action/ReloadTlsCertificates --json '{}'

fi

Place this as /usr/local/bin/stalwart-cli, adapt homedir, stalwart docker network + create file STALWART_ADMIN_TOKEN with a valid token from stalwart.

#!/bin/sh

# Wrapper for stalwart-cli container
# note the docker volume to be used as cache, replace with simple bind-mount
# or remove it - will work anyways

cmd="$*"
ADMIN_TOKEN=$(cat <stalwart_home>/STALWART_ADMIN_TOKEN)

docker run --rm --network <stalwart_docker_network> --name stalwart_cli \
  -e "STALWART_URL=http://stalwart:8080" \
  -e "STALWART_TOKEN=${ADMIN_TOKEN}" \
  -v "stalwart-cli_cache:/home/nonroot/.cache" \
  stalwartlabs/cli:1.0.10 ${cmd}