HTTPS adalah HTTP yang dienkripsi dengan TLS (dulu namanya SSL): isi request dan response diacak di jalan, jadi password dan cookie gak bisa dibaca orang di WiFi yang sama. Supaya browser mau tersambung lewat HTTPS, server butuh certificate: kartu identitas digital yang ditandatangani Certificate Authority (CA). Let's Encrypt adalah CA gratis yang mengeluarkan certificate secara otomatis, dan certbot adalah program di server yang memintanya dan memasangnya. Bayangin bikin kartu anggota perpustakaan: petugas mengirim surat ke alamat yang kamu tulis, dan kamu harus menunjukkan surat itu untuk membuktikan alamatnya benar milikmu. Kartunya juga cuma berlaku beberapa bulan, jadi harus rajin diperpanjang.
🧪 Tebakan cepat: firewall web-1 cuma membuka port 22 (SSH) dan 443 (HTTPS). Port 80 sengaja ditutup, toh semuanya mau HTTPS. Kamu menjalankan
sudo certbot --nginx -d catatan.example.com. Berhasil atau gagal? Tebak dulu, jawabannya ada di bagian "Challenge HTTP-01: membuktikan domainnya milikmu".
Cara kerja TLS di dalamnya (handshake, rantai certificate, HSTS) sudah dibahas di pelajaran HTTPS & TLS di track Security. Di sini fokusnya praktik: memasang certificate di nginx yang sudah jadi reverse proxy catatan-api. Satu catatan: catatan.example.com cuma nama contoh. Let's Encrypt menolak domain example.com karena dicadangkan untuk dokumentasi, jadi di server sungguhan pakai domainmu sendiri.
Meminta certificate dengan certbot
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d catatan.example.com -d www.catatan.example.com
-dmenyebut tiap nama yang harus tercantum di certificate.wwwjuga perlu disebut, kalau gak,https://www.catatan.example.comditolak browser.--nginxartinya certbot memakai nginx dua kali: untuk lolos challenge, dan untuk memasang certificate ke config. Untuk Apache,--apache.- Waktu pertama kali, certbot menanyakan email dan persetujuan Terms of Service sekali, lalu mendaftarkan akun ACME (protokol yang dipakai Let's Encrypt).
Kalau berhasil, ini yang tercetak (di Lab, ditambah bingkai ajakan donasi di bawahnya):
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for catatan.example.com and www.catatan.example.com
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/catatan.example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/catatan.example.com/privkey.pem
This certificate expires on 2027-01-07.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Deploying certificate
Successfully deployed certificate for catatan.example.com to /etc/nginx/sites-enabled/catatan
Successfully deployed certificate for www.catatan.example.com to /etc/nginx/sites-enabled/catatan
Congratulations! You have successfully enabled HTTPS on https://catatan.example.com and https://www.catatan.example.com
fullchain.pemberisi certificate situs plus certificate intermediate, supaya browser bisa menelusuri rantainya.privkey.pemadalah private key: cuma root yang boleh membacanya, jangan pernah di-commit.- Certificate dikeluarkan 9 Oktober 2026 dan berlaku 90 hari, sampai 2027-01-07.
Challenge HTTP-01: membuktikan domainnya milikmu
Let's Encrypt gak kenal kamu. Sebelum mengeluarkan certificate, dia minta bukti bahwa kamu menguasai server di balik nama itu, lewat challenge HTTP-01:
- certbot meminta certificate untuk dua nama tadi.
- Let's Encrypt memberi satu token (teks acak) per nama: "taruh jawaban untuk token ini di
http://catatan.example.com/.well-known/acme-challenge/<token>". - certbot menyuruh nginx menjawab path itu untuk sementara.
- Server Let's Encrypt, dari beberapa lokasi di dunia, mencari IP
catatan.example.comlewat DNS (203.0.113.10), lalu membuka URL tadi lewat port 80. - Jawabannya cocok? Certificate dikeluarkan, certbot menyimpannya dan memasangnya ke nginx.
Port 80 tertutup, jadi langkah 4 gak pernah tersambung, dan certbot gagal. Itu jawaban tebakannya. Pesannya:
Certbot failed to authenticate some domains (authenticator: nginx). The Certificate Authority reported these problems:
Domain: catatan.example.com
Type: connection
Detail: 203.0.113.10: Fetching http://catatan.example.com/.well-known/acme-challenge/oxq7J0ax22How6lDMneZGC4fAjOGM9lE40rw65FFR2o: Timeout during connect (likely firewall problem)
Buka port 80 dan 443 dengan sudo ufw allow 'Nginx Full', lalu ulangi. Penyebab gagal yang lain: DNS masih menunjuk server lama (pesannya Invalid response from ...: 404), atau nama itu belum punya record A (pesannya DNS problem: NXDOMAIN looking up A for ...).
Yang ditulis certbot ke config nginx
certbot menambahkan baris bertanda # managed by Certbot. Hasilnya setara dengan config tulisan tangan ini:
server {
listen 80;
listen [::]:80;
server_name catatan.example.com www.catatan.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name catatan.example.com www.catatan.example.com;
ssl_certificate /etc/letsencrypt/live/catatan.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/catatan.example.com/privkey.pem;
# location /lampiran/ dan location / dari pelajaran Reverse Proxy
}
- Server block port 80 sekarang cuma mengalihkan:
return 301 https://$host$request_uri;menyuruh browser membuka alamat yang sama lewat HTTPS.301artinya pindah permanen. - Server block port 443 memegang TLS. App di
127.0.0.1:3000tetap menerima HTTP polos: ini SSL termination, danX-Forwarded-Protosekarang berisihttps. curl -I http://catatan.example.com/catatansekarang menjawabHTTP/1.1 301 Moved Permanentlydengan headerLocation: https://catatan.example.com/catatan.
Header HSTS yang memaksa browser selalu HTTPS dibahas di pelajaran Security Headers.
90 hari, lalu diperpanjang otomatis
Certificate Let's Encrypt berlaku 90 hari, dan Let's Encrypt sudah mengumumkan masa berlakunya bakal makin pendek beberapa tahun ke depan. Memperpanjang dengan tangan pasti suatu hari lupa, jadi certbot dari apt memasang systemd timer certbot.timer yang menjalankan certbot renew dua kali sehari. Certificate baru benar-benar diperpanjang kalau sisa umurnya 30 hari atau kurang:
| Hari | Kejadian |
|---|---|
| 0 (9 Okt 2026) | certificate dikeluarkan, berlaku sampai 7 Jan 2027 |
| 1 sampai 59 | timer jalan, certbot renew bilang "not due for renewal yet" |
| 60 (8 Des 2026) | sisa 30 hari: challenge diulang, certificate baru berlaku sampai 8 Mar 2027, nginx di-reload |
| 90 tanpa renewal | browser menolak: NET::ERR_CERT_DATE_INVALID |
Uji jalur perpanjangannya sekarang dengan sudo certbot renew --dry-run, jangan menunggu hari ke-60. --dry-run menjalankan seluruh proses ke server uji (staging) Let's Encrypt tanpa mengganti certificate-mu. Kalau di sini gagal, renewal sungguhan juga bakal gagal. Let's Encrypt juga sudah berhenti mengirim email pengingat kedaluwarsa sejak 2025, jadi pastikan timer-nya jalan.
Membaca URL di kode
Di latihan, kamu membedah URL jadi { protocol, isSecure, domain, port }. Port yang gak ditulis berarti port bawaan: 80 untuk http, 443 untuk https.
| URL | protocol | isSecure | domain | port |
|---|---|---|---|---|
https://catatan.example.com |
"https" |
true |
"catatan.example.com" |
443 |
http://catatan.example.com |
"http" |
false |
"catatan.example.com" |
80 |
http://localhost:3000 |
"http" |
false |
"localhost" |
3000 |
function analyzeUrl(url) {
const u = new URL(url);
const protocol = u.protocol.replace(":", ""); // "https:" jadi "https"
const isSecure = protocol === "https";
const port = u.port ? Number(u.port) : isSecure ? 443 : 80;
return { protocol, isSecure, domain: u.hostname, port };
}
new URL()menulisprotocoldengan titik dua ("https:"), jadi titik duanya dibuang.u.portkosong ("") kalau port-nya bawaan, dan berupa teks ("3000") kalau ditulis, jadi diubah ke angka denganNumber.- Urutan key-nya
protocol,isSecure,domain,port, karena hasilnya dibandingkan sebagai teks JSON.
⚠️ Jebakan yang sering ketemu
- Menutup port 80. Challenge HTTP-01 dan redirect ke HTTPS dua-duanya lewat port 80. Buka 80 dan 443.
- DNS belum mengarah ke server. Termasuk record AAAA lama: Let's Encrypt mencoba IPv6 duluan kalau ada AAAA, dan gagal kalau IPv6-nya menunjuk server lain.
- Mencoba berkali-kali saat salah. Let's Encrypt membatasi 5 validasi gagal per jam untuk nama yang sama. Betulkan dulu masalahnya, dan pakai
--dry-rununtuk mencoba. - Gak pernah menguji renewal. Semua tampak beres sampai hari ke-90. Jalankan
sudo certbot renew --dry-runsetiap kali config nginx berubah.
TL;DR: HTTPS mengenkripsi HTTP dengan TLS, dan butuh certificate dari CA; Let's Encrypt memberikannya gratis lewat certbot: sudo certbot --nginx -d catatan.example.com -d www.catatan.example.com. Challenge HTTP-01 membuktikan kepemilikan: Let's Encrypt membuka http://nama/.well-known/acme-challenge/<token> lewat port 80, jadi DNS harus mengarah ke server dan port 80 harus terbuka. certbot menyimpan fullchain.pem dan privkey.pem di /etc/letsencrypt/live/<nama>/, menambahkan listen 443 ssl dan redirect 301 ke HTTPS, dan memasang certbot.timer yang memperpanjang certificate 90 hari itu saat sisanya 30 hari. Uji dengan sudo certbot renew --dry-run. Di URL, port bawaan http 80 dan https 443.