TLS/SSL dan Let's Encrypt

TLS/SSL dan Let's Encrypt

Bitnesia • Aug 26, 2026 93 •EN

Seluruh virtual host yang sudah kita bangun sejak Bab 12, yaitu example.local, www.example.local, blog.example.local di Nginx maupun Apache, dan app.example.local di Bab 16, masih melayani traffic lewat HTTP polos. Setiap request dan response antara Visitor dan server berjalan sebagai teks biasa yang bisa dibaca siapa saja yang berhasil menyadap jalur jaringan di antara keduanya. Di jaringan WiFi kantor yang dipakai bersama, di hotspot publik, bahkan di jaringan kabel yang salah satu perangkatnya sudah disusupi, Attacker cukup menjalankan packet sniffer seperti Wireshark atau tcpdump untuk membaca isi request tersebut apa adanya, termasuk password login yang dikirim lewat form HTML atau session cookie yang seharusnya bersifat rahasia.

Bab ini menutup celah tersebut dengan menambahkan lapisan TLS (Transport Layer Security) ke seluruh virtual host yang sudah kita bangun. Kita akan mulai dari konsep dasar HTTPS dan sertifikat digital, dilanjutkan dengan Certbot dan Let's Encrypt sebagai cara paling umum mendapatkan sertifikat gratis untuk domain publik sungguhan, lalu mempraktikkan langsung konfigurasi TLS di Nginx dan Apache memakai sertifikat lab, dan ditutup dengan strategi auto-renewal agar sertifikat tidak pernah kedaluwarsa tanpa disadari.

17.1 Konsep HTTPS dan Sertifikat Digital

HTTPS pada dasarnya adalah protokol HTTP yang sama persis dengan yang sudah kita pakai sejak Bab 12, hanya saja seluruh datanya dibungkus lewat TLS sebelum dikirim melalui jaringan. Nama lama protokol ini adalah SSL (Secure Sockets Layer), tetapi seluruh versi SSL (2.0 dan 3.0) sudah dinyatakan usang dan tidak aman untuk dipakai lagi selama bertahun-tahun terakhir. Istilah "SSL" tetap bertahan di percakapan sehari-hari termasuk di judul bab ini, tetapi implementasi yang sebenarnya berjalan di server modern manapun, termasuk yang akan kita konfigurasi di bab ini, adalah TLS versi 1.2 dan 1.3.

17.1.1 Enkripsi dan TLS Handshake Secara Singkat

TLS menggabungkan dua jenis enkripsi sekaligus. Enkripsi asimetris, yang memakai sepasang kunci publik dan kunci privat, dipakai di awal koneksi untuk saling memverifikasi identitas dan menyepakati kunci rahasia bersama, sedangkan enkripsi simetris yang jauh lebih cepat secara komputasi dipakai untuk mengenkripsi data sesungguhnya sepanjang sesi koneksi berlangsung. Proses negosiasi di awal koneksi inilah yang disebut TLS handshake: client mengirim daftar cipher yang didukungnya lewat pesan ClientHello, server membalas dengan memilih cipher, mengirimkan sertifikatnya lewat pesan ServerHello, kedua pihak lalu menghitung kunci sesi yang sama tanpa pernah mengirim kunci privat lewat jaringan, dan barulah setelah itu data aplikasi sungguhan mulai mengalir dalam keadaan terenkripsi.

Detail penuh handshake ini banyak berubah antara TLS 1.2 dan TLS 1.3, terutama soal jumlah round-trip yang dibutuhkan sebelum data bisa mulai dikirim, tetapi bagi Sysadmin yang mengelola web server, detail tersebut sepenuhnya ditangani oleh library TLS di balik layar seperti OpenSSL. Tugas kita cukup menyediakan sertifikat yang valid dan mengaktifkan versi protokol yang aman, bagian yang akan kita praktikkan langsung di Bagian 17.3.

17.1.2 Anatomi Sertifikat X.509 dan Chain of Trust

Sertifikat digital yang dipakai HTTPS mengikuti standar X.509, sebuah format yang mengikat identitas sebuah domain ke sebuah kunci publik, ditandatangani secara digital oleh pihak yang menerbitkannya. Field terpenting di dalam sertifikat ini antara lain Subject (identitas pemilik sertifikat, biasanya nama domain), Issuer (pihak yang menerbitkan dan menandatangani sertifikat), Validity Period (rentang Not Before dan Not After yang menentukan kapan sertifikat mulai dan berhenti berlaku), Public Key, dan tanda tangan digital dari Issuer di bagian akhir. Sejak beberapa tahun terakhir, browser modern seperti Chrome dan Firefox sudah tidak lagi memercayai field Common Name (CN) sendirian, melainkan mewajibkan nama domain terdaftar di extension Subject Alternative Name (SAN), yang juga memungkinkan satu sertifikat menaungi lebih dari satu domain sekaligus, kemampuan yang akan kita manfaatkan langsung di Bagian 17.3.1 untuk menaungi seluruh domain lab dalam satu sertifikat.

