Carbonio LetsEncript ssl deploy on ubuntu 24.4
mkdir -p /etc/letsencrypt/cloudflare vi /etc/letsencrypt/cloudflare/credentials.ini
Carbonio LetsEncript ssl deploy on ubuntu 24.4
mkdir -p /etc/letsencrypt/cloudflare vi /etc/letsencrypt/cloudflare/credentials.ini
dns_cloudflare_api_token = YOUR_CLOUDFLARE_API_TOKEN
chmod 600 /etc/letsencrypt/cloudflare/credentials.ini
apt install certbot
apt install python3-certbot-dns-cloudflare -y
certbot certonly \ — dns-cloudflare \ — dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini \ — dns-cloudflare-propagation-seconds 30 \ -d “example.com” \ -d “*.example.com” \ — email system@example.com \ — agree-tos \ — non-interactive
#!/usr/bin/env bash
#
# carbonio-deploy-if-cert-changed.sh (Ubuntu 24.04 / yeni Carbonio)
# -----------------------------------------------------------------------------
# 1) Live sertifikanin kalan suresine bakar; <= RENEW_THRESHOLD_DAYS ise
# zextras kullanicisi ile `certbot renew` calistirir.
# 2) Live ile deploy edilmis sertifikayi fingerprint uzerinden karsilastirir.
# 3) Farkliysa Carbonio'ya deploy eder.
# 4) systemd target'lari ile tum bilesenleri yeniden baslatir
# (komple sunucu reboot etmeden).
# 5) Her servis icin port uzerinden SHA-256 fingerprint dogrulamasi yapar;
# eslesmeyen olursa hedefli restart dener; hala olmuyorsa hata kodu ile cikar.
#
# Onerilen cron: 10 3 * * * /opt/scripts/carbonio-deploy-if-cert-changed.sh \
# >> /var/log/carbonio-cert-deploy.log 2>&1
# -----------------------------------------------------------------------------
set -euo pipefail
# ---- AYARLAR ----------------------------------------------------------------
DOMAIN="mail.example.com"
LIVE_DIR="/opt/zextras/common/certbot/etc/letsencrypt/live/${DOMAIN}"
LIVE_CERT="${LIVE_DIR}/cert.pem"
# zmcertmgr deploycrt'in fiilen yazdigi dosyalardan birini referans al.
DEPLOYED_PEM="/opt/zextras/conf/nginx.crt"
COMM_KEY_DST="/opt/zextras/ssl/carbonio/commercial/commercial.key"
TMP_DIR="/tmp"
# Certbot
CERTBOT_BIN="/opt/zextras/common/bin/certbot"
RENEW_THRESHOLD_DAYS=5
ISRG_URL="https://letsencrypt.org/certs/isrgrootx1.pem.txt"
LOCK_FILE="/var/lock/carbonio-deploy-if-cert-changed.lock"
# Carbonio systemd target'lari (Ubuntu 24.04)
UMBRELLA_TARGET="carbonio.target"
LDAP_TARGET="carbonio-directory-server.target"
MTA_TARGET="carbonio-mta.target"
PROXY_TARGET="carbonio-proxy.target"
APPSERVER_TARGET="carbonio-appserver.target"
# Dogrulanacak (port|label|openssl-extra) listesi
declare -a VERIFY_TARGETS=(
"443|HTTPS-proxy|"
"993|IMAPS|"
"995|POP3S|"
"465|SMTPS|"
"25|SMTP-STARTTLS|-starttls smtp"
"587|Submission-STARTTLS|-starttls smtp"
"389|LDAP-STARTTLS|-starttls ldap"
)
# Restart sonrasi dogrulamadan once beklenecek sure (saniye)
SETTLE_SECONDS=30
# -----------------------------------------------------------------------------
log() { echo "[$(date -u '+%Y-%m-%d %H:%M:%S UTC')] $*"; }
# ---- Lock + on kontroller --------------------------------------------------
exec 9>"$LOCK_FILE"
flock -n 9 || { log "Baska bir kopya calisiyor, cikiliyor."; exit 0; }
if [[ $EUID -ne 0 ]]; then
log "HATA: Bu script root olarak calismali."
exit 1
fi
[[ -f "$LIVE_CERT" ]] || { log "HATA: Live cert yok: $LIVE_CERT"; exit 1; }
[[ -f "$DEPLOYED_PEM" ]] || { log "HATA: Deployed cert yok: $DEPLOYED_PEM"; exit 1; }
[[ -x "$CERTBOT_BIN" ]] || { log "HATA: certbot bulunamadi: $CERTBOT_BIN"; exit 1; }
# ---- Yardimci fonksiyonlar -------------------------------------------------
fp_of_file() {
openssl x509 -in "$1" -noout -fingerprint -sha256 2>/dev/null \
| awk -F= '{print $2}' | tr -d ':'
}
fp_of_port() {
local port="$1" extra="$2"
echo | timeout 8 openssl s_client ${extra} -connect "127.0.0.1:${port}" \
-servername "$DOMAIN" 2>/dev/null \
| openssl x509 -noout -fingerprint -sha256 2>/dev/null \
| awk -F= '{print $2}' | tr -d ':'
}
dates_of_port() {
local port="$1" extra="$2"
echo | timeout 8 openssl s_client ${extra} -connect "127.0.0.1:${port}" \
-servername "$DOMAIN" 2>/dev/null \
| openssl x509 -noout -dates -subject 2>/dev/null
}
restart_target() {
local tgt="$1"
if systemctl list-unit-files "$tgt" --quiet 2>/dev/null | grep -q "$tgt"; then
log " systemctl restart $tgt"
systemctl restart "$tgt" || { log " HATA: $tgt restart edilemedi"; return 1; }
else
log " $tgt bulunamadi, atlaniyor"
fi
return 0
}
# ---- 1) Sure kontrolu + gerekirse certbot renew ----------------------------
NOT_AFTER_EPOCH=$(date -d "$(openssl x509 -in "$LIVE_CERT" -noout -enddate | cut -d= -f2)" +%s)
NOW_EPOCH=$(date -u +%s)
DAYS_LEFT=$(( (NOT_AFTER_EPOCH - NOW_EPOCH) / 86400 ))
log "Live cert son gecerlilik: $(date -d "@${NOT_AFTER_EPOCH}" -u '+%Y-%m-%d %H:%M:%S UTC') (${DAYS_LEFT} gun kaldi)"
if (( DAYS_LEFT <= RENEW_THRESHOLD_DAYS )); then
log "Esik (${RENEW_THRESHOLD_DAYS} gun) altinda. zextras ile certbot renew calistiriliyor..."
if su - zextras -c "${CERTBOT_BIN} renew --non-interactive"; then
log "certbot renew tamamlandi."
else
log "UYARI: certbot renew basarisiz. Yine de deploy karsilastirmasina devam ediliyor."
fi
else
log "Sure yeterli (${DAYS_LEFT} > ${RENEW_THRESHOLD_DAYS}). certbot renew atlandi."
fi
# ---- 2) Fingerprint karsilastirmasi ----------------------------------------
LIVE_FP=$(fp_of_file "$LIVE_CERT")
DEPLOYED_FP=$(fp_of_file "$DEPLOYED_PEM")
[[ -n "${LIVE_FP:-}" ]] || { log "HATA: Live fingerprint okunamadi"; exit 1; }
[[ -n "${DEPLOYED_FP:-}" ]] || { log "HATA: Deployed fingerprint okunamadi"; exit 1; }
log "LIVE FP: $LIVE_FP"
log "DEPLOYED FP: $DEPLOYED_FP"
if [[ "$LIVE_FP" == "$DEPLOYED_FP" ]]; then
log "Sertifika ayni, deploy gerekmez. Cikiliyor."
exit 0
fi
log "Sertifika farkli! Deploy islemi basliyor..."
# ---- 3) Dosya hazirligi ----------------------------------------------------
for f in "$LIVE_DIR/privkey.pem" "$LIVE_DIR/cert.pem" "$LIVE_DIR/fullchain.pem"; do
[[ -f "$f" ]] || { log "HATA: Kaynak dosya yok: $f"; exit 1; }
done
cp -fL "$LIVE_DIR/privkey.pem" "$COMM_KEY_DST"
chown zextras:zextras "$COMM_KEY_DST"
chmod 600 "$COMM_KEY_DST"
cp -fL "$LIVE_DIR/cert.pem" "$TMP_DIR/commercial.pem"
chown zextras:zextras "$TMP_DIR/commercial.pem"
cp -fL "$LIVE_DIR/fullchain.pem" "$TMP_DIR/fullchain.pem"
chown zextras:zextras "$TMP_DIR/fullchain.pem"
wget --no-check-certificate -q -O "$TMP_DIR/ISRG-X1.pem" "$ISRG_URL" \
|| { log "HATA: ISRG Root indirilemedi"; exit 1; }
cat "$TMP_DIR/fullchain.pem" "$TMP_DIR/ISRG-X1.pem" > "$TMP_DIR/zextras_ca.pem"
chown zextras:zextras "$TMP_DIR/zextras_ca.pem"
# ---- 4) Deploy -------------------------------------------------------------
su - zextras -c "cd /tmp && /opt/zextras/bin/zmcertmgr verifycrt comm \
/opt/zextras/ssl/carbonio/commercial/commercial.key \
/tmp/commercial.pem \
/tmp/zextras_ca.pem"
su - zextras -c "cd /tmp && /opt/zextras/bin/zmcertmgr deploycrt comm \
/tmp/commercial.pem \
/tmp/zextras_ca.pem"
# mailboxd.pem deploycrt tarafindan guncellenMEZ; tutarlilik icin elle senkronla
cp -fL "$LIVE_DIR/fullchain.pem" /opt/zextras/mailboxd/etc/mailboxd.pem
chown zextras:zextras /opt/zextras/mailboxd/etc/mailboxd.pem
chmod 644 /opt/zextras/mailboxd/etc/mailboxd.pem
# ---- 5) TUM Carbonio bilesenlerini yeniden baslat --------------------------
# Onerilen: umbrella target'i restart et -- tum alt target'lari (ldap, mta,
# proxy, appserver) systemd dogru bagimlilik sirasinda yeniden baslatir.
# Bu, sunucu reboot'una en yakin temiz yontemdir.
log "Tum Carbonio bilesenleri yeniden baslatiliyor (${UMBRELLA_TARGET})..."
if systemctl list-unit-files "$UMBRELLA_TARGET" --quiet 2>/dev/null | grep -q "$UMBRELLA_TARGET"; then
if systemctl restart "$UMBRELLA_TARGET"; then
log "${UMBRELLA_TARGET} restart tamamlandi."
else
log "UYARI: ${UMBRELLA_TARGET} restart hata verdi. Tek tek deniyorum..."
restart_target "$LDAP_TARGET" || true
restart_target "$MTA_TARGET" || true
restart_target "$PROXY_TARGET" || true
restart_target "$APPSERVER_TARGET" || true
fi
else
log "${UMBRELLA_TARGET} bulunamadi. Alt target'lar tek tek restart ediliyor..."
restart_target "$LDAP_TARGET" || true
restart_target "$MTA_TARGET" || true
restart_target "$PROXY_TARGET" || true
restart_target "$APPSERVER_TARGET" || true
fi
# ---- 6) Settle bekle -------------------------------------------------------
log "Servislerin oturmasi icin ${SETTLE_SECONDS} sn bekleniyor..."
sleep "$SETTLE_SECONDS"
# ---- 7) Port bazinda fingerprint dogrulamasi -------------------------------
log "Port bazinda fingerprint dogrulamasi:"
ALL_OK=1
declare -a FAILED_PORTS=()
for entry in "${VERIFY_TARGETS[@]}"; do
IFS='|' read -r port label extra <<< "$entry"
port_fp=$(fp_of_port "$port" "$extra" || true)
if [[ -z "$port_fp" ]]; then
log " [$label :$port] BAGLANTI YOK / cert okunamadi (servis kapali olabilir, atlaniyor)"
continue
fi
if [[ "$port_fp" == "$LIVE_FP" ]]; then
log " [$label :$port] OK"
else
log " [$label :$port] HATALI: port=$port_fp"
log " $(dates_of_port "$port" "$extra")"
FAILED_PORTS+=("$entry")
ALL_OK=0
fi
done
# ---- 8) Eslesmeyenler icin ikinci tur hedefli restart ----------------------
if (( ALL_OK == 0 )); then
log "Eslesmeyen portlar var. Hedefli ikinci tur restart deneniyor..."
# Eslesmeyen portlara gore hangi target'lari restart edecegimizi belirle
declare -A NEED_RESTART=()
for entry in "${FAILED_PORTS[@]}"; do
IFS='|' read -r port _ _ <<< "$entry"
case "$port" in
25|465|587) NEED_RESTART["$MTA_TARGET"]=1 ;;
443) NEED_RESTART["$PROXY_TARGET"]=1 ;;
993|995) NEED_RESTART["$APPSERVER_TARGET"]=1 ;;
389) NEED_RESTART["$LDAP_TARGET"]=1 ;;
esac
done
for tgt in "${!NEED_RESTART[@]}"; do
log " -> $tgt"
restart_target "$tgt" || true
done
log "Ikinci settle bekleyisi: ${SETTLE_SECONDS} sn..."
sleep "$SETTLE_SECONDS"
log "Yeniden dogrulama:"
ALL_OK=1
for entry in "${FAILED_PORTS[@]}"; do
IFS='|' read -r port label extra <<< "$entry"
port_fp=$(fp_of_port "$port" "$extra" || true)
if [[ "$port_fp" == "$LIVE_FP" ]]; then
log " [$label :$port] OK"
else
log " [$label :$port] HALA HATALI"
ALL_OK=0
fi
done
fi
# ---- 9) Sonuc --------------------------------------------------------------
NEW_DEPLOYED_FP=$(fp_of_file "$DEPLOYED_PEM")
log "Yeni DEPLOYED FP: $NEW_DEPLOYED_FP"
if (( ALL_OK == 1 )); then
log "BASARILI: Tum servisler yeni sertifikayi serve ediyor."
exit 0
else
log "KRITIK: Bazi servisler hala eski sertifikayi serve ediyor!"
log " Onerilen: 'systemctl stop ${UMBRELLA_TARGET} && systemctl start ${UMBRELLA_TARGET}'"
log " veya son care olarak sunucu reboot."
# Opsiyonel uyari kanali (mail/webhook) buraya eklenebilir.
# echo "Carbonio cert deploy basarisiz: $DOMAIN" | mail -s "ALERT" admin@example.com
exit 2
fi
chmod u+x /opt/scripts/carbonio-deploy-if-cert-changed.sh
crontab -e
10 3 * * * /opt/scripts/carbonio-deploy-if-cert-changed.sh >> /var/log/carbonio-cert-deploy.log 2>&1
메타데이터
- post_id
- 9c99b0e52f6d
- slug
- carbonio-letsencript-ssl-deploy-on-ubuntu-24-4-9c99b0e52f6d
- url
- https://medium.com/@dururustem68/carbonio-letsencript-ssl-deploy-on-ubuntu-24-4-9c99b0e52f6d
- canonical_url
- https://medium.com/@dururustem68/carbonio-letsencript-ssl-deploy-on-ubuntu-24-4-9c99b0e52f6d
- author_url
- https://medium.com/@dururustem68
- status
- ok
- fetched_at
- 2026-07-16 00:55:23