Best Practices

Best Practices #

Setelah memahami semua fitur Caddy, artikel terakhir ini merangkum best practices dari pengalaman komunitas dan operator production. Ini adalah checklist dan panduan untuk memastikan deployment Caddy berjalan andal, aman, dan mudah dikelola jangka panjang.

1. Keamanan #

TLS dan Sertifikat #

{
    # Gunakan email untuk notifikasi sertifikat
    email [email protected]
    
    # Matikan admin API jika tidak diperlukan
    # admin off
    
    # Atau batasi hanya localhost
    admin localhost:2019
}

example.com {
    # HSTS — jangan aktifkan preload sebelum yakin
    header Strict-Transport-Security "max-age=63072000; includeSubDomains"
    
    # Sembunyikan informasi server
    header -Server
    header -X-Powered-By
    
    # Security headers penting
    header X-Content-Type-Options "nosniff"
    header X-Frame-Options "SAMEORIGIN"
}

Principle of Least Privilege #

# Caddy tidak perlu berjalan sebagai root
# Gunakan user caddy dengan capability minimal

# Pastikan user caddy hanya bisa akses yang diperlukan
ls -la /etc/caddy/
# drwxr-x--- 2 root caddy 4096 ...
# -rw-r----- 1 root caddy 1234 Caddyfile

ls -la /var/lib/caddy/
# drwxr-x--- 3 caddy caddy 4096 ...

# Caddy tidak perlu akses ke direktori lain

Hindari Konfigurasi Berbahaya #

# JANGAN lakukan ini:
# (expose admin API ke internet)
{
    # admin 0.0.0.0:2019  ← SANGAT BERBAHAYA
}

# JANGAN expose backend langsung
# Backend seharusnya hanya bisa diakses dari localhost
# Bukan: bind backend ke 0.0.0.0
# Ya: bind backend ke 127.0.0.1

# JANGAN gunakan * sebagai Allow-Origin dengan credentials
# header Access-Control-Allow-Origin *  ← tidak bisa dengan credentials
# Gunakan origin spesifik

2. Performa #

Kompresi dan Caching #

example.com {
    # Selalu aktifkan kompresi
    encode gzip zstd
    
    root * /var/www/html
    
    # Cache optimal untuk aset statis
    @versioned path_regexp \.[a-f0-9]{8,}\.(js|css|woff2?)$
    header @versioned Cache-Control "public, max-age=31536000, immutable"
    
    @html path *.html /
    header @html Cache-Control "no-cache"
    
    file_server
}

Tuning Sistem #

# Naikkan limit file descriptors untuk Caddy
# /etc/security/limits.conf
# caddy soft nofile 65535
# caddy hard nofile 65535

# Atau via systemd override
sudo systemctl edit caddy
[Service]
LimitNOFILE=65535
# Kernel tuning untuk web server
# /etc/sysctl.conf
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_fin_timeout = 15
net.core.netdev_max_backlog = 65535

3. Monitoring #

Health Check Komprehensif #

#!/bin/bash
# health-check.sh — Jalankan via cron setiap 5 menit

SITES=(
    "https://example.com"
    "https://api.example.com/health"
    "https://admin.example.com"
)

ALERT_EMAIL="[email protected]"
SLACK_WEBHOOK="https://hooks.slack.com/..."

for url in "${SITES[@]}"; do
    STATUS=$(curl -sf -o /dev/null -w "%{http_code}" \
        --max-time 10 "$url" 2>/dev/null)
    
    if [ "$STATUS" != "200" ] && [ "$STATUS" != "301" ]; then
        msg="🚨 Health check FAILED: $url (HTTP $STATUS)"
        echo "$msg"
        
        # Email alert
        echo "$msg" | mail -s "Caddy Alert: $url DOWN" "$ALERT_EMAIL"
        
        # Slack alert
        curl -s -X POST "$SLACK_WEBHOOK" \
            -H "Content-Type: application/json" \
            -d "{\"text\": \"$msg\"}"
    fi
done

Metrics dengan Prometheus #

# Build Caddy dengan metrics module
xcaddy build \
    --with github.com/hairyhenderson/caddy-whoami  # Contoh

# Atau gunakan log-based metrics
# Parse access log dan generate Prometheus metrics

4. Backup dan Recovery #

Backup Konfigurasi #

#!/bin/bash
# backup-caddy.sh

BACKUP_DIR="/backup/caddy"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p "$BACKUP_DIR"

# Backup konfigurasi
cp /etc/caddy/Caddyfile "$BACKUP_DIR/Caddyfile.$DATE"

# Backup konfigurasi aktif via Admin API
curl -s http://localhost:2019/config/ | jq . > \
    "$BACKUP_DIR/config-live.$DATE.json"

# Backup sertifikat TLS
tar -czf "$BACKUP_DIR/certs.$DATE.tar.gz" \
    /var/lib/caddy/.local/share/caddy/certificates/

# Bersihkan backup lama (simpan 30 hari)
find "$BACKUP_DIR" -mtime +30 -delete

echo "✓ Backup selesai: $BACKUP_DIR"

Recovery Procedure #

# Jika Caddy gagal start setelah update konfigurasi:

# 1. Lihat error
sudo journalctl -u caddy -n 50

# 2. Rollback ke konfigurasi terakhir yang bekerja
sudo cp /etc/caddy/Caddyfile.bak /etc/caddy/Caddyfile

# 3. Atau restore dari backup
sudo cp /backup/caddy/Caddyfile.20240115_120000 /etc/caddy/Caddyfile

