SSD Nodes Learn
Panduan Matt ConnorOleh Matt Connor · Dikemas kini 2026-07-24

Cara pasang Certbot untuk nginx di Ubuntu 24.04

Gunakan sudo apt install certbot python3-certbot-nginx atau snap. Ketahui perbezaan versi dan cara elak masalah timeout port 80 semasa pembaharuan sijil.

Pasang Certbot: apt atau snap

Pada Ubuntu 24.04, sudo apt install certbot python3-certbot-nginx menyediakan Certbot yang berfungsi untuk mengeluarkan sijil Let's Encrypt yang sah dan dipercayai secara awam. Dokumentasi rasmi Certbot menyarankan penggunaan snap; perbezaannya adalah kecil — snap mengikuti versi terkini daripada pembangun, manakala pakej arkib mengikuti versi yang disertakan dengan LTS dan menerima kemas kini keselamatan.

Pilih satu sahaja. Dua salinan Certbot bermaksud dua pemasa pembaharuan yang menyasarkan pokok /etc/letsencrypt yang sama, dan salinan yang anda lupakan akan menyebabkan masalah.

Laluan apt:

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

Ia memasang /usr/bin/certbot, plugin nginx, pasangan certbot.service + certbot.timer, dan entri /etc/cron.d/certbot yang tidak aktif di bawah systemd.

Laluan 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 menyertakan pemasa sendiri, snap.certbot.renew.timer. Buang pakej apt sebelum memasang snap.

Kedua-dua pemasangan akan berfungsi dengan cara yang sama selepas itu. Certbot 2.x menggunakan kunci ECDSA (P-256) secara lalai — gunakan --key-type rsa hanya untuk klien yang tidak menyokong ECDSA. Semua keadaan disimpan di bawah /etc/letsencrypt: archive/ menyimpan fail kunci dan sijil sebenar, live/ adalah pautan simbolik (symlinks) ke fail semasa, renewal/ menyimpan satu fail konfigurasi bagi setiap sijil, dan accounts/ adalah kunci akaun ACME anda.

Apa yang sebenarnya dilakukan oleh HTTP-01, dan mengapa port 80 tidak boleh diabaikan

Cabaran HTTP-01 adalah satu proses panggilan balik (callback). Anda meminta sijil bagi example.com daripada Let's Encrypt; ia akan menyelesaikan nama tersebut dalam DNS awam, membuka sambungan ke port 80 pada alamat yang ditemui, dan meminta http://example.com/.well-known/acme-challenge/<token>. Pelayan anda mesti menjawab dengan kandungan token yang tepat seperti yang ditulis oleh Certbot ke dalam cakera. Itulah keseluruhan mekanismenya. Terdapat tiga kesan daripada proses ini, dan ia merupakan punca utama kegagalan pengeluaran sijil.

  • Port 80 mesti boleh dicapai dari internet awam, bukan sekadar dari komputer riba anda. Peraturan ufw, kumpulan keselamatan pembekal awan, atau tembok api konsol VPS yang hanya membuka port 443 akan membatalkan pengeluaran sijil dan semua pembaharuan pada masa hadapan.
  • DNS mesti sudah menghala ke pelayan ini. Pelayan pengesahan melakukan carian sendiri dari luar; entri /etc/hosts anda dan cache pelayar tidak bermakna baginya.
  • Jika anda menerbitkan rekod AAAA, IPv6 akan dicuba terlebih dahulu. Let's Encrypt akan mencuba semula melalui IPv4 jika sambungan IPv6 gagal sepenuhnya — tetapi rekod AAAA yang tidak sah yang menghala ke hos yang menerima sambungan tetapi memberikan kandungan lain akan menyebabkan kegagalan mutlak.

Penghalaan semula (Redirects) adalah dibenarkan: pengesahan akan mengikut penghalaan semula HTTP ke HTTPS dan tidak mempedulikan sama ada sijil di hujung sana hilang, tamat tempoh, atau ditandatangani sendiri (self-signed). Namun, ia tidak akan bermula di mana-mana selain port 80. Certbot tidak mempunyai pelaksanaan TLS-ALPN-01, jadi cadangan "gunakan sahaja 443" bukanlah jalan penyelesaian.

