Admin Endpoint #
Caddy memiliki built-in REST API yang berjalan di localhost:2019 secara default. Melalui API ini kamu bisa membaca konfigurasi aktif, mengubahnya secara real-time, memeriksa status sertifikat TLS, memantau upstream reverse proxy, dan bahkan melakukan reload konfigurasi — semua tanpa restart Caddy sama sekali.
Ini adalah salah satu fitur yang membedakan Caddy dari web server tradisional seperti Nginx. Di Nginx, kamu harus edit file konfigurasi dan jalankan nginx -s reload. Di Caddy, kamu bisa langsung POST JSON ke API dan konfigurasi langsung berubah secara atomic.
Default Behavior Admin API #
Saat Caddy pertama kali dijalankan:
Admin API mendengarkan di: localhost:2019
Hanya bisa diakses dari: 127.0.0.1 (loopback saja)
Autentikasi: Tidak ada (tapi hanya localhost yang bisa akses)
Protocol: HTTP (bukan HTTPS, karena lokal)
Endpoint utama:
GET /config/ → Baca seluruh konfigurasi aktif
POST /config/ → Replace seluruh konfigurasi
PATCH /config/ → Merge perubahan ke konfigurasi
DELETE /config/ → Hapus konfigurasi (Caddy berhenti serve)
GET /id/{id} → Baca bagian konfigurasi berdasarkan @id
PUT /id/{id} → Ganti elemen berdasarkan @id
DELETE /id/{id} → Hapus elemen berdasarkan @id
GET /pki/ca/ → Info PKI dan CA lokal
GET /reverse_proxy/upstreams/ → Status upstream reverse proxy
POST /load → Load config dari body (format apapun)
POST /stop → Hentikan Caddy secara graceful
Mengakses Admin API #
# Cek apakah Caddy berjalan dan admin API aktif
curl http://localhost:2019/config/
# Output: konfigurasi JSON lengkap yang sedang aktif
# Jika Caddy belum dikonfigurasi: {} atau null
# Pretty print dengan jq
curl -s http://localhost:2019/config/ | jq .
# Cek versi Caddy
curl -s http://localhost:2019/ | jq .
# Output contoh:
# {
# "status": "ok"
# }
Mengamankan Admin API #
Default konfigurasi (hanya localhost) sudah cukup aman untuk deployment biasa. Tapi ada beberapa skenario di mana kamu perlu konfigurasi lebih lanjut.
Mengubah Listen Address #
{
# Ubah port admin API
admin localhost:2020
# Atau bind ke semua interface (BERBAHAYA tanpa firewall!)
# admin 0.0.0.0:2019
# Atau matikan admin API sepenuhnya
# admin off
}
example.com {
reverse_proxy localhost:3000
}
Menonaktifkan Admin API #
Untuk production yang sudah stabil dan tidak perlu dynamic reconfiguration:
{
# Matikan admin API
# Caddy tidak bisa diubah konfigurasinya via API setelah ini
# Perlu restart untuk perubahan konfigurasi
admin off
}
example.com {
file_server {
root /var/www/html
}
}
Remote Admin dengan TLS #
Untuk mengakses admin API dari server lain secara aman:
{
admin {
# Listen di semua interface (bukan hanya localhost)
listen 0.0.0.0:2019
# Lindungi dengan TLS + client certificate
enforce_origin
origins "admin.example.com"
tls {
# Sertifikat untuk admin endpoint
cert_file /etc/caddy/admin-cert.pem
key_file /etc/caddy/admin-key.pem
# Require client certificate
client_auth {
mode require_and_verify
trusted_ca_certs_pem_files /etc/caddy/admin-ca.pem
}
}
}
}
Jangan pernah expose admin API ke internet tanpa proteksi yang memadai. Admin API tidak memiliki autentikasi bawaan — siapa saja yang bisa mengakses endpoint ini bisa mengubah konfigurasi Caddy sepenuhnya, termasuk menambahkan reverse proxy ke server internal atau mengubah sertifikat TLS.
Semua Endpoint Admin API #
/config/ — Konfigurasi
#
# READ: Baca konfigurasi lengkap
curl -s http://localhost:2019/config/ | jq .
# READ: Baca bagian tertentu dari konfigurasi
# Path mengikuti struktur JSON konfigurasi
curl -s http://localhost:2019/config/apps/http/servers/ | jq .
curl -s http://localhost:2019/config/apps/tls/ | jq .
curl -s http://localhost:2019/config/apps/http/servers/srv0/routes/ | jq .
# CREATE/REPLACE: Ganti konfigurasi lengkap
curl -X POST http://localhost:2019/config/ \
-H "Content-Type: application/json" \
-d '{ "apps": { "http": { "servers": { ... } } } }'
# PATCH: Tambahkan atau update bagian tertentu
curl -X PATCH http://localhost:2019/config/apps/http/servers/srv0/routes/ \
-H "Content-Type: application/json" \
-d '[{ ... route baru ... }]'
# DELETE: Hapus bagian konfigurasi
curl -X DELETE http://localhost:2019/config/apps/http/servers/srv0/routes/0
# Tambahkan elemen ke array
curl -X POST "http://localhost:2019/config/apps/http/servers/srv0/routes/" \
-H "Content-Type: application/json" \
-d '{ ... route baru ... }'
/reverse_proxy/upstreams/ — Status Upstream
#
# Lihat semua upstream dan statusnya
curl -s http://localhost:2019/reverse_proxy/upstreams/ | jq .
# Output contoh:
# [
# {
# "address": "backend-1:3000",
# "healthy": true,
# "num_requests": 12345,
# "fails": 0
# },
# {
# "address": "backend-2:3000",
# "healthy": false,
# "num_requests": 11982,
# "fails": 3
# }
# ]
/pki/ca/ — PKI dan Sertifikat
#
# Info CA lokal Caddy
curl -s http://localhost:2019/pki/ca/local | jq .
# Output contoh:
# {
# "id": "local",
# "name": "Caddy Local Authority",
# "root_common_name": "Caddy Local Authority - ...",
# "intermediate_common_name": "Caddy Local Authority - ...",
# "root": {
# "public_key_algorithm": "ECDSA",
# "subject": { ... },
# "not_before": "...",
# "not_after": "...",
# "pem": "-----BEGIN CERTIFICATE-----\n..."
# }
# }
# Export root certificate
curl -s http://localhost:2019/pki/ca/local | jq -r '.root.pem' \
> caddy-root-ca.pem
/load — Load Konfigurasi dari File
#
# Load konfigurasi dari Caddyfile (format otomatis terdeteksi)
curl -X POST http://localhost:2019/load \
-H "Content-Type: text/caddyfile" \
--data-binary @/etc/caddy/Caddyfile
# Load dari JSON
curl -X POST http://localhost:2019/load \
-H "Content-Type: application/json" \
--data-binary @/etc/caddy/config.json
/stop — Hentikan Caddy
#
# Hentikan Caddy secara graceful (tunggu request yang sedang diproses selesai)
curl -X POST http://localhost:2019/stop
# Setelah ini Caddy berhenti dan proses exit
# (Caddy akan di-restart oleh systemd jika dikonfigurasi dengan Restart=on-failure)
Navigasi Path di Admin API #
API menggunakan path yang mencerminkan struktur JSON konfigurasi. Ini sangat powerful tapi butuh pemahaman struktur:
/config/ → Root konfigurasi
/config/apps/ → Semua aplikasi
/config/apps/http/ → Aplikasi HTTP
/config/apps/http/servers/ → Semua server HTTP
/config/apps/http/servers/srv0/ → Server pertama
/config/apps/http/servers/srv0/routes/ → Routes server pertama
/config/apps/http/servers/srv0/routes/0/ → Route index 0
/config/apps/tls/ → Aplikasi TLS
/config/apps/tls/automation/ → Automasi sertifikat
/config/apps/tls/automation/policies/ → Policy sertifikat
/config/logging/ → Konfigurasi logging
# Contoh: Lihat semua routes
curl -s http://localhost:2019/config/apps/http/servers/srv0/routes/ | jq .
# Lihat route pertama
curl -s http://localhost:2019/config/apps/http/servers/srv0/routes/0 | jq .
# Lihat handler dalam route pertama
curl -s http://localhost:2019/config/apps/http/servers/srv0/routes/0/handle/ | jq .
Menggunakan @id untuk Referensi yang Lebih Mudah
#
Navigasi via index (routes/0, routes/1) mudah berubah jika konfigurasi dimodifikasi. Caddy mendukung custom @id untuk referensi yang lebih stabil:
{
"apps": {
"http": {
"servers": {
"srv0": {
"routes": [
{
"@id": "main-app-route",
"match": [{"host": ["example.com"]}],
"handle": [...]
},
{
"@id": "api-route",
"match": [{"host": ["api.example.com"]}],
"handle": [...]
}
]
}
}
}
}
}
# Akses via @id — tidak terpengaruh perubahan posisi
curl -s http://localhost:2019/id/main-app-route | jq .
curl -s http://localhost:2019/id/api-route | jq .
# Update route berdasarkan @id
curl -X PUT http://localhost:2019/id/main-app-route \
-H "Content-Type: application/json" \
-d '{ "@id": "main-app-route", "match": [...], "handle": [...] }'
Monitoring via Admin API #
#!/bin/bash
# Script monitoring sederhana menggunakan admin API
echo "=== Caddy Status ==="
echo ""
echo "--- Upstream Health ---"
curl -s http://localhost:2019/reverse_proxy/upstreams/ | jq -r \
'.[] | "\(.address): \(if .healthy then "✓ healthy" else "✗ UNHEALTHY" end) | requests: \(.num_requests) | fails: \(.fails)"'
echo ""
echo "--- TLS Certificates ---"
curl -s http://localhost:2019/config/apps/tls/ 2>/dev/null | jq -r \
'.automation.policies[]?.subjects[]? // "no policies"' 2>/dev/null || echo "TLS info not available"
echo ""
echo "--- Active Routes ---"
curl -s http://localhost:2019/config/apps/http/servers/srv0/routes/ 2>/dev/null | \
jq -r '.[] | "Route: \(.match[0].host // ["*"] | join(", "))"' 2>/dev/null || echo "No routes"
Ringkasan #
- Admin API default berjalan di
localhost:2019— hanya bisa diakses dari mesin itu sendiri, tidak perlu autentikasi untuk akses lokal.- Gunakan
admin offdi global options jika kamu tidak butuh dynamic reconfiguration di production untuk meminimalkan attack surface.- Jangan expose admin API ke internet tanpa TLS + client certificate — tidak ada autentikasi bawaan.
- Navigasi API menggunakan path JSON:
/config/apps/http/servers/srv0/routes/untuk melihat atau memodifikasi routes.- Gunakan
@iddi JSON konfigurasi untuk referensi yang stabil — lebih reliable dari index numerik yang bisa berubah.- Endpoint
/reverse_proxy/upstreams/sangat berguna untuk monitoring health status upstream secara real-time.