# 4. Validasi sebelum start
caddy validate --config /etc/caddy/Caddyfile

# 5. Start Caddy
sudo systemctl start caddy
sudo systemctl status caddy

5. Upgrade Strategy #

# Upgrade Caddy dengan aman

# 1. Baca changelog (cek breaking changes)
# https://github.com/caddyserver/caddy/releases

# 2. Test di staging dulu
# (ganti binary di staging, test semua fungsi)

# 3. Build binary baru (jika ada custom plugins)
xcaddy build v2.8.5 \  # Ganti dengan versi terbaru
    --with github.com/caddy-dns/cloudflare

# 4. Validasi config dengan binary baru
./caddy validate --config /etc/caddy/Caddyfile

# 5. Deploy ke production
sudo systemctl stop caddy
sudo cp /usr/bin/caddy /usr/bin/caddy.v2.8.4.bak  # Backup binary lama
sudo cp ./caddy /usr/bin/caddy
sudo systemctl start caddy

# 6. Verifikasi
caddy version
sudo systemctl status caddy
curl -f https://example.com/health

6. Production Checklist #

Keamanan:
  □ HTTPS aktif (otomatis oleh Caddy)
  □ HSTS dikonfigurasi
  □ Security headers (X-Content-Type-Options, X-Frame-Options, dll.)
  □ File sensitif diblokir (.env, .git, config files)
  □ Admin API hanya bisa diakses dari localhost
  □ Rate limiting dikonfigurasi untuk endpoint publik
  □ File Caddyfile mode 640 (tidak world-readable)
  □ Caddy berjalan sebagai user non-root

Performa:
  □ Kompresi diaktifkan (encode gzip zstd)
  □ Cache-Control headers dikonfigurasi untuk aset statis
  □ Health check dikonfigurasi untuk semua backend
  □ Timeout yang tepat untuk setiap backend
  □ Log sampling untuk traffic tinggi (jika diperlukan)

Monitoring:
  □ Access log aktif dan disimpan ke file
  □ Error log dikonfigurasi di level WARN
  □ Log rotation dikonfigurasi (roll_size, roll_keep_days)
  □ Alerting untuk health check failure
  □ Alerting untuk TLS renewal failure
  □ Upstream health monitoring

Backup & Recovery:
  □ Caddyfile di-backup secara otomatis (harian)
  □ Sertifikat TLS di-backup (mingguan)
  □ Runbook untuk common failures tersedia
  □ Procedure rollback sudah ditest
  □ Caddy berjalan via systemd dengan Restart=on-failure

Deployment:
  □ caddy validate di CI/CD pipeline
  □ Staging environment tersedia untuk testing
  □ Rollback plan tersedia
  □ Dokumentasi konfigurasi up-to-date

7. Dokumentasikan Konfigurasimu #

# Caddyfile yang baik memiliki komentar yang menjelaskan keputusan
# yang tidak obvious.
{
    # Email untuk notifikasi Let's Encrypt
    # Ganti dengan email tim operasi
    email [email protected]
    
    # Admin API hanya untuk localhost
    # JANGAN ubah ini ke 0.0.0.0 tanpa autentikasi
    admin localhost:2019
}

# ===== example.com — Main Website =====
# Reverse proxy ke aplikasi Node.js
# Backend: PM2 cluster di port 3000
# Last updated: 2024-01-15 oleh @username
example.com {
    # Security headers standar
    # Lihat: https://securityheaders.com untuk penjelasan
    header {
        Strict-Transport-Security "max-age=31536000; includeSubDomains"
        X-Content-Type-Options    "nosniff"
        X-Frame-Options           "SAMEORIGIN"
        -Server
    }
    
    encode gzip zstd
    
    # Aset statis langsung dari disk (lebih efisien)
    @static path /static/* /favicon.ico
    handle @static {
        root * /var/www/myapp
        file_server
        header Cache-Control "public, max-age=31536000, immutable"
    }
    
    # Semua lainnya ke backend Node.js
    handle {
        reverse_proxy localhost:3000 {
            health_uri /health
            health_interval 10s
        }
    }
}

Ringkasan #

  • Keamanan first: matikan admin API jika tidak diperlukan, selalu tambahkan security headers, blokir akses ke file sensitif, dan jalankan Caddy sebagai non-root.
  • Selalu kompresi dan cache: encode gzip zstd dan Cache-Control yang tepat bisa meningkatkan performa drastis dengan usaha minimal.
  • Monitor secara aktif: health check, alert untuk downtime dan certificate issues, dan log rotation yang proper mencegah kejutan di production.
  • Automasi dan validasi: caddy validate di CI/CD, backup otomatis, dan rollback yang tertest membuat deployment lebih aman.
  • Dokumentasikan keputusan: Caddyfile dengan komentar yang baik menghemat waktu tim saat troubleshooting bulan kemudian.
  • Test dulu di staging: hampir semua masalah production bisa terdeteksi di staging jika environment-nya cukup mirip.

← Sebelumnya: Tools Diagnostik   Kembali ke Awal: Apa Itu Caddy →


Penutup #

Selamat! Kamu telah menyelesaikan seluruh panduan Caddy Web Server ini. Dari memahami konsep dasar hingga deployment production yang aman, dari konfigurasi TLS otomatis hingga membangun plugin sendiri.

Caddy adalah web server yang luar biasa untuk era modern — sederhana di permukaan, powerful di dalamnya. Komunitas Caddy sangat aktif di caddy.community jika kamu butuh bantuan atau ingin berbagi pengalaman.

Selamat membangun!

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