Let’s Encrypt #
Let’s Encrypt adalah Certificate Authority (CA) nirlaba yang menyediakan sertifikat TLS gratis, otomatis, dan terbuka untuk siapa saja. Diluncurkan pada November 2015 oleh Internet Security Research Group (ISRG), Let’s Encrypt telah menerbitkan lebih dari tiga miliar sertifikat dan menjadi CA paling banyak digunakan di dunia — menjadi alasan utama adopsi HTTPS melonjak dari sekitar 40% menjadi lebih dari 80% dari seluruh web traffic.
Caddy mengintegrasikan Let’s Encrypt sebagai CA default secara native. Dalam banyak kasus, kamu tidak perlu menulis satu baris konfigurasi pun untuk mendapatkan sertifikat Let’s Encrypt — cukup tulis domain di Caddyfile dan semuanya berjalan otomatis.
Cara Kerja Otomatisasi Let’s Encrypt di Caddy #
Caddy menangani seluruh lifecycle sertifikat Let’s Encrypt tanpa intervensi manual:
Saat Caddy pertama kali dimulai atau domain baru ditambahkan:
1. Buat akun ACME (sekali, tersimpan di storage)
2. Minta sertifikat untuk setiap domain
3. Lakukan HTTP-01 challenge (default) atau DNS-01 (jika dikonfigurasi)
4. Simpan sertifikat ke storage
5. Aktifkan HTTPS untuk domain tersebut
Secara ongoing (background daemon):
6. Periksa semua sertifikat setiap ~10 menit
7. Jika sertifikat <= 30 hari sebelum expire → mulai renewal
8. Jika renewal berhasil → sertifikat baru langsung aktif tanpa restart
9. Jika renewal gagal → retry dengan backoff, notifikasi via log
Seluruh proses ini terjadi di background, tanpa downtime, dan tanpa perlu restart Caddy.
Konfigurasi Minimal (Zero Configuration) #
Untuk domain publik yang DNS-nya sudah mengarah ke server kamu, tidak ada konfigurasi TLS yang diperlukan sama sekali:
# Ini cukup — Let's Encrypt digunakan secara otomatis
example.com {
root * /var/www/html
file_server
}
Yang terjadi di balik layar:
- Caddy mendeteksi
example.comsebagai domain yang membutuhkan sertifikat - Caddy menghubungi Let’s Encrypt via protokol ACME
- HTTP-01 challenge diselesaikan otomatis (Caddy serve token di port 80)
- Sertifikat diterima dan dipasang
- HTTPS aktif untuk
example.com - Redirect dari HTTP ke HTTPS otomatis aktif
Menambahkan Email (Direkomendasikan) #
Meski bukan wajib, selalu tambahkan email di global options untuk production:
{
email [email protected]
}
example.com {
file_server
}
Email ini digunakan untuk:
- Notifikasi dari Let’s Encrypt jika renewal sertifikat gagal
- Peringatan beberapa minggu sebelum sertifikat expire (sebagai backup)
- Pemulihan akun ACME jika diperlukan
Multiple Domain dengan Let’s Encrypt #
Caddy otomatis mendapatkan sertifikat terpisah untuk setiap domain unik:
{
email [email protected]
}
# Sertifikat 1: untuk example.com
example.com {
root * /var/www/example
file_server
}
# Sertifikat 2: untuk api.example.com
api.example.com {
reverse_proxy localhost:8080
}
# Sertifikat 3: satu sertifikat untuk dua domain (SAN certificate)
# Caddy otomatis membuat sertifikat dengan kedua domain sebagai Subject Alternative Names
app.example.com, staging.example.com {
reverse_proxy localhost:3000
}
# Sertifikat 4: www redirect tidak memerlukan sertifikat sendiri
# (Caddy otomatis menambahkan www ke SAN sertifikat utama jika keduanya ada)
www.example.com {
redir https://example.com{uri} permanent
}
SAN Certificate Otomatis #
Ketika beberapa domain berada dalam satu blok site, Caddy secara otomatis membuat SAN (Subject Alternative Names) certificate yang mencakup semua domain tersebut:
# Satu blok, satu sertifikat dengan 3 SAN
example.com, api.example.com, app.example.com {
reverse_proxy localhost:3000
}
Certificate yang dihasilkan:
Subject: CN=example.com
SANs: example.com, api.example.com, app.example.com
Monitoring Status Sertifikat #
Caddy menyediakan beberapa cara untuk memantau status sertifikat yang dikelolanya:
Via Admin API #
# Lihat semua sertifikat yang dikelola
curl -s http://localhost:2019/config/apps/tls/ | jq '.automation.policies'
# Lihat detail managed certificates
curl -s "http://localhost:2019/pki/ca/local" | jq .
# Cek status TLS secara keseluruhan
curl -s http://localhost:2019/config/ | jq '.apps.tls'
Via OpenSSL dari Luar #
# Cek sertifikat yang aktif di domain
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -text
# Cek tanggal expire saja
echo | openssl s_client -connect example.com:443 2>/dev/null \
| openssl x509 -noout -dates
# Output:
# notBefore=Jan 1 00:00:00 2024 GMT
# notAfter=Apr 1 00:00:00 2024 GMT
# Script monitoring sederhana
check_cert_expiry() {
local domain=$1
local days_left=$(echo | openssl s_client -connect "$domain:443" 2>/dev/null \
| openssl x509 -noout -enddate \
| sed 's/notAfter=//' \
| xargs -I{} date -d "{}" +%s \
| xargs -I{} sh -c 'echo $(( ({} - $(date +%s)) / 86400 ))')
echo "$domain: $days_left hari tersisa"
}
check_cert_expiry example.com
check_cert_expiry api.example.com
Via Log Caddy #
# Lihat semua event terkait sertifikat
sudo journalctl -u caddy | grep -i "certificate\|acme\|tls"
# Cari event renewal
sudo journalctl -u caddy | grep -i "renew\|renewal"
# Cari error ACME
sudo journalctl -u caddy | grep -i "error" | grep -i "acme\|tls"
Troubleshooting: Masalah Umum #
Caddy Tidak Bisa Mendapatkan Sertifikat #
# Gejala di log:
# "solving challenge: error"
# "failed to get certificate"
# Diagnosa 1: DNS belum propagate
dig +short example.com
# Harus return IP publik server kamu
# Jika return IP yang berbeda atau kosong, tunggu DNS propagation
# Diagnosa 2: Port 80 tidak accessible
# Test dari server lain atau pakai tool online
curl -I http://example.com/.well-known/acme-challenge/test
# Diagnosa 3: Port 80 diblokir firewall
sudo ufw status # Ubuntu
sudo firewall-cmd --list-ports # CentOS/RHEL
# Diagnosa 4: Proses lain menggunakan port 80
sudo ss -tlnp | grep ':80'
Rate Limit Tercapai #
# Gejala di log:
# "too many certificates already issued for registered domain"
# "rateLimited"
# Cek sertifikat yang sudah diterbitkan di crt.sh
# Buka browser: https://crt.sh/?q=example.com
# Hitung sertifikat dalam 7 hari terakhir
# Solusi sementara: Gunakan staging CA sambil menunggu rate limit reset
# Edit Caddyfile:
# {
# acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
# email [email protected]
# }
# Rate limit reset setelah 7 hari (rolling window)
# Tidak ada cara untuk mempercepat reset
# Pencegahan: Jangan hapus volume data Caddy sembarangan
# Sertifikat yang ada di storage bisa digunakan ulang tanpa request baru
Sertifikat Tidak Dipercaya Browser #
# Gejala: Browser menampilkan "Certificate not trusted" atau warning
# Kemungkinan: Menggunakan staging CA secara tidak sengaja
# Cek issuer sertifikat
echo | openssl s_client -connect example.com:443 2>/dev/null \
| openssl x509 -noout -issuer
# Production issuer: issuer=C=US, O=Let's Encrypt, CN=R3
# Staging issuer: issuer=CN=Fake LE Intermediate X1
# Jika staging, hapus baris acme_ca dari global options
# dan reload Caddy untuk mendapatkan sertifikat production
Renewal Gagal Terus-menerus #
# Gejala di log:
# "certificate renewal failed" berulang kali
# Cek penyebab spesifik
sudo journalctl -u caddy -n 200 | grep -A5 "renewal"
# Penyebab umum:
# 1. Port 80 tidak lagi accessible (perubahan firewall)
# 2. DNS berubah dan tidak mengarah ke server ini
# 3. Server diblokir oleh Let's Encrypt (jarang terjadi)
# 4. Storage penuh (tidak bisa simpan sertifikat baru)
# Paksa renewal manual (jika perlu)
# Hapus sertifikat dari storage dan restart Caddy
# (Caddy akan minta sertifikat baru dari awal)
sudo find /var/lib/caddy -name "*.pem" -path "*example.com*" -delete
sudo systemctl restart caddy
Best Practice untuk Production #
1. Selalu Set Email #
{
email [email protected]
# atau mailing list khusus untuk alert
email [email protected]
}
2. Gunakan Staging Dulu saat Testing #
# Workflow yang direkomendasikan:
# 1. Setup dengan staging CA terlebih dahulu
# 2. Verifikasi konfigurasi bekerja (meski sertifikat tidak di-trust)
# 3. Hapus acme_ca dari config
# 4. Reload Caddy untuk mendapat sertifikat production
3. Persist Storage Sertifikat #
# Docker: Selalu gunakan named volume
docker run -v caddy_data:/data caddy
# Systemd: Pastikan /var/lib/caddy tidak dihapus saat deploy
# Backup /var/lib/caddy secara berkala
4. Monitor Expired Certificates #
# Buat script monitoring sederhana
#!/bin/bash
# /etc/cron.daily/check-certs
THRESHOLD=14 # Alert jika <= 14 hari lagi
for domain in example.com api.example.com app.example.com; do
expiry=$(echo | openssl s_client -connect "$domain:443" 2>/dev/null \
| openssl x509 -noout -enddate | cut -d= -f2)
days=$((( $(date -d "$expiry" +%s) - $(date +%s) ) / 86400))
if [ $days -le $THRESHOLD ]; then
echo "WARNING: $domain expires in $days days!" | \
mail -s "Certificate Expiry Warning" [email protected]
fi
done
Cara Caddy Berbeda dari Certbot #
Meski keduanya menggunakan Let’s Encrypt, pendekatan Caddy dan Certbot sangat berbeda:
Certbot: Caddy:
───────────────────────────────────── ──────────────────────────────────
Tool terpisah dari web server Terintegrasi dalam web server
Perlu setup cronjob manual Auto-renewal bawaan
Edit nginx.conf untuk install cert Tidak perlu konfigurasi TLS sama sekali
Cronjob berjalan dua kali sehari Background daemon always-on
Gagal senyap jika cron tidak jalan Retry otomatis dengan backoff
Perlu systemd timer atau cron Tidak ada ketergantungan external
Konfigurasi Nginx dimodifikasi oleh Caddy mengelola TLS sendiri tanpa
certbot — bisa rusak konfigurasi modifikasi file konfigurasi
Ringkasan #
- Tidak ada konfigurasi yang diperlukan untuk Let’s Encrypt di Caddy — cukup tulis domain dan semuanya otomatis.
- Selalu set
- Caddy mendapatkan sertifikat terpisah per domain, atau SAN certificate jika beberapa domain berada dalam satu blok site.
- Rate limit production: 50 sertifikat per registered domain per minggu. Gunakan staging CA untuk testing.
- Jika rate limit tercapai, harus tunggu hingga 7 hari. Jangan hapus volume sertifikat sembarangan.
- Gunakan Admin API (
/config/apps/tls) danopenssl s_clientuntuk monitoring status sertifikat.- Caddy jauh lebih sederhana dari setup Certbot + Nginx karena TLS dikelola sepenuhnya oleh Caddy sendiri.