Caddy JSON #
Caddy JSON adalah format konfigurasi native Caddy — semua konfigurasi, termasuk Caddyfile, pada akhirnya dikonversi ke JSON sebelum digunakan oleh Caddy. Caddyfile adalah lapisan abstraksi yang ramah manusia, tapi di balik layar Caddy selalu bekerja dengan JSON.
Memahami Caddy JSON membuka kemungkinan yang tidak bisa dilakukan dengan Caddyfile: konfigurasi yang sangat granular, integrasi dengan Config API, penggunaan fitur-fitur yang belum ada shortcut-nya di Caddyfile, dan pembuatan tooling yang menghasilkan konfigurasi Caddy secara programatik.
Mengapa Memahami Caddy JSON #
Caddyfile: Caddy JSON:
──────────────────────────────────────────────────
Ramah manusia Native format Caddy
Mudah ditulis Lebih verbose tapi lebih lengkap
Kurang ekspresif Akses semua opsi modul
Tidak cocok untuk Cocok untuk Config API
programmatic use dan tooling
Cocok untuk Bisa di-generate programatik
manusia (misalnya dari database)
Struktur Top-Level Caddy JSON #
{
"admin": { ... }, // Konfigurasi admin API
"logging": { ... }, // Konfigurasi logging global
"storage": { ... }, // Storage untuk sertifikat TLS
"apps": {
"http": { ... }, // Aplikasi HTTP server
"tls": { ... }, // Aplikasi TLS / cert management
"layer4": { ... }, // TCP/UDP proxy (opsional)
"dns": { ... } // DNS server (opsional)
}
}
Mengkonversi Caddyfile ke JSON #
Cara termudah memahami struktur JSON adalah mengkonversi Caddyfile yang sudah kamu buat:
# Konversi Caddyfile ke JSON
caddy adapt --config /etc/caddy/Caddyfile --adapter caddyfile
# Pretty print dengan jq
caddy adapt --config /etc/caddy/Caddyfile --adapter caddyfile | jq .
# Simpan ke file
caddy adapt --config /etc/caddy/Caddyfile --adapter caddyfile \
| jq . > /etc/caddy/config.json
Contoh Konversi #
Caddyfile:
example.com {
reverse_proxy localhost:3000
encode gzip
log {
output file /var/log/caddy/access.log
format json
}
}
Hasil JSON (caddy adapt output, disederhanakan):
{
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [":443", ":80"],
"routes": [
{
"match": [{"host": ["example.com"]}],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"handler": "encode",
"encodings": {"gzip": {}}
}
]
},
{
"handle": [
{
"handler": "reverse_proxy",
"upstreams": [{"dial": "localhost:3000"}]
}
]
}
]
}
],
"terminal": true
}
],
"logs": {
"logger_names": {
"example.com": "log0"
}
}
}
}
},
"tls": {
"automation": {
"policies": [
{
"subjects": ["example.com"],
"issuers": [
{
"module": "acme",
"ca": "https://acme-v02.api.letsencrypt.org/directory"
}
]
}
]
}
}
},
"logging": {
"logs": {
"log0": {
"writer": {
"output": "file",
"filename": "/var/log/caddy/access.log"
},
"encoder": {"format": "json"}
}
}
}
}
Anatomi Routes #
Routes adalah jantung dari konfigurasi HTTP Caddy:
{
"routes": [
{
"@id": "optional-stable-id",
"match": [
{
"host": ["example.com", "www.example.com"],
"path": ["/api/*"],
"method": ["GET", "POST"],
"header": {
"Content-Type": ["application/json"]
},
"remote_ip": {
"ranges": ["192.168.0.0/16"]
}
}
],
"handle": [
{
"handler": "headers",
"response": {
"set": {
"X-Custom-Header": ["value"]
}
}
},
{
"handler": "reverse_proxy",
"upstreams": [
{"dial": "backend:3000"}
]
}
],
"terminal": true
}
]
}
Handler Types #
// Static file server
{
"handler": "file_server",
"root": "/var/www/html",
"index_names": ["index.html"],
"browse": {}
}
// Reverse proxy
{
"handler": "reverse_proxy",
"upstreams": [
{"dial": "backend-1:3000"},
{"dial": "backend-2:3000"}
],
"load_balancing": {
"selection_policy": {
"policy": "least_conn"
}
},
"health_checks": {
"active": {
"uri": "/health",
"interval": "10s",
"timeout": "5s",
"expect_status": 200
},
"passive": {
"fail_duration": "30s",
"max_fails": 3
}
}
}
// Static response
{
"handler": "static_response",
"status_code": 301,
"headers": {
"Location": ["https://example.com{http.request.uri}"]
}
}
// Encode (compression)
{
"handler": "encode",
"encodings": {
"gzip": {},
"zstd": {}
},
"minimum_length": 1024
}
Konfigurasi TLS dalam JSON #
{
"apps": {
"tls": {
"automation": {
"policies": [
{
"subjects": ["example.com", "*.example.com"],
"issuers": [
{
"module": "acme",
"ca": "https://acme-v02.api.letsencrypt.org/directory",
"email": "[email protected]",
"challenges": {
"dns": {
"provider": {
"name": "cloudflare",
"api_token": "{env.CF_API_TOKEN}"
}
}
}
},
{
"module": "acme",
"ca": "https://acme.zerossl.com/v2/DV90",
"external_account": {
"key_id": "{env.ZEROSSL_KEY_ID}",
"mac_key": "{env.ZEROSSL_MAC_KEY}"
}
}
]
},
{
"subjects": ["internal.company.com"],
"issuers": [
{
"module": "internal"
}
]
}
]
}
}
}
}
Admin dan Logging dalam JSON #
{
"admin": {
"listen": "localhost:2019",
"enforce_origin": false,
"origins": ["localhost:2019"]
},
"logging": {
"logs": {
"default": {
"writer": {
"output": "stderr"
},
"encoder": {
"format": "console"
},
"level": "INFO"
},
"access": {
"writer": {
"output": "file",
"filename": "/var/log/caddy/access.log",
"roll_size_mb": 50,
"roll_keep": 5,
"roll_keep_days": 30
},
"encoder": {
"format": "json"
},
"include": ["http.log.access"]
}
}
}
}
Menggunakan JSON Langsung #
# Jalankan Caddy dengan JSON config
caddy run --config /etc/caddy/config.json --adapter json
# Atau jika JSON adalah format native (tidak perlu --adapter):
caddy run --config /etc/caddy/config.json
# Load JSON via Admin API
curl -X POST http://localhost:2019/load \
-H "Content-Type: application/json" \
--data-binary @/etc/caddy/config.json
Kapan Menggunakan JSON vs Caddyfile #
Gunakan CADDYFILE ketika:
✓ Konfigurasi ditulis dan dipelihara oleh manusia
✓ Tim tidak familiar dengan format JSON verbose
✓ Use case standar (reverse proxy, file server, dll.)
✓ Tidak butuh integrasi programatik
✓ Untuk sebagian besar deployment production sehari-hari
Gunakan JSON ketika:
✓ Konfigurasi di-generate secara programatik
✓ Integrasi dengan Config API (platform multi-tenant)
✓ Butuh fitur yang belum ada shortcut-nya di Caddyfile
✓ Tooling atau infrastruktur yang menghasilkan config
✓ Testing dan debugging konfigurasi detail
✓ Kubernetes CRD atau Terraform provider yang generate JSON
Ringkasan #
- Caddy JSON adalah format native — semua Caddyfile dikonversi ke JSON sebelum digunakan. Gunakan
caddy adaptuntuk melihat JSON yang dihasilkan dari Caddyfile.- Struktur top-level:
apps(berisihttp,tls),admin,logging, danstorage.- Routes terdiri dari
match(kondisi),handle(handlers), danterminal(apakah stop matching setelah route ini cocok).- Gunakan
@iddi routes untuk referensi stabil yang bisa digunakan dengan Config API endpoint/id/{id}.- JSON lebih verbose dari Caddyfile tapi memberikan akses ke semua opsi modul yang mungkin tidak ada shortcut-nya di Caddyfile.
- Untuk sebagian besar kebutuhan, Caddyfile sudah lebih dari cukup — gunakan JSON hanya ketika memang diperlukan (programmatic generation, tooling, advanced config).