Memilih pengesah: --nginx, --webroot, --standalone

--nginx adalah pilihan lalai yang tepat jika nginx sudah berjalan dan sudah melayani domain tersebut. Certbot membaca konfigurasi anda, memasukkan lokasi cabaran sementara, memuat semula nginx, melakukan pengesahan, kemudian menulis arahan TLS ke dalam blok pelayan anda. Tiada masa henti (downtime).

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

Skrip, untuk pelayan baharu:

sudo certbot --nginx \
  -d example.com -d www.example.com \
  --agree-tos -m ops@example.com --no-eff-email \
  --redirect --non-interactive

--webroot adalah tepat apabila anda tidak mahu Certbot mengubah konfigurasi nginx anda — contohnya konfigurasi yang dijana daripada templat, disimpan dalam git, atau dihantar menggunakan Ansible. Certbot hanya menulis fail cabaran 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 tepat apabila tiada perkhidmatan yang mendengar pada port 80: pelayan e-mel, API yang hanya menggunakan port 443, atau skrip but pertama yang berjalan sebelum nginx wujud. Certbot akan menggunakan port 80 itu sendiri selama beberapa saat. Jika nginx sedang berjalan, proses ini akan gagal — hentikan nginx sebelum menjalankan arahan ini:

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

Hook tersebut direkodkan dalam konfigurasi pembaharuan sijil, supaya proses henti/mula yang sama berlaku secara automatik semasa pembaharuan.

Blok pelayan yang berfungsi sebelum dan selepas sijil wujud

Masalah "chicken-and-egg": nginx gagal bermula kerana ssl_certificate merujuk kepada fail yang tidak wujud, manakala Certbot tidak boleh melakukan pengesahan semasa nginx terhenti. Jalankan laman web 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, sahkan jawapan curl -I http://example.com/ dari luar pelayan, kemudian keluarkan sijil. Selepas 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 adalah penting: ia menghalang blok return 301 daripada menyerap permintaan cabaran. Mengekalkan lokasi tersebut pada port 80 memastikan pembaharuan sijil terus berfungsi selepas bahagian laman web yang lain bertukar kepada HTTPS sahaja.

Sintaks HTTP/2 bergantung pada versi nginx anda, dan penggunaan dua bentuk yang bercampur akan menyebabkan ralat permulaan. Ubuntu 24.04 menggunakan nginx 1.24, yang memerlukan sintaks inline — listen 443 ssl http2;. Debian 13 menggunakan nginx yang lebih baharu, yang memerlukan arahan http2 on; yang berasingan. Semak nginx -v terlebih dahulu.

Arahkan nginx ke live/, jangan sesekali ke archive/. Pautan simbolik (symlinks) live/ akan diubah arah pada setiap pembaharuan; penggunaan laluan tetap ke archive/ akan mengunci anda pada sijil yang akan tamat tempoh.

Wildcard bermaksud DNS-01, dan DNS-01 bermaksud plugin

Sijil wildcard (*.example.com) tidak boleh disahkan melalui HTTP-01 — tiada hos tunggal untuk mengambil fail tersebut. DNS-01 adalah satu-satunya jalan: anda membuktikan kawalan dengan menerbitkan rekod _acme-challenge.example.com TXT. Certbot memerlukan kredensial API untuk penyedia DNS anda bagi melakukan proses ini secara automatik, sebab itulah plugin penyedia wujud. Panduan lengkap sijil wildcard menerangkan mekanik rekod TXT dan masalah pembaharuan dalam mod manual; versi Cloudflare yang ringkas menyusul kemudian.

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

Pada laluan apt, ia adalah sudo apt install python3-certbot-dns-cloudflare. Kredensial disimpan dalam fail yang hanya boleh diakses oleh root:

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

Hadkan token kepada hak edit DNS pada zon tersebut sahaja. Ia adalah kunci kepada DNS anda; layan ia seperti kunci.

