> ## Content Index
> Fetch the complete content index at: https://ostreff.info/llms.txt
> Use this file to discover other available public pages before exploring further.

# Using Caddy as free SSL certificates manager
- URL: https://ostreff.info/using-caddy-as-free-certificates-manager/
- Published: 2026-02-25T22:56:58.000Z
- Updated: 2026-02-26T09:10:45.000Z
- Description: It's really convinient to use caddy for renewing multiple free SSL certificates. Here is my automation for postfix and dovecot
- Author: Jordan Ostreff
- Tags: caddy, Dovecot, Postfix, FreeBSD

```bash
#!/bin/sh

CADDY_BASE="/var/db/caddy/data/caddy/certificates/acme-v02.api.letsencrypt.org-directory"
POSTFIX_DIR="/usr/local/etc/postfix"
STATE_FILE="/var/run/last_ssl_update"

# list of domains
DOMAINS="mail.ostreff.info mail.classic-bg.net mail.albena-bg.be mail.realesr.ostreff.info"

# 1. Find newest certificate (Epoch)
NEWEST_CHANGE=$(find $CADDY_BASE -name "*.crt" -exec stat -f "%m" {} + | sort -rn | head -1)

# last execution
[ -f "$STATE_FILE" ] && LAST_CHANGE=$(cat "$STATE_FILE") || LAST_CHANGE=0

# 2. is there change?
if [ "$NEWEST_CHANGE" -gt "$LAST_CHANGE" ]; then
    echo "$(date): Found new certificates. Refreshing services..."

    : > "$POSTFIX_DIR/mail.crt"
    : > "$POSTFIX_DIR/mail.key"
    
    # Protect the key (only for root )
    chmod 600 "$POSTFIX_DIR/mail.key"

    for DOMAIN in $DOMAINS; do
        CRT="$CADDY_BASE/$DOMAIN/$DOMAIN.crt"
        KEY="$CADDY_BASE/$DOMAIN/$DOMAIN.key"

        if [ -f "$CRT" ] && [ -f "$KEY" ]; then
            cat "$CRT" >> "$POSTFIX_DIR/mail.crt"
            cat "$KEY" >> "$POSTFIX_DIR/mail.key"
            echo " [+] Added certificate for: $DOMAIN"
        else
            echo " [!] Error: Missing files for $DOMAIN"
        fi
    done

    # 3. for Postfix
    /usr/local/sbin/postmap -F hash:"$POSTFIX_DIR/vmail_ssl.map"
    /usr/sbin/service postfix restart
    echo " [+] Postfix restarted."
    # 4. Restart/Reload of Dovecot, certificates are already in place because of https://ostreff.info/use-sni-in-dovecot-and-postfix/
    if [ -f "/usr/local/etc/rc.d/dovecot" ]; then
        /usr/sbin/service dovecot restart
        echo " [+] Dovecot restarted."
    fi

    # Refresh state
    echo "$NEWEST_CHANGE" > "$STATE_FILE"
    echo "Ready."
else
    echo "No changes in certificates."
fi

```

```bash
0 * * * * /root/mail-ssl-generate.sh > /dev/null 2>&1

```