Pihak yang menerbitkan sertifikat disebut Certificate Authority (CA). Browser dan sistem operasi menyimpan daftar root CA yang dipercaya secara bawaan di dalam trust store masing-masing. Root CA sendiri hampir tidak pernah langsung menandatangani sertifikat domain, melainkan mendelegasikan tugas itu ke intermediate CA, sedangkan root key-nya disimpan offline demi keamanan. Rangkaian tanda tangan dari sertifikat domain, ke intermediate CA, sampai ke root CA yang dipercaya inilah yang disebut chain of trust. Begitu browser menerima sertifikat dari server, browser menelusuri rantai ini sampai menemukan root CA yang sudah ada di trust store-nya; jika rantai itu terputus atau berujung pada CA yang tidak dikenal, browser menampilkan peringatan keamanan alih-alih membuka koneksi begitu saja.

Sertifikat yang ditandatangani oleh diri sendiri, tanpa CA pihak ketiga sama sekali, disebut self-signed certificate. Secara kriptografis, kekuatan enkripsinya sama persis dengan sertifikat yang diterbitkan CA publik, tetapi karena tidak ada chain of trust menuju root CA manapun yang dikenal browser, self-signed certificate selalu memicu peringatan keamanan di browser Visitor. Sertifikat semacam ini cocok untuk kebutuhan internal seperti lab, staging environment, atau komunikasi antar-server yang Sysadmin kendalikan sepenuhnya, tetapi tidak pernah cocok untuk layanan publik yang diakses Visitor umum, poin yang akan kita bahas lebih jauh di Bagian 17.2.3 saat mencoba menerbitkan sertifikat untuk domain lab kita sendiri.

17.2 Certbot dan Let's Encrypt

Let's Encrypt adalah Certificate Authority nonprofit yang dikelola Internet Security Research Group (ISRG) sejak 2015, menerbitkan sertifikat TLS secara gratis dan sepenuhnya otomatis. Kehadirannya menjadi salah satu pendorong terbesar adopsi HTTPS secara masif di seluruh web publik, karena sebelumnya sertifikat TLS dari CA komersial umumnya berbayar dan proses penerbitannya manual. Certbot, yang dikembangkan Electronic Frontier Foundation (EFF), adalah client resmi paling populer untuk berkomunikasi dengan Let's Encrypt, sekaligus yang akan kita pakai di bab ini.

17.2.1 ACME: Cara Let's Encrypt Memverifikasi Kepemilikan Domain

Let's Encrypt menerbitkan sertifikat lewat protokol standar bernama ACME (Automated Certificate Management Environment, RFC 8555). Berbeda dari CA komersial lama yang memverifikasi identitas pemohon secara manual, ACME membuktikan kepemilikan domain secara otomatis lewat challenge yang harus diselesaikan client, seperti Certbot, sebelum sertifikat diterbitkan. Dua jenis challenge yang paling umum dipakai adalah:

  • HTTP-01: Certbot menaruh file berisi token unik di path /.well-known/acme-challenge/ pada web server, lalu server Let's Encrypt mencoba mengambil file tersebut lewat HTTP di port 80 milik domain yang dimohonkan. Jika file itu berhasil diambil dan isinya cocok, kepemilikan domain dianggap terbukti.
  • DNS-01: Certbot diminta membuat record TXT tertentu pada zone DNS publik milik domain, lalu server Let's Encrypt memverifikasi keberadaan record tersebut lewat query DNS biasa. Challenge jenis ini wajib dipakai untuk sertifikat wildcard (misalnya *.example.com) dan berguna saat port 80 tidak bisa diakses langsung dari internet.

Satu prasyarat yang berlaku untuk kedua jenis challenge di atas sering luput diperhatikan pemula: server validasi milik Let's Encrypt harus benar-benar bisa menjangkau domain yang dimohonkan lewat internet publik, baik lewat HTTP di HTTP-01 maupun lewat DNS publik di DNS-01. Poin inilah yang akan langsung kita buktikan sendiri di Bagian 17.2.3.

17.2.2 Instalasi Certbot

Ubuntu Server menyediakan Certbot langsung dari repository resmi, sehingga instalasinya bisa memakai APT biasa tanpa perlu menambah repository pihak ketiga, konsisten dengan kebiasaan instalasi paket yang sudah kita jalani sejak Bab 6. Certbot dari APT dipecah menjadi paket inti dan paket plugin terpisah untuk setiap web server, supaya server yang hanya memakai Nginx tidak perlu ikut memasang dependency milik Apache, begitu pula sebaliknya.

Langkah Praktik

  1. Perbarui daftar paket, lalu pasang paket inti Certbot.
    sudo apt update
    sudo apt install certbot
    Paket ini saja sudah cukup untuk menerbitkan sertifikat lewat plugin standalone atau webroot, tetapi belum bisa dipakai bersama flag --nginx atau --apache yang akan kita coba di Bagian 17.2.3.
  2. Pasang plugin python3-certbot-nginx agar Certbot bisa membaca dan menyunting konfigurasi Nginx secara otomatis lewat flag --nginx. Sekalian pasang python3-certbot-apache karena lab kita juga memakai Apache sejak Bab 13, meskipun paket ini baru benar-benar relevan sebagai referensi di Bagian 17.2.4.
    sudo apt install python3-certbot-nginx python3-certbot-apache
  3. Pastikan instalasi berhasil dengan memeriksa versinya.
    certbot --version

Verifikasi dan Troubleshooting

  • Nomor versi yang tampil bisa berbeda tergantung kapan repository Ubuntu terakhir disinkronkan, jadi jangan heran jika angkanya tidak sama persis dengan contoh di modul ini, mirip catatan yang sama untuk versi PHP di Bagian 14.1.1.
  • Untuk memastikan kedua plugin benar-benar terpasang, periksa lewat dpkg.
    dpkg -l | grep certbot
    Output harus menampilkan tiga baris paket dengan status ii di kolom pertama, yaitu certbot, python3-certbot-nginx, dan python3-certbot-apache.

17.2.3 Mencoba Menerbitkan Sertifikat untuk Domain Lab

Mari kita buktikan langsung apa yang terjadi saat mencoba menerbitkan sertifikat Let's Encrypt untuk domain www.example.local yang sudah kita bangun sejak Bab 12. Nginx dari Bab 16 seharusnya masih aktif di server ini, jadi kita pakai plugin --nginx yang baru saja dipasang untuk mengedit konfigurasi Nginx secara otomatis.

Langkah Praktik

  1. Jalankan Certbot dengan plugin Nginx, menargetkan domain example.local dan www.example.local sekaligus.
    sudo certbot --nginx -d example.local -d www.example.local
  2. Certbot akan meminta alamat email untuk notifikasi kedaluwarsa sertifikat, lalu meminta persetujuan Terms of Service. Isi seperlunya dan lanjutkan.

Beberapa saat kemudian, proses ini akan gagal dengan pesan kurang lebih seperti berikut.

Certbot failed to authenticate some domains (authenticator: nginx). The Certificate Authority reported these problems:
  Domain: www.example.local
  Type:   dns
  Detail: DNS problem: NXDOMAIN looking up A for www.example.local - check that a DNS record exists for this domain

Hint: The Certificate Authority failed to download the challenge files from the temporary standalone webserver started by Certbot on port 80. Ensure that the listed domains point to this machine and that it can accept inbound connections from the internet.

Kegagalan ini bukan bug, melainkan bukti bahwa mekanisme HTTP-01 di Bagian 17.2.1 bekerja persis seperti seharusnya. Domain example.local memang bisa di-resolve dengan sempurna dari jaringan lab kita berkat BIND9 di Bab 9, tetapi TLD .local sama sekali tidak terdaftar di root DNS publik yang dipakai seluruh internet, sehingga server Let's Encrypt yang mencoba melakukan lookup domain ini dari luar jaringan lab akan selalu mendapati domain tersebut tidak dikenal. Bukan cuma Certbot atau Let's Encrypt, CA publik manapun yang tunduk pada aturan CA/Browser Forum tidak akan pernah menerbitkan sertifikat untuk domain yang kepemilikannya tidak bisa diverifikasi dari internet publik. Ini adalah batasan fundamental dari sistem trust berbasis CA publik, bukan sekadar keterbatasan tooling.

Verifikasi dan Troubleshooting

  • Kesalahan yang sama juga akan muncul untuk domain publik sungguhan yang baru didaftarkan tetapi belum benar-benar diarahkan ke IP publik server lewat record A/AAAA, atau untuk server yang port 80-nya masih diblokir firewall/NAT dari internet. Pesan DNS problem: NXDOMAIN menandakan domainnya sendiri tidak ditemukan, sedangkan Fetching ... Connection refused atau Connection timed out menandakan domain sudah resolve tapi server tidak bisa dihubungi di port 80.
  • Di lapangan, kesalahan mengira domain internal seperti .local, .internal, atau .lan bisa menerima sertifikat Let's Encrypt adalah jebakan yang cukup sering ditemui Sysadmin baru. Bagian 17.2.4 dan 17.3 membahas dua jalan keluar berbeda untuk situasi ini, tergantung apakah domainnya publik sungguhan atau memang murni internal.

