Caddy Validate

Caddy Validate #

caddy validate adalah perintah yang memvalidasi file konfigurasi Caddy tanpa menjalankan server. Ini adalah alat yang sangat penting untuk workflow deployment yang aman — selalu validasi sebelum reload atau deploy ke production.

Cara Kerja caddy validate #

caddy validate --config /etc/caddy/Caddyfile

Proses validasi:
  1. Parse Caddyfile → JSON internal
  2. Cek syntax (apakah semua directive valid?)
  3. Cek semantic (apakah nilai-nilai masuk akal?)
  4. Provision modul secara dry-run
     (jalankan Provision() tapi tidak start server)
  5. Jalankan Validate() pada semua modul
  
Hasil:
  VALID   → Print "Valid configuration", exit code 0
  INVALID → Print error detail, exit code 1

Penggunaan Dasar #

# Validasi Caddyfile default (/etc/caddy/Caddyfile)
caddy validate

# Validasi file tertentu
caddy validate --config /etc/caddy/Caddyfile

# Validasi JSON config
caddy validate --config /etc/caddy/config.json --adapter json

# Validasi dari stdin
cat /etc/caddy/Caddyfile | caddy validate --config /dev/stdin

# Validasi dan cetak konfigurasi JSON yang dihasilkan
caddy validate --config /etc/caddy/Caddyfile && \
    caddy adapt --config /etc/caddy/Caddyfile | jq .

Output Validasi #

# Sukses:
$ caddy validate --config /etc/caddy/Caddyfile
Valid configuration

# Gagal (contoh 1 — syntax error):
$ caddy validate --config /etc/caddy/Caddyfile
parsing Caddyfile tokens: /etc/caddy/Caddyfile:5 - Error during parsing:
  unrecognized directive: rverse_proxy
  
# Gagal (contoh 2 — modul tidak ditemukan):
$ caddy validate --config /etc/caddy/Caddyfile
loading initial config: loading new config: http app module: 
  provisioning http handlers: handler module "dns" not registered

# Gagal (contoh 3 — nilai tidak valid):
$ caddy validate --config /etc/caddy/Caddyfile
loading initial config: loading new config: tls app:
  invalid ACME CA URL: ...

# Cek exit code untuk scripting
caddy validate --config /etc/caddy/Caddyfile
echo "Exit code: $?"  # 0 = valid, 1 = invalid

Integrasi di Pre-Deploy Script #

#!/bin/bash
# deploy.sh — Safe deployment dengan validation

set -e  # Exit on any error

CONFIG_FILE="/etc/caddy/Caddyfile"
NEW_CONFIG="$1"  # Path ke config baru

if [ -z "$NEW_CONFIG" ]; then
    echo "Usage: $0 <new-config-file>"
    exit 1
fi

echo "[1/4] Validating new configuration..."
if ! caddy validate --config "$NEW_CONFIG"; then
    echo "✗ Configuration validation FAILED"
    echo "  Deployment aborted. Current config is unchanged."
    exit 1
fi
echo "✓ Configuration is valid"

echo "[2/4] Backing up current configuration..."
BACKUP="/etc/caddy/Caddyfile.bak.$(date +%Y%m%d_%H%M%S)"
cp "$CONFIG_FILE" "$BACKUP"
echo "✓ Backup saved to $BACKUP"

echo "[3/4] Applying new configuration..."
cp "$NEW_CONFIG" "$CONFIG_FILE"

echo "[4/4] Reloading Caddy..."
if sudo systemctl reload caddy; then
    echo "✓ Caddy reloaded successfully"
else
    echo "✗ Reload failed, rolling back..."
    cp "$BACKUP" "$CONFIG_FILE"
    sudo systemctl reload caddy
    echo "✓ Rolled back to previous configuration"
    exit 1
fi

# Opsional: health check setelah deploy
sleep 3
HTTP_STATUS=$(curl -sf -o /dev/null -w "%{http_code}" https://example.com/ 2>/dev/null)
if [ "$HTTP_STATUS" = "200" ]; then
    echo "✓ Health check passed ($HTTP_STATUS)"
    echo "✓ Deployment successful!"
else
    echo "✗ Health check failed ($HTTP_STATUS), rolling back..."
    cp "$BACKUP" "$CONFIG_FILE"
    sudo systemctl reload caddy
    exit 1
fi

Validasi di Git Hooks #

Cegah commit atau push konfigurasi yang tidak valid:

# .git/hooks/pre-commit (atau pre-push)
#!/bin/bash

# Cek apakah ada Caddyfile yang dimodifikasi
CADDYFILES=$(git diff --cached --name-only | grep -E "Caddyfile|\.caddyfile$")

if [ -n "$CADDYFILES" ]; then
    echo "Validating Caddyfile changes..."
    
    for file in $CADDYFILES; do
        echo "  Checking: $file"
        if ! caddy validate --config "$file" 2>&1; then
            echo "✗ Caddyfile validation failed: $file"
            echo "  Please fix the configuration before committing."
            exit 1
        fi
    done
    
    echo "✓ All Caddyfiles are valid"
fi

exit 0
# Install hook
chmod +x .git/hooks/pre-commit

Validasi dalam GitHub Actions CI #

# .github/workflows/validate-caddy.yml
name: Validate Caddy Config

on:
  pull_request:
    paths:
      - 'caddy/**'
      - '**/Caddyfile'
      - '**/*.caddyfile'

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Install Caddy
        run: |
          sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
          curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | \
              sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
          curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | \
              sudo tee /etc/apt/sources.list.d/caddy-stable.list
          sudo apt update && sudo apt install caddy          
      
      - name: Validate all Caddyfiles
        run: |
          EXIT_CODE=0
          find . -name "Caddyfile" -o -name "*.caddyfile" | while read -r file; do
              echo "Validating: $file"
              if ! caddy validate --config "$file" 2>&1; then
                  echo "FAILED: $file"
                  EXIT_CODE=1
              else
                  echo "PASSED: $file"
              fi
          done
          exit $EXIT_CODE          
      
      - name: Comment PR with validation result
        if: failure()
        uses: actions/github-script@v7
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: '❌ **Caddyfile validation failed!** Please check the workflow logs for details.'
            })            