sudo certbot certonly \
  --dns-cloudflare \
  --dns-cloudflare-credentials /root/.secrets/cloudflare.ini \
  -d example.com -d '*.example.com'

Gunakan tanda petik pada wildcard supaya shell anda tidak melakukan globbing. DNS-01 juga menyelesaikan masalah yang tidak dapat diselesaikan oleh HTTP-01: sijil untuk hos tanpa port 80 awam — perkhidmatan dalaman, peranti yang hanya boleh dicapai melalui self-hosted WireGuard VPN pada VPS, atau panel admin pada antara muka peribadi.

Pembaharuan: tempoh 90 hari, pemasa, dan deploy hook

Sijil Let's Encrypt sah selama 90 hari. Certbot akan memperbaharui sijil apabila baki tempoh kurang daripada 30 hari. Ini memberikan anda ruang 30 hari untuk membaiki kegagalan pembaharuan sebelum berlaku gangguan perkhidmatan. Let's Encrypt tidak lagi menghantar e-mel amaran tamat tempoh — tiada sesiapa akan memaklumkan anda, jadi pemantauan kini adalah tanggungjawab anda.

Semak pemasa yang disertakan semasa pemasangan:

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

certbot renew menyemak setiap konfigurasi dalam /etc/letsencrypt/renewal/, melangkau apa-apa yang berada di luar tempoh 30 hari, dan memperbaharui selebihnya menggunakan flag yang sama seperti semasa pelaksanaan asal. Sebab itulah pelaksanaan pertama adalah penting: ia adalah pelaksanaan yang direkodkan.

Memperbaharui fail pada cakera tidak mengubah apa-apa secara automatik — nginx akan terus menggunakan sijil lama daripada memori sehingga ia diarahkan untuk reload. Tetapkan deploy hook sekali sahaja:

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

Apa-apa fail boleh laksana dalam renewal-hooks/deploy/ akan dijalankan selepas pembaharuan berjaya. Flag --deploy-hook melakukan tugas yang sama untuk satu sijil, dengan menyimpan renew_hook = ... dalam konfigurasi pembaharuannya. certbot --nginx melakukan reload untuk anda; tetapan --webroot dan --standalone tidak melakukannya. Ketiadaan hook adalah punca utama laman web memaparkan sijil tamat tempoh manakala certbot certificates melaporkan sijil baharu dengan berjaya. Apa-apa aplikasi lain yang membaca sijil semasa startup memerlukan hook yang sama — aplikasi dalam bekas (containerised) seperti pemasangan Nextcloud VPS dengan Docker, TLS dan sandaran juga memerlukan langkah restart atau reload yang ditetapkan di sini.

Ujian pembaharuan sebenar

sudo certbot renew --dry-run

Proses ini menjalankan cabaran penuh terhadap persekitaran staging Let's Encrypt: laluan kod yang sama, tembok api yang sama, DNS yang sama, tanpa kos had kadar (rate-limit), dan tiada data ditulis ke cakera. Jika ia berjaya hari ini, pembaharuan automatik dalam 60 hari juga akan berjaya, dengan andaian tiada perubahan pada konfigurasi pelayan.

Dry run tidak membuktikan hook reload anda berfungsi — tingkah laku ini berbeza mengikut versi Certbot. Uji bahagian tersebut secara manual: jalankan skrip hook secara terus, sahkan systemctl reload nginx berjaya, dan semak sudo grep renew_hook /etc/letsencrypt/renewal/example.com.conf.

Ralat yang akan anda hadapi

Could not bind to IPv4 or IPv6.--standalone kerana nginx sedang menggunakan port 80. Gunakan --nginx atau --webroot, atau hentikan nginx sebelum menjalankan proses tersebut. Sahkan pemilik port dengan sudo ss -lntp | grep ':80'.

Timeout during connect (likely firewall problem) — Let's Encrypt tidak dapat mencapai port 80. Periksa secara berperingkat: sudo ufw status (buka menggunakan sudo ufw allow 'Nginx Full'), kemudian tembok api penyedia VPS, kemudian DNS. Uji dari lokasi selain pelayan anda: curl -sSv http://example.com/.well-known/acme-challenge/test. Rekod AAAA yang tidak sah juga menghasilkan mesej yang sama.

unauthorized :: Invalid response from http://example.com/.well-known/acme-challenge/xyz: 404 — port 80 boleh dicapai, tetapi token tidak dihantar. Permintaan masuk ke blok pelayan yang berbeza (semak blok mana yang memiliki default_server), atau direktori yang diberikan kepada -w bukan direktori yang dilayani oleh nginx. Letakkan fail di /var/www/example.com/.well-known/acme-challenge/test dan ambil secara luaran; jika ia menghasilkan ralat 404, sijil tersebut bukan punca masalah.

DNS problem: NXDOMAIN looking up A for example.com — nama tidak dapat diselesaikan secara awam. Rekod baharu yang belum tersebar, atau rekod dalam zon yang tidak disediakan oleh pendaftar anda.

too many certificates already issued for: example.com — had kadar, dan ini sering berlaku semasa proses penyahpepijatan berulang. Let's Encrypt mengehadkan sijil pendua — set nama yang sama tepat — kepada lima setiap minggu, dan secara berasingan membenarkan 50 sijil baharu bagi setiap domain berdaftar setiap minggu; tiada apa yang boleh membatalkan had ini kecuali masa. Lakukan penyahpepijatan menggunakan staging dengan --dry-run.

nginx: [emerg] cannot load certificate "/etc/letsencrypt/live/example.com/fullchain.pem": No such file or directory — nginx dikonfigurasikan untuk sijil yang tidak pernah dikeluarkan, atau sijil yang telah dibuang dengan certbot delete. Komenkan blok pelayan TLS, mulakan nginx, keluarkan sijil, kemudian pulihkan semula blok tersebut.

open() "/etc/letsencrypt/options-ssl-nginx.conf" failed — fail tersebut disertakan bersama pakej plugin nginx. Pada kotak certonly tanpa python3-certbot-nginx, sama ada tambah plugin tersebut atau gantikan baris include dengan tetapan ssl_protocols dan ssl_ciphers anda sendiri.

Menguruskan ini pada skala besar

Satu sijil boleh memuatkan sehingga 100 nama, dan satu certbot --nginx -d a.example.com -d b.example.com ... tunggal memang menarik — sehinggalah satu rekod DNS yang tidak lagi sah gagal dalam pengesahan dan menyebabkan semua nama lain pada sijil tersebut turut gagal. Sijil berasingan bagi setiap tapak akan gagal secara bebas, yang merupakan keadaan yang anda inginkan pada pelayan yang menghoskan lebih daripada beberapa perkara. Selepas mempunyai beberapa tapak, pintu masuk yang menyedari ACME akan memberikan nilai yang berbaloi: Traefik reverse proxy yang menjalankan pelbagai aplikasi di bawah Docker Compose akan meminta dan memperbaharui sijil itu sendiri, dan Certbot tidak lagi diperlukan.

Sandarkan /etc/letsencrypt sepenuhnya — sudo tar -czf letsencrypt-$(date +%F).tar.gz -C /etc letsencrypt — dengan symlinks yang utuh. Pokok direktori tersebut mengandungi accounts/, iaitu kunci akaun ACME anda, yang tidak boleh dijana semula dengan identiti yang sama. Berpindah ke VPS baharu kemudian hanya melibatkan: rsync pokok direktori tersebut dengan -a, pasang Certbot, tetapkan semula DNS, dan jalankan certbot renew --dry-run sebelum anda melakukan peralihan.

Membina semula pelayan atau berpindah ke LTS baharu akan menyebabkan pemasa pembaharuan tidak mengikut anda. Selepas sebarang migrasi, pemulihan snapshot, atau naik taraf distro, jalankan systemctl list-timers 'certbot*' dan satu --dry-run. Mengabaikan langkah ini adalah punca laman web tergendala 89 hari kemudian, pada jam 3 pagi, pada sijil yang disangka semua orang akan diperbaharui secara automatik.

