Memanfaatkan automatic HTTPS FrankenPHP: sertifikat Let's Encrypt untuk domain produksi tanpa intervensi manual, sertifikat internal untuk localhost, directive tls, variabel SERVER_NAME, dan cara menangani kasus khusus https://127.0.0.1 di Docker.

Setelah episode 9 membahas reverse proxy, episode ini menyentuh fitur yang membuat FrankenPHP (dan Caddy) begitu berbeda dari tumpukan web server tradisional: HTTPS yang bekerja sendiri. Tidak ada lagi certbot, tidak ada lagi cron renewal, tidak ada lagi lupa memperbarui sertifikat yang berakhir tengah malam. FrankenPHP mengambil, memperbarui, dan memperpanjang sertifikat secara otomatis.
Mengapa penting? HTTPS adalah syarat mutlak di 2026 — browser menandai situs HTTP sebagai tidak aman, dan HTTP/2/3 tidak berjalan tanpa TLS. Kemampuan ini menghapus salah satu bagian paling menyakitkan dari operasional web server, dan memahaminya akan mencegah kalian dari kebingungan "kenapa sertifikat lokal tidak dipercaya".
Caddy punya modul ACME bawaan (Automatic Certificate Management Environment). Alurnya:
api.kaliansite.com.frankenphp run pertama kali, Caddy meminta sertifikat dari Let's Encrypt untuk domain itu.Karena port 80 dan 443 harus bisa diakses dari internet untuk verifikasi, pastikan firewall membukanya dan DNS mengarah ke IP server.
Contoh: dengan Caddyfile berikut dan DNS yang sudah benar, HTTPS produksi jalan tanpa satu pun perintah manual:
api.kaliansite.com {
reverse_proxy 127.0.0.1:8081
}Cukup itu. Buka https://api.kaliansite.com — sertifikat valid, renewal otomatis, dan HTTP/2/3 aktif.
Tanpa domain, FrankenPHP menerbitkan sertifikat internal untuk localhost secara otomatis. Ini berlaku untuk development: https://localhost langsung bekerja tanpa konfigurasi TLS apa pun. Browser akan menampilkan peringatan karena CA-nya tidak dipercaya — klik "Advance" dan lanjutkan, atau tambahkan CA lokal FrankenPHP ke trust store sistem.
localhost {
root * public/
php_server
}Jalankan frankenphp run lalu buka https://localhost. Caddyfile di atas menghasilkan sertifikat untuk localhost tanpa kalian menulis directive tls sama sekali.
Warning
Gunakan https://localhost, bukan https://127.0.0.1. FrankenPHP menerbitkan sertifikat untuk hostname localhost secara default — mengakses lewat 127.0.0.1 akan memicu error TLS "certificate is valid for localhost, not 127.0.0.1". Untuk memakai IP, kalian harus menambahkannya ke server name.
tlsDirective tls memberi kontrol manual ketika default otomatis tidak cukup:
localhost {
tls internal
root * public/
php_server
}tls internal memaksa sertifikat lokal alih-alih mencoba Let's Encrypt — berguna di development tanpa internet. Pilihan lainnya:
example.com {
tls /etc/ssl/example.crt /etc/ssl/example.key
root * public/
php_server
}Mode manual ini untuk sertifikat dari CA eksternal (misal company CA internal atau sertifikat wildcard).
SERVER_NAMEUntuk image Docker, hostname diambil dari env var SERVER_NAME — ini cara paling umum mengganti domain di image yang sama:
docker run \
-e SERVER_NAME="api.kaliansite.com" \
-p 80:80 -p 443:443 -p 443:443/udp \
dunglas/frankenphpUntuk development tanpa HTTPS, matikan automatic HTTPS dengan SERVER_NAME=:80:
docker run \
-e SERVER_NAME=":80" \
-p 80:80 \
dunglas/frankenphpNilai SERVER_NAME juga bisa berupa daftar hostname yang dipisahkan koma — semua akan mendapatkan sertifikat.
https://127.0.0.1 dengan DockerKadang kalian membutuhkan akses via 127.0.0.1 (misal untuk menguji API di localhost dari host). Dua solusi dari dokumentasi resmi:
Solusi 1 — Host networking (Linux):
docker run \
-e SERVER_NAME="127.0.0.1" \
-v $PWD:/app/public \
--network host \
dunglas/frankenphpSolusi 2 — Masukkan IP container ke server name:
docker run \
-e SERVER_NAME="127.0.0.1, 172.17.0.3" \
-v $PWD:/app/public \
-p 80:80 -p 443:443 -p 443:443/udp \
dunglas/frankenphpKedua pendekatan menambahkan 127.0.0.1 sebagai subject sertifikat sehingga TLS tidak lagi ditolak. Host networking tidak didukung di macOS/Windows — di platform itu gunakan Solusi 2 (cek docker network inspect bridge untuk menemukan IP container).
Caddy melakukan redirect HTTP ke HTTPS secara otomatis selama automatic HTTPS aktif. Ini termasuk default:
http://domain → dijawab 308 → diarahkan ke https://domain.Untuk memastikan redirect tetap berjalan saat HTTPS dimatikan di development, jangan aktifkan SERVER_NAME=:80 di produksi.
caddy_data harus persisten (Docker named volume) — jika hilang, sertifikat diperoleh ulang, dan renewal tidak mungkin terjadi.localhost dan memakai sertifikat internal — periksa kembali SERVER_NAME.Pada episode 10 ini, kalian telah menguasai TLS/HTTPS otomatis FrankenPHP.
Inti yang harus dibawa pulang:
localhost — HTTPS development gratis.tls internal / tls <crt> <key> untuk kontrol manual.SERVER_NAME mengendalikan hostname (terutama di Docker).https://localhost, dan simpan volume caddy_data agar sertifikat awet.Di episode 11 selanjutnya kita membahas manajemen konfigurasi lintas environment: environment variables, Caddy env substitution, dan format config Caddyfile vs JSON — agar satu aplikasi bisa berjalan di development, staging, dan produksi. Sampai jumpa di episode 11!