Caddy cert only and events to restart a container

1. The problem I’m having:

No problems!, just trying to work out if this is correctly formatted and will work as expected. So to explain, I will be running Caddy using docker compose in Alpine Linux, (currently its working in a different way on Fedora with Podman) I have 2 domains that I want certs for and for it to proxy to the correct container(this isn’t the issue) I want another domain to only receive a cert from Caddy no proxying or https etc (currently I use certbot for this) and perform a command when it receives said cert.

2. Error messages and/or full log output:

no errors 

3. Caddy version:

latest as of this writing so 2.11.4, I think

4. How I installed and ran Caddy:

caddy is installed using docker compose

a. System environment:

Alpine Linux

b. Command:

docker compose up -d

c. Service/unit/compose file:

services:
  caddy:
    container_name: caddy
    build: .
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - /home/alpine/caddy/conf:/etc/caddy
      - /home/alpine/caddy/site:/srv
      - caddy_data:/data
      - caddy_config:/config
    env_file:
     - .env
    command: caddy run --config /etc/caddy/caddy.json
volumes:
  caddy_data:
  caddy_config:

networks:
 default:
   external:
     name: caddy

d. My complete Caddy config:

{
  "apps": {
    "http": {
      "servers": {
        "srv0": {
          "listen": [
            ":443"
          ],
          "routes": [
            {
              "match": [
                {
                  "host": [
                    "vaultwarden.my-domain.uk"
                  ]
                }
              ],
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "reverse_proxy",
                          "upstreams": [
                            {
                              "dial": "vaultwarden:8001"
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "terminal": true
            },
            {
              "match": [
                {
                  "host": [
                    "opencloud.my-domain.uk"
                  ]
                }
              ],
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "reverse_proxy",
                          "upstreams": [
                            {
                              "dial": "opencloud:9200"
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    },
    "tls": {
      "certificates": {
        "automate": [
          "ejabberd.my-domain.uk",
          "*.ejabberd.my-domain.uk"
        ]
      }
      "automation": {
        "policies": [
          {
            "subjects": [
              "vaultwarden.my-domain.uk",
              "opencloud.my-domain.uk"
            ],
            "issuers": [
              {
                "challenges": {
                  "dns": {
                    "provider": {
                      "auth_api_token": "{env.IONOS_API_TOKEN}",
                      "name": "ionos"
                    }
                  }
                },
                "email": "my-email@emails.com",
                "module": "acme"
              }
            ]
          }
        ]
      }
    },
    "events": {
      "subscriptions": [
        {
          "events":["cert_obtained"],
          "handlers": [
            {
              "handler": "exec",
              "command": "/usr/local/bin/docker-restart.sh",
              "args": ["ejabberd"]
            }
          ]
        }
      ]
    }
  }
}

5. Links to relevant resources:

so to explain in a little more detail, I have converted my Caddyfile to JSON because I want to utilise the cert only option in TLS. I have added ejabberd and *ejabberd as cert only under automate, I’m hoping this is the correct way of doing this for both the wildcard and the base domain cert.

I have then added an ‘event’ to utilise a script to restart the ejabberd container after receiving a new cert. ( not sure this will work )

this is the script

#!/bin/sh

/usr/local/bin/docker-restart.sh

CONTAINER_NAME=$1

Check if container exists

if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
docker restart "${CONTAINER_NAME}"
else
echo "Container ${CONTAINER_NAME} not found"
exit 1
fi

I’m not sure how to only restart the container following a renewal of only the ejabberd domain and not the other 2 managed domains.

So I’ve made a little headway on this issue and resolved somethings I didn’t know were wrong to start with.

This is my updated caddy.json to make certs work for ejabberd (certs only) , still not sure I should add the wildcard in this way but it seems to work.

{
  "apps": {
    "http": {
      "servers": {
        "srv0": {
          "listen": [
            ":443"
          ],
          "routes": [
            {
              "match": [
                {
                  "host": [
                    "vaultwarden.my-domain.uk"
                  ]
                }
              ],
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "reverse_proxy",
                          "upstreams": [
                            {
                              "dial": "vaultwarden:8001"
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "terminal": true
            },
            {
              "match": [
                {
                  "host": [
                    "opencloud.my-domain.uk"
                  ]
                }
              ],
              "handle": [
                {
                  "handler": "subroute",
                  "routes": [
                    {
                      "handle": [
                        {
                          "handler": "reverse_proxy",
                          "upstreams": [
                            {
                              "dial": "opencloud:9200"
                            }
                          ]
                        }
                      ]
                    }
                  ]
                }
              ],
              "terminal": true
            }
          ]
        }
      }
    },
    "tls": {
      "certificates": {
        "automate": [
          "ejabberd.my-domain.uk",
          "*.ejabberd.my-domain.uk"
        ]
      },
      "automation": {
        "policies": [
          {
            "subjects": [
              "vaultwarden.my-domain.uk",
              "opencloud.my-domain.uk",
              "ejabberd.my-domain.uk",
              "*.ejabberd.my-domain.uk"
            ],
            "issuers": [
              {
                "challenges": {
                  "dns": {
                    "provider": {
                      "auth_api_token": "{env.IONOS_API_TOKEN}",
                      "name": "ionos"
                    }
                  }
                },
                "email": "my-email",
                "module": "acme"
              }
            ]
          }
        ]
      }
    },
    "events": {
      "subscriptions": [
        {
          "events":["cert_obtained"],
          "handlers": [
            {
              "handler": "exec",
              "command": "/usr/local/bin/docker-restart.sh",
              "args": ["ejabberd-server"]
            }
          ]
        }
      ]
    }
  }
}

I updated the docker restart script as ejabberd couldn’t access the certs as it runs with user 9000 in the container. I’m not sure this working properly and still could use some help on this front, in the script it uses the docker command which when run from the caddy container obviously doesn’t exist. I thought this event would trigger the script to run on the host is this not correct?

#!/bin/sh
# /usr/local/bin/docker-restart.sh

CONTAINER_NAME=$1

# Check if container exists
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
    cp /home/alpine/caddy/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/ejabberd.my-domain.uk/ejabberd.my-domain.uk.{crt,key} /home/alpine/ejabberd/certs
    cp /home/alpine/caddy/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.ejabberd.my-domain.uk/wildcard_.ejabberd.my-domain.uk.{crt,key} /home/alpine/ejabberd/certs
    chown 9000:9000 /home/alpine/ejabberd/certs/*
    docker restart "${CONTAINER_NAME}"
else
    echo "Container ${CONTAINER_NAME} not found"
    exit 1
fi

is this a bad way to achieve the desired result ?