Cara Install Certbot Nginx di Ubuntu 24.04
Panduan instalasi Certbot via apt atau snap di Ubuntu 24.04. Pelajari perbedaan versi dan cara menghindari error timeout pada port 80 saat proses renewal.
Install Certbot: apt atau snap
Pada Ubuntu 24.04, sudo apt install certbot python3-certbot-nginx menyediakan Certbot yang berfungsi untuk menerbitkan sertifikat Let's Encrypt asli yang dipercaya publik. Dokumentasi resmi Certbot menyarankan penggunaan snap; perbedaannya sangat kecil — snap mengikuti rilis terbaru dari pengembang, sedangkan paket repositori mengikuti versi yang disertakan pada LTS dan hanya menerima perbaikan keamanan.
Pilih salah satu. Memiliki dua salinan Certbot berarti ada dua timer pembaruan yang menargetkan pohon /etc/letsencrypt yang sama, dan salinan yang terlupakan akan menyebabkan masalah.
Metode apt:
sudo apt update
sudo apt install certbot python3-certbot-nginxPerintah tersebut menginstal /usr/bin/certbot, plugin nginx, pasangan certbot.service + certbot.timer, dan entri /etc/cron.d/certbot yang tidak berfungsi di bawah systemd.
Metode snap:
sudo apt remove certbot python3-certbot-nginx
sudo snap install core && sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbotSnap menyertakan timernya sendiri, yaitu snap.certbot.renew.timer. Hapus paket apt sebelum menginstal snap.
Kedua metode instalasi akan berperilaku sama setelahnya. Certbot 2.x menggunakan kunci ECDSA (P-256) secara default — gunakan --key-type rsa hanya jika klien tidak mendukung ECDSA. Semua data tersimpan di bawah /etc/letsencrypt: archive/ berisi file kunci dan sertifikat asli, live/ berisi symlink ke file yang sedang aktif, renewal/ berisi satu file konfigurasi per sertifikat, dan accounts/ berisi kunci akun ACME Anda.
Apa yang sebenarnya dilakukan HTTP-01, dan mengapa port 80 tidak opsional
Tantangan HTTP-01 adalah sebuah callback. Anda meminta sertifikat untuk example.com kepada Let's Encrypt; sistem tersebut akan melakukan resolusi nama pada DNS publik, membuka koneksi ke port 80 pada alamat yang ditemukan, dan meminta http://example.com/.well-known/acme-challenge/<token>. Server Anda harus menjawab dengan konten token yang persis sama dengan yang baru saja ditulis Certbot ke disk. Itulah seluruh mekanismenya. Terdapat tiga konsekuensi dari hal ini, yang menjadi penyebab utama kegagalan penerbitan sertifikat.
- Port 80 harus dapat dijangkau dari internet publik, bukan hanya dari laptop Anda. Aturan
ufw, security group penyedia cloud, atau firewall konsol VPS yang hanya membuka port 443 akan menggagalkan penerbitan sertifikat dan semua pembaruan di masa mendatang. - DNS harus sudah mengarah ke server ini. Server validasi melakukan pencarian sendiri dari luar; entri
/etc/hostsAnda dan cache browser tidak berpengaruh baginya. - Jika Anda memublikasikan rekaman AAAA, IPv6 akan dicoba terlebih dahulu. Let's Encrypt akan mencoba ulang melalui IPv4 jika koneksi IPv6 gagal sepenuhnya — namun rekaman AAAA yang kedaluwarsa yang mengarah ke host yang menerima koneksi tetapi menyajikan konten lain akan menyebabkan kegagalan total.
Pengalihan (redirect) diperbolehkan: validasi mengikuti pengalihan HTTP ke HTTPS dan tidak peduli jika sertifikat di ujung lainnya hilang, kedaluwarsa, atau ditandatangani sendiri (self-signed). Namun, validasi tidak akan memulai koneksi dari mana pun selain port 80. Certbot tidak memiliki implementasi TLS-ALPN-01, sehingga saran "gunakan saja port 443" bukanlah solusi.
Memilih authenticator: --nginx, --webroot, --standalone
--nginx adalah pilihan default yang tepat jika nginx sudah berjalan dan sudah melayani domain tersebut. Certbot akan membaca konfigurasi Anda, menyisipkan lokasi tantangan (challenge) sementara, memuat ulang nginx, melakukan validasi, lalu menulis direktif TLS ke dalam server block Anda. Tanpa downtime.
sudo certbot --nginx -d example.com -d www.example.comMenggunakan skrip, untuk server baru:
sudo certbot --nginx \
-d example.com -d www.example.com \
--agree-tos -m ops@example.com --no-eff-email \
--redirect --non-interactive--webroot adalah pilihan tepat jika Anda tidak ingin Certbot menyentuh konfigurasi nginx Anda — misalnya jika Anda menghasilkan konfigurasi dari template, menyimpannya di git, atau mengirimnya menggunakan Ansible. Certbot hanya menulis file tantangan ke dalam direktori yang sudah Anda layani.
sudo certbot certonly --webroot -w /var/www/example.com \
-d example.com -d www.example.com \
--deploy-hook "systemctl reload nginx"--standalone adalah pilihan tepat jika tidak ada layanan yang mendengarkan pada port 80: seperti mail server, API yang hanya menggunakan port 443, atau skrip booting pertama yang berjalan sebelum nginx ada. Certbot akan menggunakan port 80 itu sendiri selama beberapa detik. Jika nginx sedang berjalan, proses ini akan gagal — hentikan nginx sebelum menjalankan perintah ini:
sudo certbot certonly --standalone -d mail.example.com \
--pre-hook "systemctl stop nginx" \
--post-hook "systemctl start nginx"Hook tersebut dicatat dalam konfigurasi pembaruan sertifikat, sehingga proses stop/start yang sama akan berjalan secara otomatis saat pembaruan.
Server block yang berfungsi sebelum dan sesudah sertifikat tersedia
Masalah urutan (chicken-and-egg): nginx gagal dijalankan karena ssl_certificate mengarah ke file yang tidak ada, sementara Certbot tidak dapat melakukan validasi saat nginx mati. Jalankan situs pada port 80 terlebih dahulu.
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
location ^~ /.well-known/acme-challenge/ {
root /var/www/example.com;
default_type "text/plain";
try_files $uri =404;
}
location / {
try_files $uri $uri/ =404;
}
}Jalankan sudo nginx -t && sudo systemctl reload nginx, konfirmasi jawaban curl -I http://example.com/ dari luar server, lalu lakukan proses issue. Setelah itu:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location ^~ /.well-known/acme-challenge/ {
root /var/www/example.com;
default_type "text/plain";
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}Awalan ^~ pada lokasi ACME sangat penting: ini mencegah blok return 301 menyerap permintaan challenge. Menjaga lokasi tersebut tetap pada port 80 memastikan pembaruan tetap berfungsi setelah seluruh situs beralih ke HTTPS-only.
Sintaks HTTP/2 bergantung pada versi nginx Anda, dan mencampur kedua format tersebut akan menyebabkan error saat startup. Ubuntu 24.04 menyertakan nginx 1.24, yang memerlukan format inline — listen 443 ssl http2;. Debian 13 menyertakan nginx yang lebih baru, yang memerlukan direktif http2 on; terpisah. Periksa nginx -v terlebih dahulu.
Arahkan nginx ke live/, jangan pernah ke archive/. Symlink live/ akan diarahkan ulang pada setiap pembaruan; menggunakan path absolut ke archive/ akan mengunci Anda pada sertifikat yang akan kedaluwarsa.
Wildcard berarti DNS-01, dan DNS-01 berarti sebuah plugin
Sertifikat wildcard (*.example.com) tidak dapat divalidasi melalui HTTP-01 — tidak ada satu hostname tunggal untuk mengambil file. DNS-01 adalah satu-satunya jalur: Anda membuktikan kontrol dengan memublikasikan rekaman _acme-challenge.example.com TXT. Certbot memerlukan kredensial API penyedia DNS Anda untuk melakukan hal tersebut secara otomatis, itulah alasan plugin penyedia tersedia. Panduan lengkap sertifikat wildcard membahas mekanisme rekaman TXT dan masalah pembaruan pada mode manual; versi Cloudflare singkat tersedia setelahnya.
sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-cloudflarePada jalur apt, metodenya adalah sudo apt install python3-certbot-dns-cloudflare. Kredensial disimpan dalam file khusus root:
# /root/.secrets/cloudflare.ini
# then: sudo chmod 600 /root/.secrets/cloudflare.ini
dns_cloudflare_api_token = your_scoped_token_hereBatasi cakupan token hanya pada hak edit DNS di zona tersebut. Token ini adalah kunci DNS Anda; perlakukan seperti kunci asli.
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
-d example.com -d '*.example.com'Gunakan tanda kutip pada wildcard agar shell tidak melakukan globbing. DNS-01 juga menyelesaikan masalah yang tidak dapat diatasi HTTP-01: sertifikat untuk host tanpa port 80 publik — layanan internal, perangkat yang hanya dapat dijangkau melalui self-hosted WireGuard VPN pada VPS, atau panel admin pada antarmuka privat.
Pembaruan: 90 hari, timer, dan deploy hook
Sertifikat Let's Encrypt berlaku selama 90 hari. Certbot melakukan pembaruan saat sisa masa berlaku kurang dari 30 hari. Hal ini memberi Anda jendela waktu 30 hari agar kegagalan pembaruan hanya menjadi gangguan kecil yang bisa diperbaiki, bukan menyebabkan outage. Let's Encrypt tidak lagi mengirimkan email peringatan kedaluwarsa — tidak ada yang akan memberi tahu Anda secara manual, jadi pemantauan kini menjadi tanggung jawab Anda.
Periksa timer yang disertakan dalam instalasi Anda:
systemctl list-timers 'certbot*' 'snap.certbot*'
sudo certbot certificatescertbot renew memeriksa setiap konfigurasi di /etc/letsencrypt/renewal/, melewati apa pun yang berada di luar jendela 30 hari, dan memperbarui sisanya menggunakan flag yang sama persis dengan saat dijalankan pertama kali. Itulah sebabnya eksekusi pertama sangat penting: karena itulah yang dicatat.
Memperbarui file di disk tidak mengubah apa pun secara otomatis — nginx tetap menyajikan sertifikat lama dari memori hingga ada perintah untuk reload. Pasang deploy hook satu kali:
sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh >/dev/null <<'EOF'
#!/bin/sh
set -e
nginx -t && systemctl reload nginx
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.shApa pun yang dapat dieksekusi di renewal-hooks/deploy/ akan berjalan setelah pembaruan berhasil. Flag --deploy-hook melakukan tugas yang sama untuk satu sertifikat, dengan menyimpan renew_hook = ... di dalam konfigurasi pembaruannya. certbot --nginx melakukan reload untuk Anda; pengaturan --webroot dan --standalone tidak. Hilangnya hook adalah penyebab utama situs menyajikan sertifikat kedaluwarsa sementara certbot certificates melaporkan sertifikat baru dengan lancar. Aplikasi lain yang membaca sertifikat saat startup membutuhkan hook yang sama — aplikasi berbasis container seperti instalasi Nextcloud VPS dengan Docker, TLS, dan backup juga memerlukan langkah restart atau reload yang dipasang di sini.
Pengujian pembaruan secara nyata
sudo certbot renew --dry-runProses ini menjalankan tantangan lengkap terhadap lingkungan staging Let's Encrypt: jalur kode, firewall, dan DNS yang sama, tanpa biaya rate-limit, dan tidak ada data yang ditulis ke disk. Jika berhasil hari ini, pembaruan otomatis dalam 60 hari juga akan berhasil, dengan asumsi tidak ada perubahan pada konfigurasi sistem.
Dry run tidak membuktikan bahwa reload hook berjalan — perilakunya bervariasi tergantung versi Certbot. Uji bagian tersebut secara manual: jalankan skrip hook secara langsung, pastikan systemctl reload nginx berhasil, dan periksa sudo grep renew_hook /etc/letsencrypt/renewal/example.com.conf.
Kesalahan yang akan Anda temui
Could not bind to IPv4 or IPv6. — --standalone karena nginx sudah menggunakan port 80. Gunakan --nginx atau --webroot, atau hentikan nginx sebelum menjalankan proses. Pastikan aplikasi yang menggunakan port tersebut dengan sudo ss -lntp | grep ':80'.
Timeout during connect (likely firewall problem) — Let's Encrypt tidak dapat menjangkau port 80. Periksa secara bertahap: sudo ufw status (buka port dengan sudo ufw allow 'Nginx Full'), lalu firewall dari penyedia VPS, kemudian DNS. Uji dari lokasi selain server Anda: curl -sSv http://example.com/.well-known/acme-challenge/test. Rekaman AAAA yang kedaluwarsa juga menyebabkan pesan ini.
unauthorized :: Invalid response from http://example.com/.well-known/acme-challenge/xyz: 404 — port 80 dapat dijangkau, tetapi token tidak tersedia. Permintaan masuk ke server block yang berbeda (periksa server block mana yang memiliki default_server), atau direktori yang diberikan ke -w bukan direktori yang dilayani nginx. Letakkan file di /var/www/example.com/.well-known/acme-challenge/test dan akses secara eksternal; jika muncul error 404, maka sertifikat bukan penyebab masalahnya.
**DNS problem: NXDOMAIN looking up A for example.com — nama tidak dapat diurai (resolve) secara publik. Rekaman baru yang belum terpropagasi, atau rekaman pada zone yang tidak dilayani oleh registrar Anda.
**too many certificates already issued for: example.com — pembatasan laju (rate limit), yang sering ditemui saat melakukan debugging secara berulang. Let's Encrypt membatasi sertifikat duplikat — dengan set nama yang persis sama — sebanyak lima kali per minggu, dan secara terpisah mengizinkan 50 sertifikat baru per domain terdaftar per minggu; tidak ada cara untuk membuka blokir selain menunggu. Lakukan debugging menggunakan staging dengan --dry-run.
**nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/example.com/fullchain.pem": No such file or directory — nginx dikonfigurasi untuk sertifikat yang belum pernah diterbitkan, atau sertifikat yang telah dihapus dengan certbot delete. Berikan komentar pada TLS server block, jalankan nginx, terbitkan sertifikat, lalu kembalikan konfigurasi block tersebut.
**open() "/etc/letsencrypt/options-ssl-nginx.conf" failed — file tersebut disertakan dalam paket plugin nginx. Pada sistem certonly tanpa python3-certbot-nginx, tambahkan plugin atau ganti baris include dengan pengaturan ssl_protocols dan ssl_ciphers milik Anda sendiri.
Mengelola ini dalam skala besar
Satu sertifikat dapat menampung hingga 100 nama, dan satu certbot --nginx -d a.example.com -d b.example.com ... tunggal terlihat sangat menguntungkan — sampai satu catatan DNS yang kedaluwarsa gagal dalam validasi dan menyebabkan semua nama lain pada sertifikat tersebut ikut gagal. Sertifikat terpisah untuk setiap situs akan gagal secara independen, yang merupakan kondisi ideal pada server yang menghosting lebih dari beberapa layanan. Setelah mengelola banyak situs, penggunaan front door yang sadar ACME sangat diperlukan: reverse proxy Traefik yang menjalankan beberapa aplikasi di bawah Docker Compose akan meminta dan memperbarui sertifikat secara otomatis, sehingga Certbot tidak lagi diperlukan.
Cadangkan /etc/letsencrypt secara utuh — sudo tar -czf letsencrypt-$(date +%F).tar.gz -C /etc letsencrypt — dengan symlink yang tetap utuh. Direktori tersebut berisi accounts/, yaitu kunci akun ACME Anda, yang tidak dapat dibuat ulang dengan identitas yang sama. Berpindah ke VPS baru kemudian hanya memerlukan langkah berikut: rsync direktori tersebut dengan -a, instal Certbot, arahkan ulang DNS, dan jalankan certbot renew --dry-run sebelum melakukan migrasi.
Timer pembaruan tidak akan mengikuti Anda saat Anda membangun ulang server atau pindah ke LTS baru. Setelah migrasi, pemulihan snapshot, atau pembaruan distro, jalankan systemctl list-timers 'certbot*' dan satu --dry-run. Melewatkan langkah ini akan menyebabkan situs mati 89 hari kemudian, pada jam 3 pagi, pada sertifikat yang dianggap semua orang akan diperbarui secara otomatis.
Semua ini mengasumsikan Anda mengontrol mesin dengan IP publik dan port 80 yang terbuka untuk umum — dengan kata lain, sebuah VPS. Mekanisme di atas identik pada jenis VPS mana pun.
Langkah sertifikat yang sama berlaku pada Apache alih-alih nginx, dan jika sertifikat publik tidak tersedia, sertifikat self-signed pada Ubuntu dapat digunakan untuk layanan internal.
FAQ
Apakah saya perlu membuka port 80 jika situs saya hanya menggunakan HTTPS?
Ya, untuk tantangan HTTP-01. Let's Encrypt selalu memulai permintaan validasi pada port 80. Certbot tidak memiliki implementasi TLS-ALPN-01, sehingga firewall yang hanya membuka port 443 akan menghalangi proses penerbitan awal dan setiap pembaruan otomatis setelahnya. Pengalihan (redirect) dari port 80 ke HTTPS diperbolehkan karena validasi akan mengikuti pengalihan tersebut. Satu-satunya cara untuk melewati port 80 sepenuhnya adalah menggunakan DNS-01 dengan plugin penyedia DNS.
apt atau snap — mana Certbot yang harus saya instal untuk nginx di Ubuntu 24.04?
Gunakan apt. sudo apt install certbot python3-certbot-nginx menyediakan Certbot 2.9.0 pada Ubuntu 24.04, yang sudah cukup mutakhir untuk semua panduan ini, mendapatkan patch keamanan melalui unattended-upgrades, dan tidak memerlukan snapd. Gunakan snap hanya jika Anda membutuhkan rilis terbaru segera atau jika Anda memerlukan plugin DNS yang hanya didistribusikan sebagai snap. Dalam kondisi apa pun, pilih hanya satu: dua instalasi berarti dua timer pembaruan yang mengarah ke pohon /etc/letsencrypt yang sama, dan instalasi yang terlupakan akan menyebabkan masalah.
Bisakah Certbot menerbitkan sertifikat wildcard untuk nginx?
Hanya melalui DNS-01. Sertifikat wildcard seperti *.example.com tidak memiliki satu hostname tunggal untuk mengambil file tantangan, sehingga --nginx, --webroot, dan --standalone tidak dapat digunakan. Instal plugin untuk penyedia DNS Anda, masukkan token API yang terbatas pada file kredensial khusus root, lalu jalankan certbot certonly --dns-cloudflare -d example.com -d '*.example.com' dengan menggunakan tanda kutip pada wildcard agar tidak terdeteksi sebagai shell globbing.
Mengapa nginx masih menampilkan sertifikat lama setelah pembaruan berhasil?
nginx menyimpan sertifikat di dalam memori dan tidak akan mendeteksi file baru di disk sampai nginx melakukan reload. certbot --nginx melakukan reload secara otomatis, tetapi menjalankan --webroot dan --standalone tidak melakukan reload, sehingga pembaruan bisa berhasil sementara browser masih menampilkan sertifikat yang akan kedaluwarsa. Masukkan skrip eksekusi ke dalam /etc/letsencrypt/renewal-hooks/deploy/ yang menjalankan nginx -t && systemctl reload nginx agar skrip tersebut berjalan setelah setiap pembaruan berhasil.
Apakah certbot renew --dry-run membuktikan bahwa pembaruan akan berhasil?
Sebagian besar. Skrip ini menjalankan tantangan asli terhadap lingkungan staging — menggunakan firewall, DNS, dan jalur kode yang sama — tanpa biaya rate-limit dan tanpa menulis apa pun ke disk, sehingga hasil sukses berarti sisi jaringan sudah benar. Namun, skrip ini tidak membuktikan secara andal bahwa deploy hook Anda berjalan. Uji hal tersebut secara terpisah: jalankan skrip hook secara manual dan periksa sudo grep renew_hook /etc/letsencrypt/renewal/example.com.conf.