17.2.4 Alur Certbot untuk Domain Publik Sungguhan

Untuk Sysadmin yang mengelola server production dengan domain publik terdaftar dan sudah diarahkan lewat DNS publik ke IP server (bukan IP privat seperti 192.168.1.20 yang kita pakai di lab ini), alur Certbot di atas akan berjalan mulus tanpa hambatan. Perintahnya identik dengan yang sudah dicoba di Bagian 17.2.3, cukup ganti domain lab dengan domain publik yang sesungguhnya.

sudo certbot --nginx -d domain-asli-anda.com -d www.domain-asli-anda.com

Untuk Apache, gunakan plugin --apache yang sudah dipasang di Bagian 17.2.2, bekerja dengan cara serupa, membaca dan mengedit langsung file VirtualHost yang relevan.

sudo certbot --apache -d domain-asli-anda.com -d www.domain-asli-anda.com

Kedua plugin ini otomatis menambahkan directive ssl_certificate (Nginx) atau SSLCertificateFile (Apache) ke virtual host yang sudah ada, sekaligus menawarkan opsi untuk membuat redirect otomatis dari HTTP ke HTTPS, persis dua hal yang akan kita konfigurasi secara manual di Bagian 17.3 memakai sertifikat lab.

Certbot tidak pernah menaruh sertifikat langsung di direktori config web server. Setiap sertifikat yang berhasil diterbitkan disimpan di /etc/letsencrypt/live/<nama-domain>/, tepatnya berupa empat symlink yang menunjuk ke revisi terbaru file sertifikat sesungguhnya di /etc/letsencrypt/archive/<nama-domain>/:

  • cert.pem: sertifikat domain itu sendiri.
  • chain.pem: sertifikat intermediate CA.
  • fullchain.pem: gabungan cert.pem dan chain.pem, inilah file yang dirujuk directive ssl_certificate di Nginx maupun SSLCertificateFile di Apache.
  • privkey.pem: private key, dirujuk directive ssl_certificate_key di Nginx maupun SSLCertificateKeyFile di Apache.

Plugin --nginx dan --apache otomatis mengisi kedua directive tersebut dengan path menuju fullchain.pem dan privkey.pem di dalam direktori live, bukan direktori archive, sehingga kita tidak perlu mengatur path secara manual seperti yang akan kita lakukan dengan self-signed certificate di Bagian 17.3. Detail ini juga penting untuk auto-renewal di Bagian 17.4: setiap kali Certbot memperbarui sertifikat, isi archive bertambah dengan revisi baru dan symlink di live otomatis diperbarui menunjuk ke revisi tersebut, sehingga konfigurasi web server yang tetap merujuk ke path live tidak perlu diubah sama sekali setelah renewal.

Bagi server yang tidak memakai Nginx atau Apache sebagai reverse proxy di depan, misalnya server mail atau database yang butuh sertifikat TLS sendiri, Certbot juga menyediakan plugin --standalone yang menjalankan web server sementaranya sendiri di port 80 khusus untuk menyelesaikan challenge, serta plugin --webroot yang menaruh file challenge langsung ke document root web server yang sudah berjalan tanpa perlu mengubah konfigurasinya sama sekali.

AspekDomain publik + Let's EncryptDomain internal/lab + Self-Signed
Trust di browser VisitorOtomatis dipercaya, tanpa peringatanSelalu memicu peringatan keamanan
BiayaGratisGratis
Syarat domainHarus publik dan bisa diverifikasi dari internetBebas, termasuk domain .local
Lokasi penyimpanan/etc/letsencrypt/live/<domain>/Bebas ditentukan sendiri, misalnya /etc/ssl/example.local/
Masa berlaku90 hari, perlu renewal otomatisDitentukan sendiri saat pembuatan, umum 365 hari
Kapan dipakaiLayanan publik yang diakses Visitor umumLab, staging, komunikasi antar-server internal

17.3 Konfigurasi TLS di Nginx dan Apache dengan Self-Signed Certificate

Karena domain lab kita murni internal, bagian ini memakai self-signed certificate untuk mempraktikkan mekanisme konfigurasi TLS yang sesungguhnya di Nginx dan Apache. Directive yang dipakai, seperti ssl_certificate di Nginx dan SSLCertificateFile di Apache, persis sama dengan yang otomatis ditambahkan Certbot pada domain publik sungguhan di Bagian 17.2.4. Bedanya cuma sumber sertifikatnya dan lokasi penyimpanannya, bukan cara mengonfigurasinya di web server.

17.3.1 Membuat Self-Signed Certificate Multi-Domain dengan OpenSSL