Validasi Konfigurasi dengan Substitusi Variable #

Ketika Caddyfile menggunakan environment variables, validasi perlu environment yang sesuai:

# Set environment variables yang diperlukan untuk validasi
export CF_API_TOKEN="test-token-for-validation"
export DB_HOST="localhost"
export ADMIN_PASSWORD_HASH='$2a$14$...'

# Validasi dengan environment variables tersedia
caddy validate --config /etc/caddy/Caddyfile

# Atau di CI/CD — set sebagai secrets GitHub Actions
# env:
#   CF_API_TOKEN: ${{ secrets.CF_API_TOKEN }}

Membandingkan Konfigurasi Lama dan Baru #

# Visualisasikan perbedaan konfigurasi
diff_configs() {
    local old_config="$1"
    local new_config="$2"
    
    # Konversi keduanya ke JSON yang normalized
    OLD_JSON=$(caddy adapt --config "$old_config" | jq -S .)
    NEW_JSON=$(caddy adapt --config "$new_config" | jq -S .)
    
    echo "$OLD_JSON" > /tmp/caddy-old.json
    echo "$NEW_JSON" > /tmp/caddy-new.json
    
    echo "=== Configuration Diff ==="
    diff --color=always /tmp/caddy-old.json /tmp/caddy-new.json || true
}

# Gunakan
diff_configs /etc/caddy/Caddyfile.bak /etc/caddy/Caddyfile.new

Ringkasan #

  • caddy validate mengeksekusi provision dan validate secara dry-run — ini lebih dari sekedar syntax check, modul benar-benar diinisialisasi secara parsial.
  • Integrasikan caddy validate di pre-commit hook agar konfigurasi yang invalid tidak pernah masuk ke repository.
  • Di CI/CD pipeline, jalankan validasi sebagai langkah mandatory sebelum deployment — buat pipeline gagal jika validasi gagal.
  • Gunakan exit code ($?) dari caddy validate dalam scripting: 0 = valid, 1 = invalid.
  • Untuk Caddyfile yang menggunakan environment variables, pastikan env vars tersedia saat menjalankan validasi, atau gunakan nilai placeholder untuk testing.
  • caddy adapt + jq -S menghasilkan JSON yang di-sort — berguna untuk diff yang bersih antara konfigurasi lama dan baru.

← Sebelumnya: Debug Konfigurasi   Berikutnya: Tools Diagnostik →


Validasi Perubahan Incremental #

Saat melakukan perubahan besar, validasi secara incremental:

# Buat copy konfigurasi untuk iterasi
cp /etc/caddy/Caddyfile /tmp/caddy-work.caddyfile

# Edit dan validasi setiap perubahan
vim /tmp/caddy-work.caddyfile
caddy validate --config /tmp/caddy-work.caddyfile

# Ketika sudah valid dan siap deploy
cp /tmp/caddy-work.caddyfile /etc/caddy/Caddyfile
sudo systemctl reload caddy

Otomatisasi Validasi dengan Makefile #

# Makefile untuk workflow Caddy

.PHONY: validate deploy rollback

CADDYFILE = /etc/caddy/Caddyfile
BACKUP_DIR = /backup/caddy

validate:
	@echo "Validating Caddyfile..."
	@caddy validate --config $(CADDYFILE) && echo "✓ Valid"

deploy: validate
	@echo "Deploying configuration..."
	@cp $(CADDYFILE) $(BACKUP_DIR)/Caddyfile.$(shell date +%Y%m%d_%H%M%S)
	@sudo systemctl reload caddy && echo "✓ Deployed"

rollback:
	@echo "Rolling back to latest backup..."
	@latest=$$(ls -t $(BACKUP_DIR)/Caddyfile.* | head -1); \
	    cp $$latest $(CADDYFILE) && \
	    sudo systemctl reload caddy && \
	    echo "✓ Rolled back to $$latest"

status:
	@systemctl status caddy --no-pager
	@echo ""
	@curl -s http://localhost:2019/reverse_proxy/upstreams/ | \
	    jq -r '.[] | "\(.address): \(if .healthy then "UP" else "DOWN" end)"'
# Gunakan
make validate   # Hanya validasi
make deploy     # Validasi + deploy
make rollback   # Rollback ke sebelumnya
make status     # Lihat status
About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact