xcaddy

xcaddy #

xcaddy adalah tool resmi dari tim Caddy untuk membangun binary Caddy kustom dengan plugin tambahan. Karena Caddy menggunakan pendekatan compile-time plugins (berbeda dari runtime plugins seperti Nginx), kamu perlu men-compile ulang Caddy setiap kali ingin menambahkan plugin baru.

xcaddy membuat proses ini sangat mudah — satu perintah cukup untuk mengunduh kode plugin, mengkompilasi, dan menghasilkan binary siap pakai.

Mengapa Compile-Time Plugins? #

Runtime plugins (Nginx, Apache):
  + Tidak perlu compile ulang saat tambah plugin
  + Bisa disable/enable plugin tanpa restart
  - Plugin berjalan sebagai proses/library terpisah
  - Overhead inter-process communication
  - ABI compatibility issues antar versi
  - Plugin yang buruk bisa crash server

Compile-time plugins (Caddy):
  + Single binary — tidak ada dependency eksternal
  + Plugin terintegrasi penuh, tidak ada overhead IPC
  + Type safety — compiler mendeteksi error lebih awal
  + Binary reproducible dan mudah didistribusikan
  - Perlu compile ulang untuk tambah/hapus plugin
  - Build process butuh Go toolchain

Instalasi xcaddy #

# Cara 1: Via go install (memerlukan Go terinstall)
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest

# Verifikasi instalasi
xcaddy version
# Output: xcaddy v0.4.x go1.22.x linux/amd64

# Cara 2: Download binary langsung
# https://github.com/caddyserver/xcaddy/releases

# Cara 3: Via package manager (beberapa distro)
# sudo apt install xcaddy  # Jika tersedia di repo

# Pastikan Go terinstall (minimal Go 1.21)
go version

Build Caddy dengan Satu Plugin #

# Format dasar
xcaddy build [versi_caddy] --with [nama_plugin]

# Build Caddy terbaru dengan satu plugin
xcaddy build --with github.com/caddy-dns/cloudflare

# Build versi spesifik Caddy
xcaddy build v2.8.4 --with github.com/caddy-dns/cloudflare

# Output: binary 'caddy' di direktori saat ini
ls -lh caddy
# -rwxr-xr-x 1 user user 35M Jan 15 14:30 caddy

# Verifikasi plugin tersedia
./caddy list-modules | grep cloudflare
# dns.providers.cloudflare

Build dengan Banyak Plugin #

# Build dengan multiple plugin sekaligus
xcaddy build \
    --with github.com/caddy-dns/cloudflare \
    --with github.com/mholt/caddy-ratelimit \
    --with github.com/caddyserver/cache-handler \
    --with github.com/greenpau/caddy-security

# Verifikasi semua plugin tersedia
./caddy list-modules | grep -E "cloudflare|rate_limit|cache|security"

Menentukan Versi Plugin #

# Plugin versi spesifik (menggunakan Go module version)
xcaddy build \
    --with github.com/caddy-dns/[email protected] \
    --with github.com/mholt/[email protected]

# Plugin dari branch tertentu
xcaddy build \
    --with github.com/example/caddy-plugin@main

# Plugin dari commit hash spesifik
xcaddy build \
    --with github.com/example/caddy-plugin@abc123def456

# Plugin dari local directory (untuk development)
xcaddy build \
    --with github.com/example/caddy-plugin=/path/to/local/plugin

Mengganti Binary yang Ada #

# Build binary baru
xcaddy build v2.8.4 \
    --with github.com/caddy-dns/cloudflare

# Stop Caddy sementara
sudo systemctl stop caddy

# Backup binary lama
sudo cp /usr/bin/caddy /usr/bin/caddy.bak

# Ganti dengan binary baru
sudo cp caddy /usr/bin/caddy
sudo chmod +x /usr/bin/caddy

# Verifikasi
caddy version
caddy list-modules | grep cloudflare

# Start Caddy kembali
sudo systemctl start caddy

Zero-Downtime Upgrade dengan caddy upgrade #

# Caddy punya built-in upgrade command
# tapi tidak support custom plugins

# Untuk upgrade dengan custom plugins, prosesnya:
# 1. Build binary baru dengan xcaddy
xcaddy build v2.8.4 \
    --with github.com/caddy-dns/cloudflare

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

# 3. Ganti binary (Caddy support graceful restart dengan SIGUSR1)
sudo systemctl stop caddy
sudo cp caddy /usr/bin/caddy
sudo systemctl start caddy

Docker Multi-Stage Build dengan xcaddy #

# Dockerfile
FROM caddy:2.8.4-builder AS builder

# Build Caddy dengan plugin yang diinginkan
RUN xcaddy build \
    --with github.com/caddy-dns/cloudflare \
    --with github.com/mholt/caddy-ratelimit

# Stage final: hanya binary yang diperlukan
FROM caddy:2.8.4

# Copy binary kustom ke image
COPY --from=builder /usr/bin/caddy /usr/bin/caddy

# Copy konfigurasi
COPY Caddyfile /etc/caddy/Caddyfile
# Build image
docker build -t my-caddy:latest .

# Verifikasi plugin di container
docker run --rm my-caddy:latest caddy list-modules | grep cloudflare