Berkat extension SAN yang sudah dibahas di Bagian 17.1.2, kita bisa membuat satu sertifikat saja yang menaungi seluruh domain lab sekaligus, yaitu example.local, www.example.local, blog.example.local, dan app.example.local, sehingga tidak perlu mengulang proses ini satu per satu untuk setiap virtual host. Berbeda dari sertifikat Let's Encrypt yang lokasinya sudah dibakukan di /etc/letsencrypt/live/, self-signed certificate bebas disimpan di mana saja; kita memakai /etc/ssl/example.local/ agar mudah dibedakan dari sertifikat bawaan sistem di /etc/ssl/certs/.

Langkah Praktik

  1. Siapkan direktori khusus untuk menyimpan sertifikat dan private key lab ini.
    sudo mkdir -p /etc/ssl/example.local
  2. Buat file konfigurasi OpenSSL yang mendefinisikan identitas sertifikat beserta daftar SAN-nya.
    sudo nano /etc/ssl/example.local/san.cnf
    [req]
    distinguished_name = req_distinguished_name
    x509_extensions = v3_req
    prompt = no
    
    [req_distinguished_name]
    C = ID
    ST = DKI Jakarta
    L = Jakarta
    O = Linux Server 101 Lab
    CN = example.local
    
    [v3_req]
    subjectAltName = @alt_names
    
    [alt_names]
    DNS.1 = example.local
    DNS.2 = www.example.local
    DNS.3 = blog.example.local
    DNS.4 = app.example.local
  3. Terbitkan private key dan sertifikat self-signed sekaligus dalam satu perintah, berlaku selama 365 hari.
    sudo openssl req -x509 -nodes -newkey rsa:2048 \
      -keyout /etc/ssl/example.local/example.local.key \
      -out /etc/ssl/example.local/example.local.crt \
      -days 365 \
      -config /etc/ssl/example.local/san.cnf
    Flag -nodes membuat private key disimpan tanpa passphrase, pilihan yang wajar untuk sertifikat web server karena passphrase justru akan menghalangi Nginx atau Apache untuk start otomatis tanpa campur tangan manual setiap kali service direstart.
  4. Batasi permission private key hanya bisa dibaca root, mengikuti praktik keamanan standar untuk file kunci kriptografi apapun.
    sudo chmod 600 /etc/ssl/example.local/example.local.key

Verifikasi dan Troubleshooting

  • Periksa isi sertifikat yang baru dibuat, pastikan keempat domain benar-benar tercatat di extension SAN.
    openssl x509 -in /etc/ssl/example.local/example.local.crt -noout -text | grep -A1 "Subject Alternative Name"
    Outputnya harus menampilkan keempat domain persis seperti yang ditulis di san.cnf.
  • Jika perintah openssl req gagal dengan pesan terkait alt_names tidak ditemukan, periksa kembali indentasi dan penulisan section header (tanda kurung siku) di san.cnf, karena OpenSSL cukup ketat terhadap format file konfigurasi semacam ini.

17.3.2 Mengaktifkan HTTPS di Nginx untuk Seluruh Virtual Host

Sertifikat sudah siap, langkah selanjutnya menambahkan blok server baru yang mendengarkan di port 443 untuk setiap virtual host Nginx yang sudah dibangun, sekaligus mengalihkan seluruh traffic HTTP di port 80 ke HTTPS agar Visitor tidak bisa lagi mengakses versi tidak terenkripsi.

Langkah Praktik

  1. Izinkan port 443 di firewall, karena Bab 12 hanya membuka port 80.
    sudo ufw allow 443/tcp
  2. Edit konfigurasi virtual host example.local, ubah blok server yang sudah ada menjadi blok HTTPS, lalu tambahkan blok baru untuk redirect HTTP.
    sudo nano /etc/nginx/sites-available/example.local
    server {
        listen 443 ssl;
        listen [::]:443 ssl;
    
        server_name example.local www.example.local;
        root /var/www/example.local/html;
    
        ssl_certificate /etc/ssl/example.local/example.local.crt;
        ssl_certificate_key /etc/ssl/example.local/example.local.key;
        ssl_protocols TLSv1.2 TLSv1.3;
    
        location / {
            try_files $uri $uri/ =404;
        }
    
        error_page 404 /404.html;
        location = /404.html {
            internal;
        }
    }
    
    server {
        listen 80;
        listen [::]:80;
    
        server_name example.local www.example.local;
    
        return 301 https://$host$request_uri;
    }
    Directive ssl_protocols membatasi Nginx hanya menerima TLS 1.2 dan TLS 1.3, menolak versi lama seperti TLS 1.0 dan 1.1 yang sudah dianggap tidak aman. Blok kedua tidak lagi menyajikan konten apapun, tugasnya cuma satu yaitu memaksa redirect ke HTTPS lewat status 301 Moved Permanently.
  3. Ulangi pola yang sama untuk blog.example.local.
    sudo nano /etc/nginx/sites-available/blog.example.local
    server {
        listen 443 ssl;
        listen [::]:443 ssl;
    
        server_name blog.example.local;
        root /var/www/blog.example.local/html;
    
        ssl_certificate /etc/ssl/example.local/example.local.crt;
        ssl_certificate_key /etc/ssl/example.local/example.local.key;
        ssl_protocols TLSv1.2 TLSv1.3;
    
        location / {
            try_files $uri $uri/ =404;
        }
    }
    
    server {
        listen 80;
        listen [::]:80;
    
        server_name blog.example.local;
    
        return 301 https://$host$request_uri;
    }
  4. Terakhir, terapkan pola yang sama untuk app.example.local dari Bab 16, cukup tambahkan tiga directive ssl_certificate, ssl_certificate_key, dan ssl_protocols ke blok server yang sudah ada, ubah listen-nya menjadi 443 ssl, lalu tambahkan blok redirect port 80 seperti dua domain sebelumnya. Blok upstream dan directive proxy_pass tidak perlu diubah sama sekali.
  5. Uji sintaks seluruh konfigurasi, lalu terapkan.
    sudo nginx -t
    sudo systemctl reload nginx
  6. Uji dari komputer lain di jaringan yang sama. Flag -k dibutuhkan agar curl tidak menolak koneksi hanya karena sertifikatnya self-signed.
    curl -k https://www.example.local
    curl -k https://blog.example.local
    curl -k https://app.example.local
  7. Pastikan redirect HTTP ke HTTPS juga bekerja.
    curl -I http://www.example.local
    Response harus menunjukkan status 301 dengan header Location mengarah ke versi https:// dari domain yang sama.

Verifikasi dan Troubleshooting

  • Tanpa flag -k, curl akan menolak koneksi dengan pesan curl: (60) SSL certificate problem: self-signed certificate. Ini bukan tanda kegagalan konfigurasi, melainkan perilaku yang benar dari curl yang tidak mengenali CA penerbit sertifikat, persis seperti peringatan yang akan dilihat browser Visitor jika mengakses domain ini tanpa pengecualian manual.
  • Jika muncul error nginx: [emerg] cannot load certificate saat nginx -t, periksa kembali path file di directive ssl_certificate dan pastikan proses Nginx (berjalan sebagai www-data, tapi membaca file dilakukan oleh proses master yang berjalan sebagai root) benar-benar bisa mengakses direktori /etc/ssl/example.local/.
  • Untuk melihat detail sertifikat yang benar-benar dikirim server saat handshake, gunakan openssl s_client langsung dari terminal.
    echo | openssl s_client -connect www.example.local:443 -servername www.example.local 2>/dev/null | openssl x509 -noout -dates -subject
    Perintah ini menampilkan subject sertifikat beserta tanggal notBefore dan notAfter, berguna untuk memverifikasi server benar-benar menyajikan sertifikat yang baru saja kita buat, bukan sertifikat lama yang tersisa dari percobaan sebelumnya.

17.3.3 Mengaktifkan HTTPS di Apache dan Redirect HTTP ke HTTPS

Virtual host Apache dari Bab 13 untuk domain example.local dan blog.example.local masih belum tersentuh sejak saat itu. Bagian ini menambahkan HTTPS ke keduanya, memakai ulang sertifikat SAN yang sama persis dari Bagian 17.3.1.

Langkah Praktik

  1. Hentikan Nginx dan aktifkan Apache, mengikuti pola toggle port 80 yang sudah kita biasakan sejak Bab 13 dan Bab 14.
    sudo systemctl stop nginx
    sudo systemctl start apache2
  2. Aktifkan module ssl, yang menyediakan seluruh directive SSL* yang dibutuhkan Apache untuk melayani HTTPS.
    sudo a2enmod ssl
  3. Edit virtual host example.local.conf, tambahkan blok VirtualHost baru untuk port 443 tepat di bawah blok yang sudah ada, lalu ubah blok lama menjadi redirect.
    sudo nano /etc/apache2/sites-available/example.local.conf
    <VirtualHost *:80>
        ServerName example.local
        ServerAlias www.example.local
    
        Redirect permanent / https://example.local/
    </VirtualHost>
    
    <VirtualHost *:443>
        ServerName example.local
        ServerAlias www.example.local
        DocumentRoot /var/www/example.local/html
    
        SSLEngine on
        SSLCertificateFile /etc/ssl/example.local/example.local.crt
        SSLCertificateKeyFile /etc/ssl/example.local/example.local.key
        SSLProtocol -all +TLSv1.2 +TLSv1.3
    
        <Directory /var/www/example.local/html>
            Options -Indexes
            AllowOverride None
            Require all granted
        </Directory>
    
        ErrorLog ${APACHE_LOG_DIR}/example.local.error.log
        CustomLog ${APACHE_LOG_DIR}/example.local.access.log combined
    </VirtualHost>
    Directive SSLProtocol -all +TLSv1.2 +TLSv1.3 setara fungsinya dengan ssl_protocols TLSv1.2 TLSv1.3; di Nginx, mematikan seluruh versi protokol lebih dulu lalu menyalakan kembali hanya dua versi yang masih dianggap aman.
  4. Ulangi pola yang sama untuk blog.example.local.conf.
    sudo nano /etc/apache2/sites-available/blog.example.local.conf
    <VirtualHost *:80>
        ServerName blog.example.local
    
        Redirect permanent / https://blog.example.local/
    </VirtualHost>
    
    <VirtualHost *:443>
        ServerName blog.example.local
        DocumentRoot /var/www/blog.example.local/html
    
        SSLEngine on
        SSLCertificateFile /etc/ssl/example.local/example.local.crt
        SSLCertificateKeyFile /etc/ssl/example.local/example.local.key
        SSLProtocol -all +TLSv1.2 +TLSv1.3
    
        <Directory /var/www/blog.example.local/html>
            Options -Indexes
            AllowOverride None
            Require all granted
        </Directory>
    
        ErrorLog ${APACHE_LOG_DIR}/blog.example.local.error.log
        CustomLog ${APACHE_LOG_DIR}/blog.example.local.access.log combined
    </VirtualHost>
  5. Uji sintaks konfigurasi, lalu restart Apache. Perubahan module mewajibkan restart penuh, bukan sekadar reload, sesuai kebiasaan yang sudah dibahas di Bagian 13.3.1.
    sudo apache2ctl configtest
    sudo systemctl restart apache2
  6. Uji dari komputer lain di jaringan yang sama.
    curl -k https://example.local
    curl -I http://example.local
  7. Setelah pengujian Apache selesai, kembalikan Nginx sebagai web server aktif agar konsisten dengan kondisi akhir Bab 14 dan seluruh praktik Bab 17.
    sudo systemctl stop apache2
    sudo systemctl start nginx

Verifikasi dan Troubleshooting

  • UFW profile Apache Full yang sudah diaktifkan sejak Bab 13 sudah mencakup port 443, jadi tidak perlu menambahkan aturan UFW baru khusus untuk Apache di bagian ini.
  • Jika apache2ctl configtest melaporkan SSL Library Error terkait file sertifikat, periksa kembali permission direktori /etc/ssl/example.local/. Berbeda dari BIND9 di Bab 9, Apache di Ubuntu tidak berjalan di bawah profil AppArmor yang membatasi direktori secara ketat, sehingga penyebab paling umum justru permission Linux biasa yang keliru.
  • Directive Redirect permanent dari module mod_alias sudah aktif secara default di Apache tanpa perlu a2enmod tambahan, berbeda dengan directive redirect berbasis mod_rewrite yang lebih fleksibel namun butuh module terpisah untuk kebutuhan redirect yang lebih kompleks.

17.4 Auto-renewal Sertifikat

Sertifikat Let's Encrypt sengaja dibuat berumur pendek, hanya 90 hari, sebuah keputusan desain yang mendorong seluruh ekosistemnya untuk mengotomasi renewal alih-alih mengandalkan proses manual yang rawan terlewat. Bagian ini membahas bagaimana renewal otomatis bekerja untuk sertifikat Let's Encrypt sungguhan, sekaligus cara memantau kedaluwarsaan sertifikat self-signed yang kita pakai di lab.

17.4.1 Renewal Otomatis Let's Encrypt Lewat Certbot

Paket certbot dari APT yang kita pasang di Bagian 17.2.2 sudah otomatis menyertakan job renewal berkala begitu instalasi selesai, tanpa perlu konfigurasi tambahan apapun dari Sysadmin. Job ini dijadwalkan lewat systemd timer, mekanisme yang sudah kita bahas mendalam di Bab 5, dan berjalan dua kali sehari untuk memeriksa seluruh sertifikat yang pernah diterbitkan Certbot di server tersebut. Certbot hanya benar-benar memperbarui sertifikat yang masa berlakunya tersisa 30 hari atau kurang, sehingga proses pengecekan yang sering ini tidak membebani server Let's Encrypt dengan request renewal yang sia-sia.

Langkah Praktik

  1. Periksa timer renewal yang sudah otomatis aktif sejak instalasi.
    systemctl list-timers | grep certbot
    Baris yang muncul menunjukkan jadwal eksekusi berikutnya dari certbot.timer, bukti bahwa renewal berjalan sebagai proses background tanpa perlu campur tangan manual Sysadmin.

Untuk server yang benar-benar memiliki sertifikat Let's Encrypt aktif hasil dari Bagian 17.2.4, dua perintah berikut adalah yang paling sering dipakai Sysadmin untuk mengelola renewal secara manual.

sudo certbot renew --dry-run
sudo certbot certificates

Flag --dry-run mensimulasikan seluruh proses renewal, termasuk menjalankan ulang ACME challenge, tanpa benar-benar mengganti sertifikat yang sedang aktif, cara paling aman untuk memastikan renewal otomatis akan berjalan mulus jauh sebelum sertifikat sungguhan benar-benar kedaluwarsa. Perintah certbot certificates menampilkan daftar seluruh sertifikat yang dikelola Certbot di server tersebut, termasuk path lengkap ke fullchain.pem dan privkey.pem di /etc/letsencrypt/live/ serta sisa masa berlakunya, jauh lebih cepat dibanding membuka setiap file sertifikat satu per satu.

Verifikasi dan Troubleshooting

  • Karena domain lab kita gagal diverifikasi di Bagian 17.2.3, perintah certbot renew --dry-run dan certbot certificates di server ini akan melaporkan tidak ada sertifikat yang dikelola Certbot, dan itu adalah hal yang wajar. Dua langkah verifikasi ini baru menghasilkan output berarti pada server dengan sertifikat Let's Encrypt sungguhan hasil Bagian 17.2.4.
  • Jika certbot.timer tidak muncul sama sekali di systemctl list-timers, periksa apakah service timer-nya aktif dan enabled.
    systemctl status certbot.timer

17.4.2 Memantau Kedaluwarsaan Sertifikat Self-Signed

Sertifikat self-signed yang kita buat di Bagian 17.3.1 tidak dikelola Certbot sama sekali, sehingga tidak ada renewal otomatis apapun yang berjalan di baliknya. Tanggung jawab memantau kedaluwarsaannya sepenuhnya berada di tangan Sysadmin sendiri.

Langkah Praktik

  1. Periksa tanggal kedaluwarsa sertifikat lab secara langsung dari filenya.
    openssl x509 -enddate -noout -in /etc/ssl/example.local/example.local.crt
    Outputnya berupa satu baris notAfter= diikuti tanggal kedaluwarsa, seharusnya menunjukkan tanggal 365 hari sejak sertifikat ini dibuat di Bagian 17.3.1.
  2. Untuk memastikan tanggal ini tidak terlewat begitu saja, catat pengingat manual atau, lebih baik lagi, buat script pendek yang memeriksa sisa hari sebelum kedaluwarsa dan menjalankannya lewat systemd timer seperti yang sudah dipelajari di Bab 5, alih-alih mengandalkan ingatan sendiri.
    openssl x509 -checkend 2592000 -noout -in /etc/ssl/example.local/example.local.crt && echo "Sertifikat masih berlaku lebih dari 30 hari" || echo "Sertifikat akan kedaluwarsa dalam 30 hari atau kurang"
    Flag -checkend menerima nilai dalam detik, dan 2592000 setara dengan 30 hari, angka ambang yang sama persis dengan yang dipakai Certbot secara internal di Bagian 17.4.1.

Verifikasi dan Troubleshooting

  • Jika sertifikat lab ini benar-benar mendekati kedaluwarsa, cukup ulangi perintah openssl req di Bagian 17.3.1 dengan file san.cnf yang sama untuk menerbitkan sertifikat baru, lalu reload Nginx dan Apache agar keduanya membaca ulang sertifikat dari disk.
  • Untuk kebutuhan yang lebih dari sekadar lab pribadi, misalnya banyak server internal dalam satu organisasi yang semuanya butuh sertifikat TLS, menerbitkan self-signed certificate satu per satu seperti ini mulai terasa merepotkan dan rawan human error. Solusi yang lebih matang di lapangan adalah menjalankan private CA sendiri, misalnya lewat tool seperti step-ca, sehingga satu root certificate internal bisa didistribusikan ke seluruh perangkat di jaringan kantor dan setiap server internal cukup meminta sertifikat baru ke CA tersebut, topik yang berada di luar cakupan series ini tetapi baik untuk diketahui sebagai langkah lanjutan.

Sampai di sini, seluruh virtual host yang sudah kita bangun sejak Bab 12, yaitu example.local, www.example.local, blog.example.local di Nginx maupun Apache, serta app.example.local dari Bab 16, sudah melayani HTTPS lengkap dengan redirect otomatis dari HTTP, dan kita sudah memahami perbedaan mendasar antara sertifikat Let's Encrypt untuk domain publik dengan self-signed certificate untuk kebutuhan internal, termasuk perbedaan lokasi penyimpanan keduanya. Bagian IV series tentang layanan web resmi ditutup di sini. Bab 18 membuka Bagian V, beralih ke database server dengan PostgreSQL 18, komponen yang hampir selalu berdiri di belakang aplikasi web yang sudah kita layani lewat Nginx dan Apache sepanjang bagian ini.