Reload Config

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 validate terlebih dahulu sebelum reload di production — konfigurasi tidak valid akan membatalkan reload dan Caddy tetap pakai config lama.
  • sudo systemctl reload caddy adalah cara yang paling umum dan direkomendasikan untuk production di Linux.
  • Jika reload menyebabkan masalah, rollback mudah: restore file backup dan reload lagi.
  • Gunakan /load endpoint 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).

← Sebelumnya: Config API   Berikutnya: Caddy JSON →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact