Admin Endpoint #
Kemampuan untuk memperbarui konfigurasi secara instan tanpa mengganggu koneksi aktif adalah salah satu fitur paling revolusioner dari web server modern. Caddy memimpin inovasi ini dengan menyediakan REST API bawaan (built-in) secara default yang memungkinkan kita membaca, memanipulasi, dan memuat ulang seluruh struktur konfigurasi server secara real-time. Berbeda dengan web server tradisional seperti Nginx atau Apache yang mengandalkan proses pembacaan ulang file konfigurasi fisik di disk dan penggantian proses pekerja (worker process), Caddy memperlakukan konfigurasi sebagai dokumen data memori yang dinamis. Kita akan membahas secara mendalam arsitektur Admin API Caddy, batasan perilaku bawaannya, opsi pengamanan lanjutan menggunakan Mutual TLS (mTLS), pemetaan JSON Path, serta penggunaan penanda objek khusus (@id) untuk otomatisasi manajemen server tingkat lanjut.
Arsitektur REST API Caddy vs Tradisional #
Sebelum kita mendalami perintah-perintah teknis, kita perlu memahami filosofi di balik arsitektur Admin API Caddy dan bagaimana ini berbeda dari pendekatan server web tradisional:
+--------------------------------------------------------------------------------+
| Arsitektur Kontrol Server |
+--------------------------------------------------------------------------------+
| Model Tradisional (Nginx / Apache): |
| [File Config Disk] --(Edit Manual)--> [reload Command] --(Restart Workers)-->|
| |
| Model Modern Caddy: |
| [Aplikasi / CLI] --(HTTP REST API)--> [Caddy Admin API] --(Atomic Swap RAM)-->|
+--------------------------------------------------------------------------------+
Pada server web tradisional seperti Nginx, alur kerja pembaruan konfigurasi selalu melibatkan interaksi berkas fisik:
- Administrator sistem mengedit file konfigurasi (misalnya
nginx.conf) di disk lokal. - Perintah
nginx -s reloaddijalankan untuk memicu sinyal sistem. - Master process Nginx memvalidasi file tersebut, kemudian menelurkan worker process baru dengan konfigurasi baru, sementara worker process lama perlahan ditutup setelah menyelesaikan request aktif (graceful draining).
Meskipun model ini terbukti stabil selama bertahun-tahun, ia memiliki batasan besar dalam ekosistem cloud modern yang dinamis. Proses penulisan file ke disk membatasi kemampuan otomatisasi programatik dari luar server, memicu masalah izin akses file (file permissions), dan berisiko memunculkan inkonsistensi status (race conditions) jika beberapa skrip mencoba mengubah konfigurasi secara bersamaan.
Caddy memecahkan masalah ini dengan meniadakan keharusan menulis ke berkas fisik untuk pembaruan konfigurasi. Di dalam Caddy, terdapat mesin runtime yang dikontrol oleh dokumen JSON terpadu di memori RAM. Ketika kita melakukan panggilan API HTTP ke Caddy, perubahan tersebut divalidasi langsung di memori, dan jika valid, langsung diterapkan menggunakan operasi pertukaran atomik (atomic swap). Hal ini membuat Caddy menjadi pilihan utama untuk platform SaaS multi-tenant, infrastruktur skala dinamis (auto-scaling), dan integrasi otomatisasi tingkat tinggi.
Perilaku Bawaan (Default Behavior) Admin API #
Secara bawaan (default), begitu kita menjalankan proses Caddy, Admin API akan otomatis aktif dan mendengarkan koneksi pada alamat berikut:
- Alamat Dengar (Listen Address):
http://localhost:2019 - Protokol: HTTP (tanpa enkripsi TLS, karena hanya melayani lalu lintas internal).
- Batasan Antarmuka (Interface Binding): Terikat ketat pada antarmuka loopback (
127.0.0.1untuk IPv4 dan[::1]untuk IPv6). - Otentikasi: Tidak membutuhkan kata sandi atau token otentikasi secara bawaan. Keamanan endpoint ini sepenuhnya bersandar pada isolasi jaringan lokal (hanya proses yang berjalan di dalam mesin yang sama yang dapat mengirimkan paket data ke port
2019).
Bagi sebagian besar skenario deployment biasa, perilaku bawaan ini sudah sangat aman. Karena hanya terikat pada loopback interface, upaya akses dari luar server menggunakan alamat IP publik akan secara otomatis ditolak pada tingkat kernel sistem operasi, bahkan tanpa adanya aturan firewall tambahan.
Mengamankan Admin API #
Meskipun konfigurasi bawaan aman untuk satu mesin, skenario produksi sering kali menuntut kita untuk mengubah perilaku ini—baik untuk memperketat keamanan dengan mematikan API sepenuhnya, memindahkan port, atau membuka akses jarak jauh (remote access) untuk kebutuhan klaster terdistribusi.
1. Mengubah Listen Address #
Kita dapat memindahkan lokasi Admin API dengan mendefinisikannya pada blok opsi global (global options) di bagian paling atas Caddyfile. Kita bisa memindahkannya ke port TCP lokal yang berbeda, atau menggunakan soket Unix (Unix domain socket) yang memberikan kontrol hak akses lebih ketat pada sistem operasi berbasis Linux:
# Mengubah port Admin API ke 2020 lokal
{
admin localhost:2020
}
example.com {
reverse_proxy localhost:3000
}
Jika kita ingin menggunakan Unix Domain Socket untuk keamanan ekstra berbasis perizinan file sistem operasi:
# Menggunakan Unix Socket untuk kontrol akses berbasis file system
{
admin unix//run/caddy-admin.sock
}
example.com {
file_server
}
Dengan menggunakan soket Unix, kita bisa mengatur kepemilikan file /run/caddy-admin.sock dan izin aksesnya (permission 0600) menggunakan utilitas sistem operasi Linux sehingga hanya pengguna sistem tertentu (seperti root atau pengguna caddy) yang dapat mengontrol server.
2. Menonaktifkan Admin API #
Pada server produksi yang bersifat statis—di mana konfigurasi Caddy hanya diperbarui secara manual oleh tim operasi melalui pembaruan berkas Caddyfile dan tidak ada integrasi API eksternal—kita sangat direkomendasikan untuk menonaktifkan Admin API sepenuhnya guna meminimalkan celah keamanan (attack surface):
# BENAR: Menonaktifkan Admin API secara total di produksi statis
{
admin off
}
example.com {
file_server {
root /var/www/html
}
}
[!WARNING] Ketika kita menetapkan
admin off, Caddy akan mematikan mesin API internalnya sepenuhnya. Konsekuensi dari tindakan ini adalah perintah-perintah CLI bawaan Caddy seperticaddy reload,caddy stop, ataucaddy adapttidak akan dapat berfungsi dari terminal lokal server tersebut. Hal ini terjadi karena utilitas baris perintah Caddy secara internal berkomunikasi dengan proses Caddy utama melalui port Admin API lokal. Jika API mati, pembaruan konfigurasi hanya dapat dilakukan dengan cara mematikan proses Caddy (kill/systemctl stop) dan menyalakannya kembali dari awal.
3. Remote Admin dengan TLS Dua Arah (mTLS) #
Dalam arsitektur klaster di mana kita memiliki beberapa node server Caddy yang dikendalikan oleh satu server pusat (control plane), kita perlu membuka akses Admin API agar dapat diakses dari jaringan luar.
Jangan pernah mengaktifkan binding API ke interface publik (seperti admin 0.0.0.0:2019) tanpa mekanisme pengamanan. Karena Admin API Caddy tidak memiliki sistem otentikasi berbasis username/password, siapa pun di internet yang menemukan port tersebut terbuka akan langsung mendapatkan kendali penuh atas server kita.
Untuk mengamankan akses jarak jauh secara mutlak, kita harus menggunakan enkripsi HTTPS yang dipadukan dengan otentikasi sertifikat klien (Mutual TLS / mTLS). Dengan metode ini, Caddy hanya akan menerima permintaan jika klien mengirimkan sertifikat digital yang valid dan telah ditandatangani oleh Otoritas Sertifikat (Certificate Authority) internal tepercaya kita:
# BENAR: Mengamankan Remote Admin API dengan mTLS kustom
{
admin {
# Dengarkan di semua interface pada port 2019
listen :2019
# Validasi header Origin HTTP untuk mencegah serangan CSRF
enforce_origin
origins control-plane.internal.net
# Konfigurasi keamanan TLS
tls {
# Sertifikat HTTPS server untuk port admin ini
cert_file /etc/caddy/certs/admin-server.crt
key_file /etc/caddy/certs/admin-server.key
# Wajibkan otentikasi sertifikat klien (mTLS)
client_auth {
mode require_and_verify
trusted_ca_certs_pem_files /etc/caddy/certs/internal-ca.crt
}
}
}
}
example.com {
reverse_proxy localhost:8080
}
Dalam konfigurasi di atas:
listen :2019membuat API dapat diakses dari jaringan luar.enforce_originmemastikan request yang dikirim melalui browser memiliki header origin yang cocok dengancontrol-plane.internal.netguna mencegah serangan Cross-Origin Resource Sharing (CORS) / CSRF.client_authdengan moderequire_and_verifymenjamin bahwa setiap klien yang memanggil API harus menyerahkan sertifikat klien (client certificate) yang diterbitkan oleh CA internal di/etc/caddy/certs/internal-ca.crt. Klien tanpa sertifikat tersebut akan ditolak langsung pada fase jabat tangan TLS (TLS handshake) sebelum request HTTP sempat diproses.
Semua Endpoint Admin API #
Caddy menyediakan sekumpulan endpoint RESTful terstruktur untuk berinteraksi dengan berbagai subsistem server. Berikut adalah daftar lengkap beserta skenario penggunaannya:
1. /config/ — Manipulasi Konfigurasi Aktif
#
Endpoint ini merupakan pintu gerbang utama untuk membaca dan mengubah dokumen konfigurasi aktif. Dokumen dikembalikan dalam format JSON terstruktur.
Membaca Konfigurasi Aktif (GET) #
Kita dapat memanggil endpoint ini dengan metode GET untuk mendapatkan dump konfigurasi aktif server kita. Kita dapat menggunakan utilitas jq untuk memformat output JSON agar mudah dibaca manusia:
# Membaca seluruh konfigurasi aktif
curl -s http://localhost:2019/config/ | jq .
Mengganti Seluruh Konfigurasi (POST) #
Metode POST ke root endpoint /config/ akan mengganti seluruh dokumen konfigurasi aktif secara instan dengan payload JSON baru yang kita kirimkan di body request:
# Ganti seluruh konfigurasi dengan file JSON lokal
curl -s -X POST http://localhost:2019/config/ \
-H "Content-Type: application/json" \
--data-binary @/etc/caddy/new_config.json
Memperbarui Subset Konfigurasi (PATCH) #
Jika kita hanya ingin memperbarui sebagian kecil konfigurasi tanpa mengunggah ulang seluruh file JSON, kita dapat menggunakan metode PATCH. Metode ini akan menggabungkan (merge) objek yang kita kirimkan ke dalam struktur konfigurasi aktif:
# Melakukan merge konfigurasi
curl -s -X PATCH http://localhost:2019/config/apps/http/servers/srv0/ \
-H "Content-Type: application/json" \
-d '{"read_timeout": "10s"}'
2. /reverse_proxy/upstreams/ — Status Upstream Real-Time
#
Endpoint ini sangat krusial bagi tim DevOps untuk memantau status kesehatan klaster backend yang berada di belakang reverse proxy Caddy. Caddy akan mengembalikan daftar seluruh server upstream aktif beserta status kesehatannya (healthy status), jumlah request yang sedang berjalan, dan akumulasi kegagalan pasif yang tercatat:
# Membaca status kesehatan backend upstream
curl -s http://localhost:2019/reverse_proxy/upstreams/ | jq .
Contoh payload keluaran dari Caddy:
[
{
"address": "10.0.1.15:8080",
"healthy": true,
"num_requests": 142,
"fails": 0
},
{
"address": "10.0.1.16:8080",
"healthy": false,
"num_requests": 0,
"fails": 3
}
]
3. /pki/ca/ — Memantau Infrastruktur CA Internal
#
Caddy memiliki manajemen Public Key Infrastructure (PKI) terintegrasi yang secara otomatis mengelola sertifikat lokal. Melalui endpoint ini, kita dapat memeriksa status Certificate Authority (CA) lokal Caddy, serta mengekspor sertifikat Root CA untuk diinstal pada perangkat klien:
# Memeriksa daftar CA lokal Caddy
curl -s http://localhost:2019/pki/ca/ | jq .
# Mengekspor sertifikat Root CA lokal Caddy ke bentuk file PEM
curl -s http://localhost:2019/pki/ca/local | jq -r '.root.pem' > caddy-root.crt
4. /load — Memuat Ulang Konfigurasi dari File
#
Endpoint /load digunakan untuk memuat ulang konfigurasi baru. Endpoint ini menerima input berupa file mentah. Keunggulan utama endpoint ini adalah Caddy secara otomatis mendeteksi format input berdasarkan header Content-Type yang kita kirimkan. Kita bisa mengirimkan dokumen JSON mentah atau file Caddyfile secara langsung:
# Memuat konfigurasi baru menggunakan berkas Caddyfile langsung
curl -s -X POST http://localhost:2019/load \
-H "Content-Type: text/caddyfile" \
--data-binary @/etc/caddy/Caddyfile
5. /stop — Menghentikan Jalannya Server
#
Endpoint ini mengirimkan sinyal penghentian server secara aman (graceful shutdown). Caddy akan berhenti menerima koneksi baru, menyelesaikan seluruh request yang saat ini sedang diproses secara bertahap, kemudian menghentikan proses runtime Caddy sepenuhnya:
# Menghentikan server Caddy secara graceful
curl -s -X POST http://localhost:2019/stop
Navigasi Path di Admin API #
Dokumen konfigurasi Caddy dimodelkan sebagai pohon objek JSON tunggal. Jalur URL pada Admin API dirancang untuk mencerminkan struktur pohon tersebut secara tepat. Ini memberikan fleksibilitas luar biasa karena kita dapat memanipulasi elemen terkecil sekalipun di dalam konfigurasi secara langsung melalui modifikasi path URL.
Mari kita perhatikan representasi struktur pohon JSON Caddy berikut:
[Root Konfigurasi] (/config/)
|
[apps] (/config/apps/)
|
[http] (/config/apps/http/)
|
[servers] (/config/apps/http/servers/)
|
[srv0] (/config/apps/http/servers/srv0/)
|
+--------+--------+
| |
[routes] [listen]
(/srv0/routes/) (/srv0/listen/)
Sebagai contoh, jika kita ingin berinteraksi dengan daftar rute (routing table) pada server HTTP pertama Caddy, jalurnya adalah /config/apps/http/servers/srv0/routes/.
Jika struktur rute kita berupa array JSON, kita dapat menargetkan elemen spesifik di dalam array menggunakan indeks numerik (dimulai dari 0 untuk elemen pertama):
# Membaca rute pertama (indeks 0) pada server srv0
curl -s http://localhost:2019/config/apps/http/servers/srv0/routes/0 | jq .
# Menghapus rute kedua (indeks 1) secara instan dari memori
curl -s -X DELETE http://localhost:2019/config/apps/http/servers/srv0/routes/1
Menggunakan @id untuk Referensi Stabil
#
Meskipun navigasi berbasis indeks numerik (seperti /routes/0) sangat mudah digunakan, metode ini memiliki kelemahan kritis ketika digunakan di lingkungan otomatisasi dinamis. Jika kita memiliki aplikasi eksternal yang sering menambah atau menghapus rute secara dinamis, indeks rute lainnya akan otomatis bergeser.
Sebagai contoh, jika kita menghapus rute di indeks 0, rute yang sebelumnya berada di indeks 1 akan bergeser menjadi indeks 0. Jika skrip otomatisasi kita mengirimkan request PUT ke /routes/1 tanpa menyadari pergeseran ini, kita akan secara tidak sengaja menimpa konfigurasi rute yang salah (race condition).
Untuk mengatasi masalah ini, Caddy memperkenalkan fitur Identifier Unik (@id). Kita dapat menyisipkan properti kustom @id bernilai string unik pada objek mana pun di dalam konfigurasi JSON kita. Begitu objek tersebut memiliki @id, kita dapat mengakses, mengubah, atau menghapusnya secara langsung melalui endpoint /id/{nama_id}, terlepas dari posisi indeks objek tersebut di dalam dokumen JSON.
Contoh Penyisipan @id pada Konfigurasi JSON
#
{
"apps": {
"http": {
"servers": {
"srv0": {
"routes": [
{
"@id": "rute-aplikasi-utama",
"match": [{"host": ["example.com"]}],
"handle": [
{
"handler": "file_server",
"root": "/var/www/main"
}
]
},
{
"@id": "rute-api-backend",
"match": [{"host": ["api.example.com"]}],
"handle": [
{
"handler": "reverse_proxy",
"upstreams": [{"dial": "localhost:8080"}]
}
]
}
]
}
}
}
}
}
Mengakses dan Memodifikasi Menggunakan @id
#
Dengan konfigurasi di atas, kita tidak perlu peduli apakah rute API berada di indeks ke-0, ke-1, atau ke-10. Kita dapat memanipulasinya langsung melalui jalurnya yang unik:
# ANTI-PATTERN: Mengakses objek menggunakan indeks numerik di skrip otomatisasi
curl -s http://localhost:2019/config/apps/http/servers/srv0/routes/1 | jq .
# BENAR: Mengakses objek secara konsisten menggunakan ID unik
curl -s http://localhost:2019/id/rute-api-backend | jq .
Kita juga dapat memperbarui konfigurasi objek tersebut secara aman menggunakan metode PUT ke endpoint ID tersebut:
# Memperbarui upstream target untuk API secara aman
curl -s -X PUT http://localhost:2019/id/rute-api-backend \
-H "Content-Type: application/json" \
-d '{
"@id": "rute-api-backend",
"match": [{"host": ["api.example.com"]}],
"handle": [
{
"handler": "reverse_proxy",
"upstreams": [{"dial": "10.0.1.50:8080"}]
}
]
}'
Jika aplikasi kita perlu menghapus rute API tersebut dari rotasi secara instan:
# Menghapus rute secara instan menggunakan ID unik
curl -s -X DELETE http://localhost:2019/id/rute-api-backend
Scripting dan Monitoring Praktis #
Kita dapat memanfaatkan Admin API Caddy untuk membuat skrip pemantauan otomatis (automated monitoring script) guna menjaga kesehatan klaster produksi kita. Berikut adalah contoh skrip Bash lengkap yang dapat dipasang di server sebagai cron job atau diintegrasikan ke sistem monitoring eksternal:
#!/bin/bash
# Skrip pemantauan kesehatan runtime Caddy via Admin API
CADDY_API="http://localhost:2019"
CHECK_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$CADDY_API/")
if [ "$CHECK_STATUS" -ne 200 ]; then
echo "✗ ERROR: Caddy Admin API tidak merespons (HTTP $CHECK_STATUS)!"
exit 1
fi
echo "=== LAPORAN STATUS RUNTIME CADDY ==="
echo "Tanggal Pemeriksaan: $(date)"
echo "-------------------------------------"
# 1. Periksa Stabilitas Server Upstream
echo "[1] Status Kesehatan Server Backend:"
UPSTREAMS_JSON=$(curl -s "$CADDY_API/reverse_proxy/upstreams/")
if [ "$UPSTREAMS_JSON" = "[]" ] || [ -z "$UPSTREAMS_JSON" ]; then
echo " - Tidak ada backend reverse proxy yang dikonfigurasi saat ini."
else
# Parsing log JSON untuk melihat detail status kesehatan
echo "$UPSTREAMS_JSON" | jq -r '.[] | " -> Upstream: \(.address) | Sehat: \(.healthy) | Request Aktif: \(.num_requests) | Error Tercatat: \(.fails)"'
fi
# 2. Periksa Domain Aktif
echo ""
echo "[2] Daftar Domain yang Sedang Dilayani (Rute Aktif):"
# Mengambil daftar host matchers dari konfigurasi server srv0
curl -s "$CADDY_API/config/apps/http/servers/srv0/routes" 2>/dev/null | \
jq -r '.[]? | select(.match != null) | " -> Host: \(.match[0].host[]?)"' 2>/dev/null || echo " - Tidak ada rute host terdaftar."
# 3. Validasi CA Sertifikat Lokal
echo ""
echo "[3] Detail CA Lokal Caddy:"
curl -s "$CADDY_API/pki/ca/local" 2>/dev/null | \
jq -r '" -> Nama CA: \(.name)\n -> Berlaku Sejak: \(.root.not_before)\n -> Kedaluwarsa Pada: \(.root.not_after)"' 2>/dev/null || echo " - Informasi CA lokal tidak tersedia."
echo "-------------------------------------"
echo "Pemeriksaan Selesai."
Skrip di atas melakukan panggilan HTTP ke Admin API lokal, memvalidasi respons, mem-parsing data status kesehatan backend proxy menggunakan jq, menyaring rute domain aktif, dan menampilkan status sertifikat CA lokal. Kita dapat mengarahkan keluaran skrip ini ke dalam sistem monitoring seperti Grafana Loki atau mengirim notifikasi Slack jika terdeteksi properti "healthy": false pada salah satu server backend.
Ringkasan #
- REST API Bawaan: Caddy menyediakan REST API bawaan yang berjalan di
localhost:2019secara default untuk memodifikasi konfigurasi secara instan tanpa restart.- Keamanan Loopback: Secara bawaan, API terikat pada loopback interface sehingga hanya dapat diakses secara lokal dari dalam mesin itu sendiri.
- Menonaktifkan API: Di produksi statis, kita disarankan menggunakan
admin offpada opsi global guna meminimalkan celah keamanan (attack surface).- Remote Access Secure: Jika harus membuka akses API jarak jauh, gunakan HTTPS dengan mTLS (
client_auth require_and_verify) agar terenkripsi dan terotentikasi kuat.- URL Refleksi JSON: URL path pada Admin API merefleksikan struktur pohon JSON dari konfigurasi Caddy (misalnya
/config/apps/http/servers/).- Kelebihan
@id: Gunakan penanda unik@idpada objek konfigurasi untuk menghindari kesalahan indeks numerik yang bergeser saat melakukan manipulasi dinamis.- Metrik Real-Time: Endpoint
/reverse_proxy/upstreams/menyediakan metrik kesehatan dan koneksi aktif backend secara real-time untuk keperluan observabilitas.