Semua ini mengandaikan anda mengawal mesin dengan IP awam dan port 80 terbuka kepada dunia — dalam erti kata lain, sebuah VPS. Mekanisme di atas adalah sama bagi mana-mana VPS.

Langkah sijil yang sama terpakai pada Apache berbanding nginx, dan apabila sijil awam bukan satu pilihan, sijil self-signed pada Ubuntu boleh digunakan untuk perkhidmatan dalaman.

FAQ

Adakah saya perlu membuka port 80 jika laman saya hanya menggunakan HTTPS?

Ya, untuk cabaran HTTP-01. Let's Encrypt sentiasa memulakan permintaan pengesahan pada port 80. Certbot tidak mempunyai pelaksanaan TLS-ALPN-01, jadi tembok api yang hanya membuka port 443 akan menyekat proses pengeluaran pertama dan setiap pembaharuan automatik selepas itu. Penghalaan (redirect) dari port 80 ke HTTPS adalah dibenarkan — pengesahan akan mengikutinya. Satu-satunya cara untuk mengelakkan port 80 sepenuhnya adalah dengan menggunakan DNS-01 melalui plugin pembekal.

apt atau snap — manakah Certbot yang patut saya pasang untuk nginx pada Ubuntu 24.04?

Gunakan apt. sudo apt install certbot python3-certbot-nginx memberikan Certbot 2.9.0 pada Ubuntu 24.04, yang sudah memadai untuk semua perkara dalam panduan ini, menerima tampalan keselamatan melalui unattended-upgrades, dan tidak memerlukan snapd. Pilih snap hanya jika anda memerlukan versi terbaru dengan segera atau memerlukan plugin DNS yang hanya diedarkan sebagai snap. Dalam kedua-dua keadaan, pilih satu sahaja: dua pemasangan bermaksud dua pemasa pembaharuan yang merujuk ke pokok /etc/letsencrypt yang sama, dan pemasangan yang terlupa akan menyebabkan masalah.

Bolehkah Certbot mengeluarkan sijil wildcard untuk nginx?

Hanya melalui DNS-01. Wildcard seperti *.example.com tidak mempunyai nama hos tunggal untuk mengambil fail cabaran, jadi --nginx, --webroot dan --standalone tidak boleh digunakan. Pasang plugin untuk pembekal DNS anda, letakkan token API yang terhad dalam fail kredensial khusus untuk root, dan jalankan certbot certonly --dns-cloudflare -d example.com -d '*.example.com' dengan meletakkan tanda petikan pada wildcard untuk mengelakkan globbing shell.

Mengapa nginx masih memaparkan sijil lama selepas pembaharuan berjaya?

nginx menyimpan sijil di dalam memori dan tidak mengesan fail baharu pada cakera sehingga ia dimuat semula (reload). certbot --nginx melakukan reload untuk anda, tetapi pelaksanaan --webroot dan --standalone tidak melakukannya, jadi pembaharuan boleh berjaya tetapi pelayar masih memaparkan sijil yang hampir tamat tempoh. Letakkan skrip boleh laksana ke dalam /etc/letsencrypt/renewal-hooks/deploy/ yang menjalankan nginx -t && systemctl reload nginx, supaya ia dijalankan selepas setiap pembaharuan yang berjaya.

Adakah certbot renew --dry-run membuktikan pembaharuan akan berfungsi?

Kebanyakannya. Ia menjalankan cabaran sebenar terhadap persekitaran staging — tembok api yang sama, DNS yang sama, laluan kod yang sama — tanpa kos had kadar (rate-limit) dan tiada data ditulis ke cakera, jadi jika berjaya, bermakna bahagian rangkaian adalah stabil. Walau bagaimanapun, ia tidak membuktikan hook deployment anda berfungsi dengan pasti. Uji perkara itu secara berasingan: jalankan skrip hook secara manual dan semak sudo grep renew_hook /etc/letsencrypt/renewal/example.com.conf.