SSD Nodes Learn Hosting plans →
Panduan Matt ConnorOleh Matt Connor · Diperbarui 2026-08-28

Instal Certbot untuk nginx di Ubuntu 24.04

Pasang certbot python3-certbot-nginx dengan apt, lalu jalankan certbot --nginx sekali. Pahami perbedaan apt dan snap serta timeout port 80 saat pembaruan.

Instal Certbot: apt atau snap

Di Ubuntu 24.04, sudo apt install certbot python3-certbot-nginx menyediakan Certbot yang dapat menerbitkan sertifikat Let's Encrypt yang valid dan dipercaya publik. Dokumentasi upstream Certbot mengarahkan Anda untuk menggunakan snap. Perbedaannya terbatas: snap mengikuti rilis upstream, sedangkan paket archive mengikuti versi yang disertakan dalam LTS dan menerima perbaikan keamanan.

Pilih salah satu. Dua salinan Certbot berarti ada dua timer pembaruan yang menargetkan tree /etc/letsencrypt yang sama. Salinan yang Anda lupakan akan menimbulkan masalah.

Jalur apt:

sudo apt update
sudo apt install certbot python3-certbot-nginx

Perintah tersebut memasang /usr/bin/certbot, plugin nginx, pasangan certbot.service + certbot.timer, serta entri /etc/cron.d/certbot yang tidak melakukan apa pun saat dijalankan di bawah systemd.

Jalur 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/certbot

snap menyediakan timer-nya sendiri, snap.certbot.renew.timer. Hapus paket apt sebelum memasang snap.

Setelah itu, kedua instalasi berperilaku sama. Certbot 2.x secara default menggunakan kunci ECDSA (P-256). Teruskan --key-type rsa hanya untuk klien yang tidak mendukung ECDSA. Semua state disimpan di bawah /etc/letsencrypt: archive/ berisi file kunci dan sertifikat asli, live/ berisi symlink ke file yang sedang digunakan, renewal/ berisi satu file konfigurasi untuk setiap sertifikat, dan accounts/ berisi kunci akun ACME Anda.

Apa yang sebenarnya dilakukan HTTP-01 dan mengapa port 80 tidak opsional

Challenge HTTP-01 adalah callback. Anda meminta Let's Encrypt menerbitkan sertifikat untuk example.com; Let's Encrypt mencari nama tersebut di DNS publik, membuka koneksi ke port 80 pada alamat yang ditemukan, lalu meminta http://example.com/.well-known/acme-challenge/<token>. Server Anda menjawab dengan isi token yang baru saja ditulis Certbot ke disk. Itulah seluruh mekanismenya. Dari mekanisme ini ada tiga konsekuensi yang menjelaskan sebagian besar kegagalan penerbitan sertifikat.

  • Port 80 harus dapat dijangkau dari Internet publik, bukan hanya dari laptop Anda. Aturan ufw, security group dari penyedia cloud, atau firewall pada konsol VPS yang hanya membuka port 443 akan menggagalkan penerbitan sertifikat dan setiap pembaruan otomatis berikutnya.
  • DNS harus sudah mengarah ke server ini. Server validasi melakukan pencarian DNS sendiri dari luar jaringan; entri /etc/hosts dan cache browser Anda tidak berpengaruh.
  • Jika Anda memublikasikan record AAAA, IPv6 akan dicoba terlebih dahulu. Let's Encrypt akan mencoba kembali melalui IPv4 jika koneksi IPv6 gagal sepenuhnya. Namun, AAAA yang sudah kedaluwarsa dan mengarah ke host yang menerima koneksi tetapi menyajikan layanan lain akan menyebabkan kegagalan langsung.

Redirect diperbolehkan: validasi mengikuti redirect HTTP ke HTTPS dan tidak memedulikan apakah sertifikat pada tujuan tidak ada, sudah kedaluwarsa, atau ditandatangani sendiri. Namun, proses ini tidak akan dimulai dari port selain port 80. Certbot tidak memiliki implementasi TLS-ALPN-01, sehingga "cukup gunakan 443" bukan solusi.

Memilih authenticator: --nginx, --webroot, --standalone

--nginx adalah pilihan default yang tepat jika nginx sudah berjalan dan sudah melayani domain tersebut. Certbot membaca konfigurasi Anda, memasukkan lokasi challenge sementara, memuat ulang nginx, melakukan validasi, lalu menulis direktif TLS ke dalam server block Anda. Tidak ada downtime.

sudo certbot --nginx -d example.com -d www.example.com

Berikut contoh berbasis 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 tepat jika Anda tidak ingin Certbot menyentuh konfigurasi nginx, misalnya karena konfigurasi dibuat dari template, disimpan di git, atau diterapkan menggunakan Ansible. Certbot hanya menulis file challenge ke 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 tepat jika tidak ada proses yang listening pada port 80: misalnya mail server, API yang hanya menggunakan 443, atau skrip first-boot yang berjalan sebelum nginx tersedia. Certbot sendiri akan bind ke port 80 selama beberapa detik. Jika nginx sedang berjalan, proses ini gagal. Hentikan nginx sebelum menjalankannya, lalu jalankan kembali setelah selesai:

sudo certbot certonly --standalone -d mail.example.com \
  --pre-hook "systemctl stop nginx" \
  --post-hook "systemctl start nginx"

Hook tersebut dicatat dalam konfigurasi renewal sertifikat, sehingga proses stop/start yang sama dilakukan tanpa intervensi saat renewal.

Blok server yang berfungsi sebelum dan sesudah sertifikat tersedia

Masalah ayam dan telur: nginx menolak start jika ssl_certificate menunjuk ke file yang belum ada, sedangkan Certbot tidak dapat melakukan validasi saat nginx berhenti. Aktifkan situs terlebih dahulu pada port 80.

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, pastikan curl -I http://example.com/ memberikan respons dari luar server, lalu terbitkan sertifikat. 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;
    }
}

Prefix ^~ pada lokasi ACME sangat penting. Prefix ini mencegah blok return 301 mengambil alih permintaan challenge. Dengan mempertahankan lokasi tersebut pada port 80, proses renewal tetap berfungsi setelah bagian situs lainnya hanya menggunakan HTTPS.

Kedua blok di atas menyajikan file dari disk. Jika nginx digunakan sebagai frontend aplikasi, location / menjadi blok proxy_pass. Blok server reverse proxy, baris demi baris menjelaskan header yang diperlukan aplikasi tersebut. Lokasi ACME dan direktif TLS tetap sama persis.

Sintaks HTTP/2 bergantung pada versi nginx. Jika kedua bentuk sintaks tertukar, nginx akan gagal start. Ubuntu 24.04 menyertakan nginx 1.24, yang mengharuskan sintaks inline, listen 443 ssl http2;. Debian 13 menyertakan nginx yang lebih baru, yang mengharuskan direktif http2 on; terpisah. Periksa nginx -v terlebih dahulu.

Arahkan nginx ke live/, bukan ke archive/. Symlink live/ diarahkan ulang pada setiap renewal. Path tetap yang mengarah ke archive/ akan membuat Anda tetap menggunakan sertifikat yang akhirnya kedaluwarsa.

Wildcard berarti DNS-01, dan DNS-01 berarti plugin

Sertifikat wildcard (*.example.com) tidak dapat divalidasi melalui HTTP-01 karena tidak ada satu hostname tertentu untuk mengambil file. DNS-01 adalah satu-satunya cara: Anda membuktikan kendali dengan menerbitkan record TXT _acme-challenge.example.com. Certbot memerlukan kredensial API untuk provider DNS Anda agar proses ini dapat berjalan tanpa intervensi. Plugin provider digunakan untuk keperluan tersebut. Panduan lengkap sertifikat wildcard menjelaskan mekanisme record TXT dan masalah renewal dalam mode manual. Versi singkat untuk Cloudflare ada di bawah ini.

sudo snap set certbot trust-plugin-with-root=ok
sudo snap install certbot-dns-cloudflare

Pada jalur apt, gunakan sudo apt install python3-certbot-dns-cloudflare sebagai gantinya. Simpan kredensial dalam file yang hanya dapat diakses oleh root:

# /root/.secrets/cloudflare.ini
# then: sudo chmod 600 /root/.secrets/cloudflare.ini
dns_cloudflare_api_token = your_scoped_token_here

Batasi token agar hanya memiliki hak untuk mengubah DNS pada satu zone tersebut. Token ini adalah kunci untuk DNS Anda. Perlakukan token ini dengan semestinya.

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 mengatasi hal yang tidak dapat dilakukan HTTP-01: menerbitkan sertifikat untuk host tanpa port publik 80, service internal, mesin yang hanya dapat dijangkau melalui WireGuard yang di-host sendiri pada VPS, atau panel admin pada interface privat.

Perpanjangan: 90 hari, timer, dan deploy hook

Sertifikat Let’s Encrypt berlaku selama 90 hari. Certbot melakukan perpanjangan ketika masa berlaku tersisa kurang dari 30 hari. Dengan demikian, Anda memiliki jendela waktu 30 hari untuk memperbaiki perpanjangan yang gagal sebelum menjadi gangguan layanan. Let’s Encrypt tidak lagi mengirim email peringatan kedaluwarsa. Tidak ada pihak yang akan mengingatkan Anda, jadi pemantauan kini menjadi tanggung jawab Anda.

Periksa timer yang disertakan dalam instalasi Anda:

systemctl list-timers 'certbot*' 'snap.certbot*'
sudo certbot certificates

certbot renew memeriksa setiap konfigurasi di /etc/letsencrypt/renewal/, melewati konfigurasi yang masa berlakunya masih lebih dari 30 hari, lalu memperpanjang konfigurasi lainnya menggunakan flag yang sama persis seperti pada proses awal. Karena itu, proses pertama penting: konfigurasi tersebut yang dicatat.

Memperbarui file di disk tidak mengubah apa pun dengan sendirinya. nginx tetap menyajikan sertifikat lama dari memori sampai diperintahkan untuk memuat ulang. Konfigurasikan 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.sh

Setiap file yang dapat dieksekusi di renewal-hooks/deploy/ dijalankan setelah perpanjangan berhasil. Flag --deploy-hook melakukan hal yang sama untuk satu sertifikat dan menyimpan renew_hook = ... dalam konfigurasi perpanjangannya. certbot --nginx memuat ulang secara otomatis; konfigurasi --webroot dan --standalone tidak melakukannya. Hook yang tidak tersedia adalah alasan situs dapat menyajikan sertifikat yang sudah kedaluwarsa sementara certbot certificates melaporkan sertifikat baru dengan benar. Komponen lain yang membaca sertifikat saat startup juga memerlukan hook yang sama. Aplikasi dalam container, seperti instalasi Nextcloud VPS dengan Docker, TLS, dan backup, juga memerlukan langkah restart atau reload tersendiri yang dikonfigurasikan di sini.

Menguji perpanjangan secara nyata

sudo certbot renew --dry-run

Perintah tersebut menjalankan challenge lengkap terhadap environment staging Let's Encrypt: jalur kode yang sama, firewall yang sama, DNS yang sama, tanpa mengurangi batas laju, dan tanpa menulis apa pun ke disk. Jika pengujian ini berhasil hari ini, perpanjangan otomatis tanpa pengawasan dalam 60 hari juga akan berhasil, selama tidak ada perubahan lain pada server.

Dry run tidak membuktikan bahwa reload hook Anda berjalan karena perilakunya berbeda-beda menurut versi Certbot. Uji bagian tersebut secara manual: jalankan skrip hook secara langsung, pastikan systemctl reload nginx berhasil, lalu periksa sudo grep renew_hook /etc/letsencrypt/renewal/example.com.conf.

Error yang benar-benar akan Anda temui

Could not bind to IPv4 or IPv6., --standalone saat nginx masih menggunakan port 80. Gunakan --nginx atau --webroot, atau hentikan nginx selama proses tersebut. Konfirmasikan proses yang menggunakan port itu dengan sudo ss -lntp | grep ':80'.

Timeout during connect (likely firewall problem), Let's Encrypt tidak dapat menjangkau port 80. Periksa dari luar ke dalam: sudo ufw status (buka dengan sudo ufw allow 'Nginx Full'), kemudian firewall milik penyedia VPS, lalu DNS. Lakukan pengujian dari lokasi yang bukan server Anda: curl -sSv http://example.com/.well-known/acme-challenge/test. Entri AAAA yang sudah tidak sesuai dapat menghasilkan pesan yang sama.

unauthorized :: Invalid response from http://example.com/.well-known/acme-challenge/xyz: 404, port 80 dapat dijangkau, tetapi token tidak disajikan. Permintaan masuk ke server block yang berbeda (periksa server block yang memiliki default_server), atau direktori yang diteruskan ke -w bukan direktori yang disajikan nginx. Buat file di /var/www/example.com/.well-known/acme-challenge/test lalu ambil file tersebut dari luar; jika hasilnya 404, masalahnya bukan sertifikat.

DNS problem: NXDOMAIN looking up A for example.com, nama tersebut tidak dapat di-resolve secara publik. Penyebabnya dapat berupa record baru yang belum terpropagasi atau record pada zone yang tidak disajikan oleh registrar Anda.

too many certificates already issued for: example.com, terjadi rate limit. Ini sering terjadi saat proses debug diulang-ulang. Let's Encrypt membatasi sertifikat duplikat—dengan set nama yang sama persis—hingga lima per minggu. Secara terpisah, Let's Encrypt mengizinkan 50 sertifikat baru per registered domain per minggu. Tidak ada cara untuk membuka batas tersebut selain menunggu. Lakukan debug terhadap 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 tidak pernah diterbitkan atau sudah dihapus dengan certbot delete. Beri komentar pada TLS server block, jalankan nginx, terbitkan sertifikat, lalu pulihkan block tersebut.

open() "/etc/letsencrypt/options-ssl-nginx.conf" failed, file tersebut disertakan dalam paket plugin nginx. Pada sistem certonly yang tidak memiliki python3-certbot-nginx, tambahkan plugin atau ganti baris include dengan ssl_protocols dan ssl_ciphers Anda sendiri.

Mengelola ini pada skala besar

Satu sertifikat dapat memuat hingga 100 nama, dan satu certbot --nginx -d a.example.com -d b.example.com ... memang menarik, tetapi satu record DNS yang sudah usang dapat menggagalkan validasi dan membuat semua nama lain pada sertifikat tersebut ikut tidak dapat digunakan. Sertifikat terpisah untuk setiap situs gagal secara independen. Ini yang Anda inginkan pada server yang menampung lebih dari beberapa layanan. Setelah jumlah situs bertambah, front door yang mendukung ACME menjadi pilihan yang efisien: reverse proxy Traefik yang menjalankan beberapa aplikasi dengan Docker Compose meminta dan memperbarui sertifikat sendiri, sehingga Certbot tidak lagi diperlukan. Proxy yang digunakan sebagai front door merupakan keputusan tersendiri, dan membandingkan Nginx dengan Caddy dan Traefik terutama bergantung pada seberapa banyak pekerjaan sertifikat dan konfigurasi per aplikasi yang ingin Anda serahkan kepada proxy.

Cadangkan seluruh /etc/letsencrypt, termasuk sudo tar -czf letsencrypt-$(date +%F).tar.gz -C /etc letsencrypt, dan pertahankan symlink. Pohon direktori tersebut menyimpan accounts/, yaitu ACME account key Anda, yang tidak dapat dibuat ulang secara identik. Jika berpindah ke VPS baru, langkahnya cukup: sinkronkan pohon direktori dengan -a, instal Certbot, arahkan ulang DNS, lalu jalankan certbot renew --dry-run sebelum melakukan perpindahan.

Jika Anda membangun ulang server atau berpindah ke LTS baru, timer pembaruan tidak ikut berpindah. Setelah migrasi, pemulihan snapshot, atau upgrade distro, jalankan systemctl list-timers 'certbot*' dan satu --dry-run. Jika langkah ini dilewati, situs dapat tidak tersedia 89 hari kemudian, pada pukul 3 pagi, karena sertifikat yang dianggap semua orang akan diperbarui secara otomatis ternyata tidak diperbarui.

Semua ini mengasumsikan mesin yang Anda kendalikan, dengan IP publik dan port 80 yang terbuka untuk publik, atau dengan kata lain, VPS. Mekanisme di atas sama pada semua jenis mesin tersebut.

Langkah sertifikat yang sama berlaku pada Apache, bukan nginx, dan ketika sertifikat publik bukan pilihan, sertifikat self-signed pada Ubuntu dapat digunakan untuk layanan internal.

FAQ

Apakah port 80 harus dibuka jika situs saya hanya menyediakan HTTPS?

Ya, untuk challenge HTTP-01. Let’s Encrypt selalu memulai permintaan validasi pada port 80, dan Certbot tidak memiliki implementasi TLS-ALPN-01. Karena itu, firewall yang hanya membuka port 443 akan memblokir penerbitan sertifikat pertama dan setiap pembaruan otomatis berikutnya. Redirect dari port 80 ke HTTPS tidak masalah karena validasi akan mengikutinya. Satu-satunya cara untuk sepenuhnya menghindari port 80 adalah menggunakan DNS-01 dengan plugin provider.

apt atau snap, Certbot mana 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. Versi ini cukup baru untuk semua hal dalam panduan ini, menerima patch keamanan melalui unattended-upgrades, dan tidak memerlukan snapd. Pilih snap hanya jika Anda memerlukan rilis terbaru segera atau plugin DNS yang hanya didistribusikan sebagai snap. Apa pun pilihannya, gunakan tepat satu metode: dua instalasi berarti ada dua timer pembaruan yang mengarah ke tree /etc/letsencrypt yang sama, dan instalasi yang terlupakan itulah yang menyebabkan masalah.

Apakah Certbot dapat menerbitkan sertifikat wildcard untuk nginx?

Hanya melalui DNS-01. Wildcard seperti *.example.com tidak memiliki satu hostname tertentu untuk mengambil file challenge, sehingga --nginx, --webroot, dan --standalone tidak dapat digunakan. Instal plugin untuk provider DNS Anda, simpan token API dengan cakupan terbatas dalam file kredensial yang hanya dapat dibaca oleh root, lalu jalankan certbot certonly --dns-cloudflare -d example.com -d '*.example.com' dengan wildcard diapit tanda kutip agar shell tidak memperlakukannya sebagai glob.

Mengapa nginx masih menyediakan sertifikat lama setelah pembaruan berhasil?

nginx menyimpan sertifikat di memori dan tidak mendeteksi file baru pada disk sampai melakukan reload. certbot --nginx melakukan reload secara otomatis, tetapi --webroot dan --standalone tidak, sehingga pembaruan dapat berhasil sementara browser masih melihat sertifikat yang akan kedaluwarsa. Letakkan skrip yang dapat dieksekusi di /etc/letsencrypt/renewal-hooks/deploy/ dan jalankan nginx -t && systemctl reload nginx di dalamnya. Skrip tersebut akan dijalankan setelah setiap pembaruan yang berhasil.

Apakah certbot renew --dry-run membuktikan bahwa pembaruan akan berhasil?

Sebagian besar. Perintah ini menjalankan challenge yang sebenarnya pada environment staging, menggunakan firewall, DNS, dan jalur kode yang sama, tanpa menggunakan kuota rate limit dan tanpa menulis apa pun ke disk. Dengan demikian, keberhasilan menunjukkan bahwa bagian jaringan berfungsi dengan baik. Namun, perintah ini tidak secara andal membuktikan bahwa deploy hook dijalankan. Uji bagian tersebut secara terpisah: jalankan skrip hook secara manual dan periksa sudo grep renew_hook /etc/letsencrypt/renewal/example.com.conf.