Build di CI/CD Pipeline #

# GitHub Actions workflow untuk build Caddy dengan plugins
name: Build Custom Caddy

on:
  push:
    branches: [main]
  workflow_dispatch:
    inputs:
      caddy_version:
        description: 'Caddy version'
        default: 'latest'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.22'
      
      - name: Install xcaddy
        run: go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
      
      - name: Build Caddy with plugins
        run: |
          xcaddy build ${{ github.event.inputs.caddy_version || 'latest' }} \
            --with github.com/caddy-dns/cloudflare \
            --with github.com/mholt/caddy-ratelimit \
            --output ./caddy-custom          
      
      - name: Test binary
        run: |
          ./caddy-custom version
          ./caddy-custom list-modules | grep -E "cloudflare|rate_limit"          
      
      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: caddy-custom-linux-amd64
          path: ./caddy-custom

Cross-Compilation #

# Build untuk platform berbeda
# Linux ARM64 (untuk Raspberry Pi, AWS Graviton, dll.)
GOOS=linux GOARCH=arm64 xcaddy build \
    --with github.com/caddy-dns/cloudflare

# Linux AMD64
GOOS=linux GOARCH=amd64 xcaddy build \
    --with github.com/caddy-dns/cloudflare

# macOS Apple Silicon
GOOS=darwin GOARCH=arm64 xcaddy build \
    --with github.com/caddy-dns/cloudflare

# Windows
GOOS=windows GOARCH=amd64 xcaddy build \
    --with github.com/caddy-dns/cloudflare

Troubleshooting Build Issues #

# Error: "module not found"
# Pastikan module path benar (cek GitHub repo)
go list -m github.com/caddy-dns/cloudflare@latest

# Error: Go version tidak kompatibel
# Install Go versi terbaru
# https://go.dev/dl/

# Error: build gagal karena dependency conflict
# Coba build dengan versi plugin yang lebih lama
xcaddy build --with github.com/example/[email protected]

# Lihat output build yang detail
XCADDY_DEBUG=1 xcaddy build --with github.com/caddy-dns/cloudflare

# Cache Go module untuk build yang lebih cepat
export GOMODCACHE=/tmp/go-modules
xcaddy build ...

Ringkasan #

  • xcaddy build --with [plugin] adalah cara standar untuk menambahkan plugin ke Caddy — satu perintah mengunduh, kompilasi, dan menghasilkan binary siap pakai.
  • Gunakan Docker multi-stage build dengan caddy:builder image untuk build yang reproducible dan isolated tanpa perlu install Go di host.
  • Selalu backup binary lama sebelum mengganti — cp /usr/bin/caddy /usr/bin/caddy.bak memungkinkan rollback instan jika ada masalah.
  • Untuk production, integrasikan xcaddy di CI/CD pipeline agar setiap update Caddy atau plugin menghasilkan binary yang sudah ditest.
  • Pin versi plugin yang digunakan (--with [email protected]) untuk build yang reproducible dan mencegah breaking changes dari plugin update.
  • Gunakan caddy list-modules untuk memverifikasi plugin berhasil terkompilasi ke dalam binary sebelum deploy ke production.

← Sebelumnya: Log Output   Berikutnya: Plugin Populer →


Menjaga Binary Tetap Up-to-date #

Salah satu tantangan dengan compiled plugins adalah mengelola update. Buat script sederhana untuk memudahkan proses update:

#!/bin/bash
# update-caddy.sh — Script untuk update Caddy dengan plugins yang sama

# Daftar plugins yang digunakan
PLUGINS=(
    "github.com/caddy-dns/cloudflare"
    "github.com/mholt/caddy-ratelimit"
)

# Build string --with untuk xcaddy
WITH_FLAGS=""
for plugin in "${PLUGINS[@]}"; do
    WITH_FLAGS="$WITH_FLAGS --with $plugin"
done

echo "Building Caddy with plugins..."
echo "Plugins: ${PLUGINS[*]}"

# Build binary baru
eval "xcaddy build latest $WITH_FLAGS --output /tmp/caddy-new"

# Verifikasi
echo ""
echo "New binary info:"
/tmp/caddy-new version
echo ""
echo "Modules:"
/tmp/caddy-new list-modules | grep -v "^standard"

# Konfirmasi sebelum deploy
read -p "Deploy? (y/N) " confirm
if [ "$confirm" = "y" ]; then
    sudo systemctl stop caddy
    sudo cp /tmp/caddy-new /usr/bin/caddy
    sudo systemctl start caddy
    echo "✓ Caddy updated successfully"
else
    echo "Deployment cancelled"
fi

xcaddy dengan Private Repository #

# Jika plugin ada di private repo (GitHub, GitLab, Bitbucket)
# Setup SSH atau token terlebih dahulu

# Untuk GitHub private repo dengan token
git config --global url."https://[email protected]/".insteadOf "https://github.com/"

# Build dengan private plugin
xcaddy build \
    --with github.com/company/private-caddy-plugin

# Environment variable GONOSUMCHECK jika perlu skip sum check
GONOSUMCHECK="github.com/company/*" xcaddy build \
    --with github.com/company/private-caddy-plugin
About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact