Reload Config #
Salah satu keunggulan terbesar Caddy adalah kemampuannya untuk memuat ulang konfigurasi secara benar-benar zero-downtime. Ketika kamu mengubah Caddyfile dan mengirim sinyal reload, Caddy tidak menghentikan request yang sedang diproses, tidak menutup koneksi yang aktif, dan tidak mengalami downtime sama sekali. Koneksi baru langsung menggunakan konfigurasi baru.
Ini berbeda dari “graceful reload” di Nginx yang kadang masih menyebabkan beberapa request gagal selama proses transisi. Caddy menggunakan pendekatan yang lebih canggih dengan atomic config swap.
Cara Kerja Atomic Config Reload #
Proses reload Caddy (disederhanakan):
1. Konfigurasi baru diterima (via sinyal SIGHUP atau Admin API)
2. Caddy mem-parse dan memvalidasi konfigurasi baru
→ Jika konfigurasi tidak valid: BATALKAN reload, tetap pakai config lama
3. Caddy membuat "server instance" baru dengan konfigurasi baru
4. Caddy melakukan atomic swap:
→ Request baru → diterima oleh instance baru (konfigurasi baru)
→ Request yang sedang berjalan → selesai di instance lama (konfigurasi lama)
5. Setelah semua request lama selesai:
→ Instance lama dimatikan
→ Hanya instance baru yang berjalan
6. TLS certificates yang sudah ada dipertahankan
→ Tidak perlu request sertifikat baru jika domain tidak berubah
Hasil: ZERO downtime, tidak ada request yang gagal
Metode Reload #
Ada beberapa cara untuk memicu reload konfigurasi Caddy:
1. caddy reload (Command Line)
#
# Reload menggunakan Caddyfile default (/etc/caddy/Caddyfile)
caddy reload
# Reload dengan file konfigurasi spesifik
caddy reload --config /path/to/Caddyfile
# Reload dengan format tertentu
caddy reload --config /path/to/config.json --adapter json
# Reload dan paksa format Caddyfile
caddy reload --config /etc/caddy/Caddyfile --adapter caddyfile
2. systemctl reload caddy (via systemd)
#
# Cara yang paling umum di production Linux
sudo systemctl reload caddy
# Ini mengirim sinyal SIGHUP ke proses Caddy
# Caddy menangkap SIGHUP dan memicu reload konfigurasi
# Sama dengan 'caddy reload' tapi melalui systemd
# Cek status setelah reload
sudo systemctl status caddy
# Lihat apakah ada error di log
sudo journalctl -u caddy -n 50
3. Sinyal SIGHUP Langsung #
# Kirim SIGHUP ke proses Caddy
sudo kill -HUP $(pgrep caddy)
# Atau dengan pkill
sudo pkill -HUP caddy
# Atau dengan systemd send-signal
sudo systemctl kill --signal=SIGHUP caddy
4. Admin API /load Endpoint
#
# Reload via Admin API dengan Caddyfile
curl -X POST http://localhost:2019/load \
-H "Content-Type: text/caddyfile" \
--data-binary @/etc/caddy/Caddyfile
# Reload via Admin API dengan JSON
curl -X POST http://localhost:2019/load \
-H "Content-Type: application/json" \
--data-binary @/etc/caddy/config.json
# Script yang lebih robust dengan error handling
reload_via_api() {
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \
http://localhost:2019/load \
-H "Content-Type: text/caddyfile" \
--data-binary @/etc/caddy/Caddyfile)
HTTP_STATUS=$(echo "$RESPONSE" | tail -n1)
BODY=$(echo "$RESPONSE" | head -n-1)
if [ "$HTTP_STATUS" = "200" ]; then
echo "✓ Reload successful"
else
echo "✗ Reload failed (HTTP $HTTP_STATUS)"
echo "Error: $BODY"
return 1
fi
}
Validasi Sebelum Reload #
Sangat penting untuk memvalidasi konfigurasi baru sebelum melakukan reload di production:
# Validasi Caddyfile tanpa reload
caddy validate --config /etc/caddy/Caddyfile
# Output jika valid:
# Valid configuration
# Output jika tidak valid:
# run: loading initial config: loading new config: ...error detail...
# Workflow yang direkomendasikan:
deploy_config() {
local new_config="$1"
echo "[1] Validating new config..."
if ! caddy validate --config "$new_config"; then
echo "✗ Config validation failed, aborting"
return 1
fi
echo "✓ Config is valid"
echo "[2] Backing up current config..."
cp /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak.$(date +%Y%m%d_%H%M%S)
echo "[3] Applying new config..."
cp "$new_config" /etc/caddy/Caddyfile
echo "[4] Reloading Caddy..."
if ! sudo systemctl reload caddy; then
echo "✗ Reload failed, rolling back..."
cp /etc/caddy/Caddyfile.bak.$(date +%Y%m%d_%H%M%S) /etc/caddy/Caddyfile
sudo systemctl reload caddy
return 1
fi
echo "✓ Config deployed successfully"
}
Reload vs Restart vs Stop #
Perintah Downtime Sertifikat Koneksi Aktif Kapan Digunakan
─────────────────────────────────────────────────────────────────────────────
reload Tidak ada Dipertahankan Dilanjutkan Perubahan config rutin
restart Singkat Dipertahankan Diputus Masalah kritis,
(dari disk) (dibuka ulang) memory leak
stop + start Ya Dari disk Diputus Upgrade Caddy binary
# Reload (DIREKOMENDASIKAN untuk perubahan config)
sudo systemctl reload caddy
# Restart (perlu downtime singkat, tapi lebih bersih)
sudo systemctl restart caddy
# Stop kemudian start (misalnya setelah update binary)
sudo systemctl stop caddy
# (ganti binary di sini)
sudo systemctl start caddy
Rollback Konfigurasi #
Jika reload menyebabkan masalah, kamu perlu rollback ke konfigurasi sebelumnya:
# Rollback manual
sudo cp /etc/caddy/Caddyfile.bak /etc/caddy/Caddyfile
sudo systemctl reload caddy
# Script dengan auto-rollback jika health check gagal setelah reload
deploy_with_rollback() {
local new_config="$1"
local health_url="$2"
# Backup
cp /etc/caddy/Caddyfile /etc/caddy/Caddyfile.rollback
# Deploy
cp "$new_config" /etc/caddy/Caddyfile
sudo systemctl reload caddy
# Health check setelah reload
sleep 3
HTTP_STATUS=$(curl -sf -o /dev/null -w "%{http_code}" "$health_url" 2>/dev/null)
if [ "$HTTP_STATUS" != "200" ]; then
echo "✗ Health check failed after reload ($HTTP_STATUS), rolling back..."
cp /etc/caddy/Caddyfile.rollback /etc/caddy/Caddyfile
sudo systemctl reload caddy
echo "✓ Rolled back to previous config"
return 1
fi
echo "✓ Deployment successful, health check passed"
rm -f /etc/caddy/Caddyfile.rollback
}
Reload dalam CI/CD Pipeline #
# GitHub Actions example
name: Deploy Caddy Config
on:
push:
paths:
- 'caddy/Caddyfile'
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate Caddyfile
run: |
docker run --rm -v $(pwd)/caddy:/caddy caddy:2.8.4 \
caddy validate --config /caddy/Caddyfile
- name: Deploy to server
uses: appleboy/[email protected]
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_KEY }}
source: "caddy/Caddyfile"
target: "/etc/caddy/"
strip_components: 1
- name: Reload Caddy
uses: appleboy/[email protected]
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_KEY }}
script: |
# Validate sebelum reload
caddy validate --config /etc/caddy/Caddyfile
# Reload
sudo systemctl reload caddy
# Health check
sleep 3
curl -sf https://example.com/health || {
echo "Health check failed, check logs"
sudo journalctl -u caddy -n 20
exit 1
}
Monitoring Reload Events #
# Pantau log saat reload
sudo journalctl -u caddy -f | grep -i "reload\|config\|error"
# Contoh log sukses:
# INFO caddy loaded new config {"now": "..."}
# INFO caddy serving initial configuration
# Contoh log gagal:
# ERROR caddy failed to load config {"error": "..."}
# (Caddy tetap menggunakan konfigurasi lama)
# Script monitoring reload
watch_reload() {
echo "Watching Caddy reload events (Ctrl+C to stop)..."
sudo journalctl -u caddy -f 2>/dev/null | while read line; do
if echo "$line" | grep -qi "loaded new config"; then
echo "$(date): ✓ Config reload successful"
elif echo "$line" | grep -qi "failed to load\|error.*config"; then
echo "$(date): ✗ Config reload FAILED: $line"
# Kirim alert
fi
done
}
Ringkasan #
- Caddy reload adalah benar-benar zero-downtime: koneksi aktif dilanjutkan, konfigurasi baru langsung berlaku untuk koneksi baru.
- Selalu
caddy validateterlebih dahulu sebelum reload di production — konfigurasi tidak valid akan membatalkan reload dan Caddy tetap pakai config lama.sudo systemctl reload caddyadalah cara yang paling umum dan direkomendasikan untuk production di Linux.- Jika reload menyebabkan masalah, rollback mudah: restore file backup dan reload lagi.
- Gunakan
/loadendpoint Admin API untuk reload programatik dari deployment script atau CI/CD pipeline.- Buat backup Caddyfile sebelum setiap deployment — bisa dilakukan di deployment script dengan
cp Caddyfile Caddyfile.bak.$(date +%Y%m%d_%H%M%S).