Format Log #
Caddy menyediakan beberapa format log bawaan dan kemampuan kustomisasi yang cukup dalam — kamu bisa memilih field mana yang disertakan, mengubah nama field, memfilter informasi sensitif, dan bahkan menulis format kustom untuk kompatibilitas dengan sistem parsing yang sudah ada.
Format yang Tersedia #
json → Setiap log entry adalah objek JSON satu baris
Cocok untuk: production, log aggregation, parsing programatik
console → Format teks manusia-readable dengan warna (jika terminal)
Cocok untuk: development, debugging interaktif
single_field → Satu field JSON spesifik diekstrak sebagai string
Cocok untuk: integrasi dengan sistem yang hanya butuh satu nilai
JSON Format dengan Field Selector #
Kamu bisa mengontrol field mana saja yang muncul di log JSON menggunakan sub-encoder filter:
example.com {
log {
output file /var/log/caddy/access.log
format filter {
# Gunakan encoder json sebagai base
wrap json
# Hapus field yang tidak diperlukan
fields {
# Hapus request headers (bisa sangat besar)
request>headers delete
# Hapus info TLS detail (jika tidak diperlukan)
request>tls delete
# Hapus response headers kecuali Content-Type
resp_headers>Content-Encoding delete
resp_headers>Server delete
}
}
}
file_server { root /var/www/html }
}
Menghapus Data Sensitif dari Log #
Sangat penting untuk tidak mencatat informasi sensitif seperti password, token, atau data pribadi:
example.com {
log {
output file /var/log/caddy/access.log
format filter {
wrap json
fields {
# Hash IP address untuk privasi (GDPR compliance)
request>remote_ip hash
# Hapus header Authorization (berisi token/password)
request>headers>Authorization delete
# Hapus header Cookie (berisi session token)
request>headers>Cookie delete
# Hapus query parameter yang mungkin berisi password
# (gunakan query_replace atau custom handler untuk ini)
}
}
}
reverse_proxy backend:3000
}
Transformasi Nilai #
example.com {
log {
output file /var/log/caddy/access.log
format filter {
wrap json
fields {
# Hash nilai field (satu arah, tidak bisa di-decode)
request>remote_ip hash
# Replace dengan nilai statis
request>headers>Authorization replace "[REDACTED]"
# Delete field sepenuhnya
request>tls delete
}
}
}
file_server
}
Format Console Kustom #
Format console menggunakan template string untuk mengontrol tampilan:
example.com {
log {
output stderr
format console
# Output default:
# 2024/01/15 14:30:45.123 INFO handled request ... {request: {...}}
}
}
Single Field Format #
Untuk integrasi dengan sistem yang hanya memproses satu nilai:
example.com {
log {
output file /var/log/caddy/combined.log
# Ambil hanya field 'msg' sebagai output
format single_field msg
}
}
Format Mirip Apache/Nginx Combined Log #
Untuk kompatibilitas dengan tools yang sudah familiar dengan format Apache/Nginx:
example.com {
log {
output file /var/log/caddy/access.log
# Format yang menghasilkan log mirip Apache Combined Log Format:
# 203.0.113.1 - - [15/Jan/2024:14:30:45 +0700] "GET /path HTTP/2.0" 200 1234
format transform `{request.remote_ip} - - [{ts}] "{request.method} {request.uri} {request.proto}" {status} {size}` {
time_format "02/Jan/2006:15:04:05 -0700"
}
}
file_server
}
Multi-Output Log (Log ke Beberapa Tempat Sekaligus) #
{
# Tidak ada built-in multi-output di Caddy
# Tapi bisa menggunakan named pipes atau log shipper
}
# Solusi 1: Gunakan tee dengan named pipe
# mkfifo /tmp/caddy-log-pipe
# tee /var/log/caddy/access.log < /tmp/caddy-log-pipe | \
# /usr/bin/logger -t caddy & # Kirim ke syslog juga
# Solusi 2: Log ke stdout, pipe ke multiple destinations
# Caddyfile: output stdout
# Di shell: caddy run 2>/dev/null | tee /var/log/caddy/access.log | logstash-forwarder
Log Format untuk Berbagai Kebutuhan #
Format untuk Elasticsearch/OpenSearch #
example.com {
log {
output file /var/log/caddy/access.log
format filter {
wrap json
fields {
# Hapus headers untuk mengurangi ukuran dokumen
request>headers delete
request>tls delete
resp_headers delete
}
}
}
}
Filebeat config untuk ingest ke Elasticsearch:
# /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
paths:
- /var/log/caddy/access.log
json.keys_under_root: true
json.overwrite_keys: true
processors:
- timestamp:
field: ts
layouts:
- UNIX_MS
output.elasticsearch:
hosts: ["https://elasticsearch:9200"]
index: "caddy-access-%{+yyyy.MM.dd}"
Format untuk Prometheus/Grafana #
# Hitung metrics dari log untuk Prometheus
# (atau gunakan plugin metrics Caddy)
# Script yang membaca log dan expose metrics
cat > /usr/local/bin/caddy-log-metrics.sh << 'EOF'
#!/bin/bash
LOG_FILE="/var/log/caddy/access.log"
METRICS_FILE="/var/lib/prometheus/caddy_metrics.prom"
# Hitung request count per status code
STATUS_COUNTS=$(cat "$LOG_FILE" | jq '.status' | sort | uniq -c)
cat > "$METRICS_FILE" << METRICS
# HELP caddy_http_requests_total Total HTTP requests
# TYPE caddy_http_requests_total counter
$(echo "$STATUS_COUNTS" | awk '{print "caddy_http_requests_total{status=\""$2"\"} "$1}')
METRICS
EOF
chmod +x /usr/local/bin/caddy-log-metrics.sh
# Jalankan via cron setiap menit
Log Rotation Manual #
Selain rotation otomatis bawaan Caddy, kamu juga bisa menggunakan logrotate:
# /etc/logrotate.d/caddy
/var/log/caddy/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 caddy caddy
# Setelah rotate, kirim sinyal USR1 ke Caddy untuk reopen file
# (Caddy mendukung USR1 untuk log rotation)
postrotate
systemctl kill --signal=USR1 caddy 2>/dev/null || true
endscript
}
Ringkasan #
- Gunakan
format filter { wrap json }untuk mengontrol field mana yang muncul di log JSON — hapus header sensitif (Authorization,Cookie) dan field besar yang tidak dibutuhkan.- Hash IP address (
request>remote_ip hash) di log untuk compliance dengan regulasi privasi seperti GDPR.- Format JSON standar adalah yang paling fleksibel — bisa diparse oleh Elasticsearch, Loki, Datadog, dan hampir semua log aggregation tool tanpa konfigurasi tambahan.
- Gunakan
logrotatebersama signalUSR1untuk rotation eksternal, atau konfigurasiroll_sizedanroll_keepbawaan Caddy untuk rotation otomatis.- Untuk debugging sementara, format
consolelebih mudah dibaca manusia — kembalikan kejsonsetelah selesai troubleshoot.- Selalu filter data sensitif sebelum log ditulis ke disk — jauh lebih mudah mencegah pencatatan data sensitif daripada membersihkannya setelah tersimpan.
← Sebelumnya: Error Log Berikutnya: Log Output →
Format Log yang Kompatibel dengan GoAccess #
GoAccess adalah analyzer log web real-time yang populer. Agar GoAccess bisa membaca log Caddy dalam format JSON:
# Install GoAccess
sudo apt install goaccess # Ubuntu/Debian
# Buat file konfigurasi GoAccess untuk Caddy JSON log
cat > ~/.goaccessrc << 'EOF'
log-format CADDY
EOF
# Jalankan GoAccess dengan log Caddy
# Format CADDY perlu didefinisikan di goaccess.conf:
# log-format {"ts":%dT%t,"request":{"remote_ip":"%h","method":"%m","uri":"%U","proto":"%H"},"status":%s,"size":%b,"duration":%T}
# Atau gunakan opsi custom format:
goaccess /var/log/caddy/access.log \
--log-format='{"ts":%^,"request":{"remote_ip":"%h"%^,"method":"%m","uri":"%U"%^},"status":%s,"size":%b}' \
--output report.html
Menambahkan Field Kustom ke Log #
example.com {
# Tambahkan request ID ke setiap request
header X-Request-ID {http.request.uuid}
log {
output file /var/log/caddy/access.log
format json
# Request ID otomatis muncul dalam log jika response header di-set
}
reverse_proxy backend:3000
}
Field kustom dari response headers backend juga akan tercatat di log jika menggunakan format JSON penuh — memudahkan korelasi antara log Caddy dan log backend menggunakan request ID yang sama.
Pola Format untuk Compliance PCI-DSS dan GDPR #
Untuk aplikasi yang memproses data pembayaran (PCI-DSS) atau data pribadi (GDPR), log harus memenuhi persyaratan tertentu:
payment.example.com {
log {
output file /var/log/caddy/payment-access.log {
roll_keep_days 365 # PCI-DSS: simpan 1 tahun
roll_keep 52 # 52 file mingguan
}
format filter {
wrap json
fields {
# GDPR: hash atau hapus IP
request>remote_ip hash
# Hapus semua header yang mungkin berisi PII
request>headers delete
# Jangan log body request (mungkin berisi nomor kartu)
}
}
}
reverse_proxy payment-backend:8443
}