Compile dari Source

Compile Caddy dari Source #

Binary standar Caddy yang diunduh dari situs resmi atau diinstall via APT/COPR hanya menyertakan modul bawaan yang mencakup fungsi web server umum. Namun banyak use case penting membutuhkan modul yang tidak disertakan secara default — terutama DNS provider modules yang diperlukan untuk mendapatkan wildcard certificate, atau plugin pihak ketiga seperti rate limiter, autentikasi OAuth, dan sebagainya.

Untuk semua kasus tersebut, kamu perlu compile Caddy sendiri. Tool resmi yang disediakan tim Caddy untuk ini adalah xcaddy — sebuah CLI sederhana yang menyembunyikan kompleksitas proses build Go menjadi satu perintah yang mudah diingat.

Mengapa Perlu Compile Sendiri? #

Binary resmi Caddy — modul yang tersedia:
  ✓ http.handlers.reverse_proxy
  ✓ http.handlers.file_server
  ✓ http.handlers.encode (gzip, zstd)
  ✓ http.handlers.basicauth
  ✓ http.handlers.rewrite, redirect, headers
  ✓ tls.issuance.acme (Let's Encrypt, ZeroSSL)
  ✓ tls.issuance.internal (localhost CA)
  ✓ Dan semua handler standar lainnya

  ✗ dns.providers.cloudflare    → Perlu compile
  ✗ dns.providers.route53       → Perlu compile
  ✗ dns.providers.digitalocean  → Perlu compile
  ✗ dns.providers.gcloud        → Perlu compile
  ✗ http.handlers.rate_limit    → Perlu compile
  ✗ http.handlers.security      → Perlu compile (OAuth2, OIDC)
  ✗ http.handlers.cache         → Perlu compile
  ✗ Dan semua plugin komunitas lainnya

Kapan kamu wajib compile sendiri:

  • Wildcard certificate (*.example.com) yang membutuhkan DNS-01 challenge
  • Platform yang perlu DNS provider tertentu
  • Kebutuhan rate limiting per-IP atau per-key
  • Autentikasi OAuth2/OIDC via caddy-security
  • HTTP caching yang lebih canggih dari bawaan

Prasyarat: Go #

xcaddy membutuhkan Go versi minimal 1.21. Jika server production kamu tidak punya Go terinstall (dan sebaiknya memang tidak), solusinya adalah compile di mesin lain (CI/CD, laptop developer) dan hasilkan binary yang tinggal di-copy ke server.

Jika kamu perlu menginstall Go di mesin build:

# Cek apakah Go sudah ada
go version

# Install di Ubuntu/Debian
sudo apt install -y golang-go

# Install versi spesifik langsung dari golang.org (lebih disarankan)
# Ganti versi sesuai kebutuhan
GO_VERSION="1.22.3"
wget "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz"

# Hapus instalasi Go yang mungkin sudah ada
sudo rm -rf /usr/local/go

# Extract ke /usr/local
sudo tar -C /usr/local -xzf "go${GO_VERSION}.linux-amd64.tar.gz"

# Tambahkan ke PATH
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
echo 'export PATH=$PATH:$(go env GOPATH)/bin' >> ~/.bashrc
source ~/.bashrc

# Verifikasi
go version
# Output: go version go1.22.3 linux/amd64

Instalasi xcaddy #

# Install xcaddy menggunakan go install
# xcaddy akan diinstall ke $GOPATH/bin (biasanya ~/go/bin)
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest

# Pastikan $GOPATH/bin ada di PATH
export PATH=$PATH:$(go env GOPATH)/bin

# Tambahkan ke .bashrc/.zshrc agar permanen
echo 'export PATH=$PATH:$(go env GOPATH)/bin' >> ~/.bashrc

# Verifikasi
xcaddy version
# Output: xcaddy v0.3.x
# go version go1.22.x ...

Alternatif: install xcaddy dari package manager di beberapa distro:

# Fedora/RHEL (jika tersedia di repository)
sudo dnf install xcaddy

# Atau gunakan binary release langsung dari GitHub
# https://github.com/caddyserver/xcaddy/releases

Build Caddy dengan xcaddy #

Build Standar (Tanpa Plugin Tambahan) #

# Build versi Caddy terbaru tanpa plugin tambahan
# Hasilnya setara dengan binary resmi, tapi di-compile sendiri
xcaddy build

# Binary bernama 'caddy' dibuat di direktori saat ini
ls -lh caddy
# Output: -rwxr-xr-x 1 user user 48M ... caddy

# Cek versi
./caddy version

# Lihat semua modul yang tersedia di binary ini
./caddy list-modules

Build dengan Satu Plugin #

# Contoh: Build dengan DNS provider Cloudflare
# Diperlukan untuk wildcard certificate via DNS-01 challenge
xcaddy build \
    --with github.com/caddy-dns/cloudflare

# Verifikasi modul tersedia
./caddy list-modules | grep cloudflare
# Output: dns.providers.cloudflare

Build dengan Banyak Plugin Sekaligus #

xcaddy build \
    --with github.com/caddy-dns/cloudflare \
    --with github.com/caddy-dns/route53 \
    --with github.com/mholt/caddy-ratelimit \
    --with github.com/greenpau/caddy-security \
    --with github.com/caddyserver/cache-handler

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

Build Versi Caddy Tertentu #

Untuk deployment production, sangat disarankan untuk pin ke versi Caddy yang spesifik agar build bisa direproduksi:

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

# Build dari commit hash spesifik (untuk testing)
xcaddy build abc1234def5678 \
    --with github.com/caddy-dns/cloudflare

# Build dari branch (JANGAN untuk production)
xcaddy build main \
    --with github.com/caddy-dns/cloudflare

Pin Versi Plugin untuk Reproducible Build #

Di production, kamu tidak ingin plugin diupdate secara tidak terduga antara satu build dan berikutnya. Selalu pin versi plugin ke commit hash atau semver tag yang spesifik:

# ANTI-PATTERN: Menggunakan versi latest tanpa pin
xcaddy build v2.8.4 \
    --with github.com/caddy-dns/cloudflare

# BENAR: Pin ke tag semver spesifik
xcaddy build v2.8.4 \
    --with github.com/caddy-dns/[email protected]

# Cara mendapatkan commit hash terbaru suatu plugin:
go list -m -json github.com/caddy-dns/cloudflare@latest | jq .Version

# Atau cek di halaman GitHub plugin yang bersangkutan

Membuat Build Script untuk Dokumentasi #

Simpan perintah build sebagai script yang di-commit ke repository:

#!/bin/bash
# build-caddy.sh
# Jalankan script ini untuk compile ulang Caddy dengan versi dan plugin yang tepat

set -e

CADDY_VERSION="v2.8.4"
CLOUDFLARE_VERSION="v0.0.0-20240101123456-abc1234def56"
RATELIMIT_VERSION="v0.0.0-20240101234567-def5678abc12"

echo "Building Caddy ${CADDY_VERSION}..."

xcaddy build "${CADDY_VERSION}" \
    --with "github.com/caddy-dns/cloudflare@${CLOUDFLARE_VERSION}" \
    --with "github.com/mholt/caddy-ratelimit@${RATELIMIT_VERSION}"

echo "Build complete:"
./caddy version
./caddy list-modules | grep -E "cloudflare|rate_limit"

Deploy Binary Hasil Build #

ke Server yang Sudah Ada #

# Setelah xcaddy build selesai, caddy binary ada di direktori saat ini

# Jika Caddy diinstall via APT (binary ada di /usr/bin/caddy):
# Step 1: Stop Caddy
sudo systemctl stop caddy

# Step 2: Backup binary lama (untuk rollback jika ada masalah)
sudo cp /usr/bin/caddy /usr/bin/caddy.backup.$(date +%Y%m%d)

# Step 3: Copy binary baru
sudo cp ./caddy /usr/bin/caddy
sudo chmod +x /usr/bin/caddy

# Step 4: Verifikasi binary baru
caddy version
caddy list-modules | grep cloudflare

# Step 5: Start Caddy
sudo systemctl start caddy
sudo systemctl status caddy

# Jika ada masalah, rollback:
# sudo cp /usr/bin/caddy.backup.$(date +%Y%m%d) /usr/bin/caddy
# sudo systemctl start caddy

ke Server Baru (Tanpa Package Manager) #

# Copy binary ke server via scp
scp ./caddy user@server-ip:/tmp/caddy

# Di server:
sudo mv /tmp/caddy /usr/local/bin/caddy
sudo chmod +x /usr/local/bin/caddy

# Buat direktori yang diperlukan
sudo mkdir -p /etc/caddy /var/lib/caddy /var/log/caddy

# Buat user caddy jika belum ada
sudo useradd --system --shell /bin/false caddy

# Set ownership
sudo chown -R caddy:caddy /var/lib/caddy /var/log/caddy

# Buat Caddyfile
sudo nano /etc/caddy/Caddyfile

# Setup systemd service
# (Install caddy.service dari https://github.com/caddyserver/dist)
sudo curl -o /etc/systemd/system/caddy.service \
  https://raw.githubusercontent.com/caddyserver/dist/master/init/caddy.service

sudo systemctl daemon-reload
sudo systemctl enable --now caddy

Dockerfile Multi-Stage untuk Docker #

Cara terbaik untuk menggunakan Caddy dengan plugin di Docker adalah multi-stage build. Ini menghasilkan image final yang ringan — hanya binary yang di-compile, tanpa toolchain Go.

# Dockerfile.caddy

# ─── Stage 1: Build ───────────────────────────────────────────────────────────
# Gunakan image builder resmi yang sudah berisi xcaddy + toolchain Go
FROM caddy:2.8.4-builder AS builder

# Argumen untuk versi plugin (bisa di-override saat build)
ARG CLOUDFLARE_VERSION=v0.0.0-20240101123456-abc1234
ARG RATELIMIT_VERSION=v0.0.0-20240101234567-def5678

# Compile Caddy dengan plugin
RUN xcaddy build v2.8.4 \
    --with github.com/caddy-dns/cloudflare@${CLOUDFLARE_VERSION} \
    --with github.com/mholt/caddy-ratelimit@${RATELIMIT_VERSION}

# ─── Stage 2: Final Image ─────────────────────────────────────────────────────
# Mulai dari image Caddy yang bersih
FROM caddy:2.8.4

# Ganti binary standar dengan yang baru di-compile
COPY --from=builder /usr/bin/caddy /usr/bin/caddy

# Verifikasi (akan dijalankan saat docker build)
RUN caddy version && caddy list-modules | grep cloudflare
# Build image
docker build -f Dockerfile.caddy -t my-caddy:2.8.4 .

# Build dengan versi plugin yang berbeda
docker build -f Dockerfile.caddy \
  --build-arg CLOUDFLARE_VERSION=v0.0.0-20240201000000-xyz789 \
  -t my-caddy:2.8.4-cf-updated .

# Verifikasi
docker run --rm my-caddy:2.8.4 caddy list-modules | grep cloudflare

Integrasi CI/CD — GitHub Actions #

Untuk tim yang mengelola binary Caddy kustom, CI/CD adalah cara terbaik untuk memastikan build yang konsisten dan terdokumentasi.

# .github/workflows/build-caddy.yml

name: Build Custom Caddy

on:
  push:
    tags:
      - 'caddy-v*'
  workflow_dispatch:   # Allow manual trigger

jobs:
  build-binary:
    name: Build Caddy Binary
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        
      - name: Setup 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
        run: |
          xcaddy build v2.8.4 \
            --with github.com/caddy-dns/[email protected] \
            --with github.com/mholt/[email protected]
                      
      - name: Verify build
        run: |
          ./caddy version
          ./caddy list-modules | grep cloudflare
          ./caddy list-modules | grep rate_limit
                    
      - name: Upload binary as artifact
        uses: actions/upload-artifact@v4
        with:
          name: caddy-linux-amd64
          path: ./caddy

  build-docker:
    name: Build Docker Image
    runs-on: ubuntu-latest
    needs: build-binary
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        
      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
          
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./Dockerfile.caddy
          push: true
          tags: |
            ghcr.io/${{ github.repository }}/caddy:latest
            ghcr.io/${{ github.repository }}/caddy:${{ github.ref_name }}            

Build untuk Plugin Lokal (Development Plugin) #

Jika kamu sedang mengembangkan plugin Caddy sendiri, xcaddy bisa menggunakan path lokal:

# Struktur direktori
my-caddy-plugin/
  ├── go.mod
  ├── go.sum
  └── plugin.go

# Build dengan plugin dari path lokal
xcaddy build \
    --with github.com/yourname/caddy-myplugin=./my-caddy-plugin

# Mix dengan plugin dari GitHub
xcaddy build \
    --with github.com/caddy-dns/cloudflare \
    --with github.com/yourname/caddy-myplugin=./my-caddy-plugin

# Replace modul dengan versi lokal (untuk patch plugin yang sudah ada)
xcaddy build \
    --with github.com/caddyserver/caddy/v2=../caddy \
    --with github.com/caddy-dns/cloudflare=../cloudflare

Troubleshooting Build #

Go Version Terlalu Lama #

# Error: "requires Go 1.21 or later"
go version  # Cek versi saat ini

# Upgrade Go sesuai panduan instalasi di atas

xcaddy Tidak Ditemukan #

# Error: "xcaddy: command not found"

# Cek GOPATH
go env GOPATH

# Tambahkan ke PATH
export PATH=$PATH:$(go env GOPATH)/bin

# Verifikasi xcaddy ada di sana
ls $(go env GOPATH)/bin/xcaddy

Plugin Tidak Kompatibel dengan Versi Caddy #

# Error: "ambiguous import: found package in ..."
# atau: "cannot use ... (type ...) as type ..."

# Ini biasanya berarti versi plugin tidak kompatibel dengan versi Caddy
# Cek halaman GitHub plugin untuk versi yang kompatibel
# Coba tanpa pin versi dulu untuk mendapatkan versi terbaru
xcaddy build v2.8.4 \
    --with github.com/caddy-dns/cloudflare  # Tanpa @version

Build Lambat #

# xcaddy mengunduh dependencies setiap build pertama
# Untuk mempercepat, set GOPROXY ke cache lokal atau gunakan Go module cache

# Aktifkan Go module cache
export GOPATH=$HOME/go
export GOMODCACHE=$GOPATH/pkg/mod

# xcaddy juga mendukung caching via GOCACHE
export GOCACHE=$HOME/.cache/go-build

Ringkasan #

  • xcaddy adalah tool resmi untuk compile Caddy dengan plugin — install via go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest.
  • Flag --with untuk menambahkan plugin; bisa digunakan berkali-kali untuk multiple plugin sekaligus.
  • Selalu pin versi plugin (@v0.0.0-...) untuk reproducible build di production — versi tanpa pin bisa berubah kapan saja.
  • Simpan build script di repository untuk dokumentasi dan kemudahan compile ulang.
  • Untuk Docker, gunakan multi-stage Dockerfile dengan caddy:builder sebagai build stage — image final tetap ringan.
  • caddy list-modules untuk verifikasi plugin berhasil disertakan di binary hasil build.
  • Compile bisa dilakukan di mesin build/CI — tidak perlu Go di server production.

← Sebelumnya: Docker Compose   Berikutnya: Struktur Caddyfile →

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