<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.2.0">Jekyll</generator><link href="https://www.udienz.web.id/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.udienz.web.id/" rel="alternate" type="text/html" /><updated>2026-11-05T01:47:14+00:00</updated><id>https://www.udienz.web.id/feed.xml</id><title type="html">udienz blog</title><subtitle>A personal blog, talk about life, and other stuff</subtitle><author><name>Mahyuddin Susanto</name></author><entry><title type="html">Cara Mendapat A+ di SSL Labs dengan Apache (Panduan 2026)</title><link href="https://www.udienz.web.id/2026/11/05/ssl-labs-a-plus-apache-id" rel="alternate" type="text/html" title="Cara Mendapat A+ di SSL Labs dengan Apache (Panduan 2026)" /><published>2026-11-05T00:00:00+00:00</published><updated>2026-11-05T00:00:00+00:00</updated><id>https://www.udienz.web.id/2026/11/05/ssl-labs-a-plus-apache-id</id><content type="html" xml:base="https://www.udienz.web.id/2026/11/05/ssl-labs-a-plus-apache-id">&lt;p&gt;Untuk dapat A+ di &lt;a href=&quot;https://www.ssllabs.com/ssltest/&quot;&gt;SSL Labs Server Test&lt;/a&gt; dari Qualys dengan Apache httpd, syaratnya sama dengan web server lain: hanya TLS 1.2 dan TLS 1.3, cipher ECDHE dengan AEAD (GCM atau ChaCha20-Poly1305), sertifikat dikirim bersama chain lengkapnya, header HSTS dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age&lt;/code&gt; minimal enam bulan, dan konfigurasi yang sama di semua alamat IP hostname tersebut. Di Apache, ada dua hal yang menentukan berhasil atau tidaknya: header HSTS harus memakai &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header always set&lt;/code&gt;, bukan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header set&lt;/code&gt;, dan virtual host yang punya &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLProtocol&lt;/code&gt; atau &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCipherSuite&lt;/code&gt; sendiri akan diam-diam mengalahkan pengaturan global.&lt;/p&gt;

&lt;p&gt;Tulisan ini memberi konfigurasi yang bisa langsung dipasang di Apache Debian atau Ubuntu, menjelaskan tiap barisnya, dan menunjukkan cara mengecek hasilnya sebelum menjalankan SSL Labs.&lt;/p&gt;

&lt;p&gt;Konfigurasi di bawah sudah diuji di Apache 2.4.69 dengan OpenSSL 3.5.7, memakai layout &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/apache2&lt;/code&gt; bawaan Debian 13 dengan modul, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt;, dan file site dari tulisan ini diaktifkan, lalu dicek dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl s_client&lt;/code&gt; dan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read in English:&lt;/strong&gt; &lt;a href=&quot;/2026/11/05/ssl-labs-a-plus-apache&quot;&gt;How to Get an A+ on SSL Labs with Apache httpd&lt;/a&gt;. Pakai nginx? Lihat &lt;a href=&quot;/2026/11/05/ssl-labs-a-plus-nginx-id&quot;&gt;Cara Mendapat A+ di SSL Labs dengan nginx&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/ssl-labs-a-plus-apache-id.png&quot; alt=&quot;Tangga grade SSL Labs untuk Apache: apa yang menahan server di B atau A-, dan syarat A+&quot; /&gt;&lt;/p&gt;

&lt;details class=&quot;toc&quot;&gt;
  &lt;summary&gt;Daftar isi&lt;/summary&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#cara-ssl-labs-memberi-nilai&quot; id=&quot;markdown-toc-cara-ssl-labs-memberi-nilai&quot;&gt;Cara SSL Labs memberi nilai&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#cek-versi-apache-dan-openssl-dulu&quot; id=&quot;markdown-toc-cek-versi-apache-dan-openssl-dulu&quot;&gt;Cek versi Apache dan OpenSSL dulu&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#langkah-1-sertifikat-dan-full-chain&quot; id=&quot;markdown-toc-langkah-1-sertifikat-dan-full-chain&quot;&gt;Langkah 1: Sertifikat dan full chain&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#langkah-2-aktifkan-modul-dan-atur-tls-secara-global&quot; id=&quot;markdown-toc-langkah-2-aktifkan-modul-dan-atur-tls-secara-global&quot;&gt;Langkah 2: Aktifkan modul dan atur TLS secara global&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#langkah-3-virtual-host-hsts-dan-redirect-http&quot; id=&quot;markdown-toc-langkah-3-virtual-host-hsts-dan-redirect-http&quot;&gt;Langkah 3: Virtual host, HSTS, dan redirect HTTP&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#kenapa-harus-header-always-set&quot; id=&quot;markdown-toc-kenapa-harus-header-always-set&quot;&gt;Kenapa harus &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header always set&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#langkah-4-waspadai-virtual-host-yang-menimpa-pengaturan-global&quot; id=&quot;markdown-toc-langkah-4-waspadai-virtual-host-yang-menimpa-pengaturan-global&quot;&gt;Langkah 4: Waspadai virtual host yang menimpa pengaturan global&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#langkah-5-ocsp-stapling-dan-lets-encrypt&quot; id=&quot;markdown-toc-langkah-5-ocsp-stapling-dan-lets-encrypt&quot;&gt;Langkah 5: OCSP stapling dan Let’s Encrypt&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#langkah-6-jebakan-configtest&quot; id=&quot;markdown-toc-langkah-6-jebakan-configtest&quot;&gt;Langkah 6: Jebakan configtest&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#langkah-7-uji-di-lokal-lalu-jalankan-ssl-labs&quot; id=&quot;markdown-toc-langkah-7-uji-di-lokal-lalu-jalankan-ssl-labs&quot;&gt;Langkah 7: Uji di lokal, lalu jalankan SSL Labs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#troubleshooting-arti-pesan-di-laporan-dan-cara-memperbaikinya&quot; id=&quot;markdown-toc-troubleshooting-arti-pesan-di-laporan-dan-cara-memperbaikinya&quot;&gt;Troubleshooting: arti pesan di laporan dan cara memperbaikinya&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#opsional-hsts-preload&quot; id=&quot;markdown-toc-opsional-hsts-preload&quot;&gt;Opsional: HSTS preload&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#konfigurasi-lengkap&quot; id=&quot;markdown-toc-konfigurasi-lengkap&quot;&gt;Konfigurasi lengkap&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sumber&quot; id=&quot;markdown-toc-sumber&quot;&gt;Sumber&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/details&gt;

&lt;h2 id=&quot;cara-ssl-labs-memberi-nilai&quot;&gt;Cara SSL Labs memberi nilai&lt;/h2&gt;

&lt;p&gt;SSL Labs menilai dukungan protokol (30%), key exchange (30%), dan kekuatan cipher (40%), lalu memberlakukan batas atas (cap) untuk masalah tertentu. A+ adalah bonus untuk server ber-grade A tanpa warning. Aturan yang berlaku sekarang adalah versi 2009r dari &lt;a href=&quot;https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide&quot;&gt;SSL Server Rating Guide&lt;/a&gt;, tertanggal 16 Mei 2025. Batas-batas yang relevan untuk server Apache pada umumnya:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Masalah&lt;/th&gt;
      &lt;th&gt;Grade maksimal&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;SSLv2, SSLv3 sebagai protokol terbaik, cipher export, bug sekelas Heartbleed&lt;/td&gt;
      &lt;td&gt;F&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Tidak mendukung TLS 1.2&lt;/td&gt;
      &lt;td&gt;C&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;TLS 1.0 atau TLS 1.1 aktif&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Tanpa forward secrecy (tanpa ECDHE/DHE)&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Tanpa cipher AEAD (GCM atau ChaCha20-Poly1305)&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Chain sertifikat tidak lengkap&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Key atau parameter DH di bawah 2048 bit&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Tidak mendukung TLS 1.3&lt;/td&gt;
      &lt;td&gt;A-&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;HSTS tidak ada atau tidak valid&lt;/td&gt;
      &lt;td&gt;A-&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Untuk A+, panduan itu mensyaratkan konfigurasi tanpa warning dan HSTS dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age&lt;/code&gt; minimal enam bulan (15768000 detik). Sejak revisi Mei 2025, sekadar dapat A pun butuh TLS 1.3 sekaligus header HSTS yang valid, dan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TLS_FALLBACK_SCSV&lt;/code&gt; tidak dihitung lagi.&lt;/p&gt;

&lt;p&gt;Sertifikat ECDSA P-256 atau RSA 2048 sudah cukup. Nilai key exchange-nya 90 dan tetap dapat A+.&lt;/p&gt;

&lt;h2 id=&quot;cek-versi-apache-dan-openssl-dulu&quot;&gt;Cek versi Apache dan OpenSSL dulu&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apache2 &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
apache2ctl &lt;span class=&quot;nt&quot;&gt;-M&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; ssl &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; headers &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; rewrite &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; http2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Versi OpenSSL yang dipakai Apache tercetak di error log saat start, di baris seperti &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Apache/2.4.69 (Debian) OpenSSL/3.5.7 configured -- resuming normal operations&lt;/code&gt;.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Fitur&lt;/th&gt;
      &lt;th&gt;Butuh&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;TLS 1.3 (dan baris &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCipherSuite TLSv1.3 ...&lt;/code&gt;)&lt;/td&gt;
      &lt;td&gt;Apache 2.4.37+ dengan OpenSSL 1.1.1+ (dukungan TLS 1.3 tercatat di 2.4.36, versi yang tidak pernah dirilis)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Intermediate di &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCertificateFile&lt;/code&gt; (tanpa &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCertificateChainFile&lt;/code&gt;)&lt;/td&gt;
      &lt;td&gt;Apache 2.4.8+&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLOpenSSLConfCmd&lt;/code&gt; (dipakai di sini untuk mengatur kurva)&lt;/td&gt;
      &lt;td&gt;Apache 2.4.8+ dengan OpenSSL 1.0.2+&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Protocols h2 http/1.1&lt;/code&gt; (HTTP/2)&lt;/td&gt;
      &lt;td&gt;Apache 2.4.17+&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLProtocol&lt;/code&gt; per virtual host dihormati saat ada SNI&lt;/td&gt;
      &lt;td&gt;Apache 2.4.42+ dengan OpenSSL 1.1.1+&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grup hybrid post-quantum &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;OpenSSL 3.5+&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;langkah-1-sertifikat-dan-full-chain&quot;&gt;Langkah 1: Sertifikat dan full chain&lt;/h2&gt;

&lt;p&gt;Dengan Let’s Encrypt dan Certbot, ambil sertifikatnya saja, lalu tulis konfigurasi TLS sendiri:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;certbot certonly &lt;span class=&quot;nt&quot;&gt;--apache&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; example.com &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; www.example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Certbot 2.0 ke atas membuat key ECDSA secara default.&lt;/p&gt;

&lt;p&gt;Arahkan Apache ke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fullchain.pem&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;SSLCertificateFile&lt;/span&gt;    /etc/letsencrypt/live/example.com/fullchain.pem
&lt;span class=&quot;nc&quot;&gt;SSLCertificateKeyFile&lt;/span&gt; /etc/letsencrypt/live/example.com/privkey.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sejak Apache 2.4.8, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCertificateFile&lt;/code&gt; boleh berisi sertifikat intermediate setelah sertifikat utama, dan &lt;a href=&quot;https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslcertificatefile&quot;&gt;dokumentasi mod_ssl&lt;/a&gt; menyebut &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCertificateChainFile&lt;/code&gt; sudah usang. Kalau &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCertificateFile&lt;/code&gt; diarahkan ke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cert.pem&lt;/code&gt; dan chain file dibuang, intermediate-nya hilang. Browser sering melengkapinya sendiri, tapi SSL Labs akan menulis “Chain issues: Incomplete” dan membatasi grade di B.&lt;/p&gt;

&lt;p&gt;Kalau memakai installer Certbot (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;certbot --apache&lt;/code&gt; tanpa &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;certonly&lt;/code&gt;), ia menambahkan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Include /etc/letsencrypt/options-ssl-apache.conf&lt;/code&gt; di dalam virtual host. File itu mengatur protokol dan cipher sendiri, dan karena letaknya di virtual host, ia mengalahkan file global dari Langkah 2. Hapus baris include itu, tapi lihat dulu apa lagi yang diatur file tersebut: &lt;a href=&quot;https://github.com/certbot/certbot/blob/main/certbot/src/certbot/_internal/plugins/apache/tls_configs/current-options-ssl-apache.conf&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;options-ssl-apache.conf&lt;/code&gt;&lt;/a&gt; versi sekarang diawali &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLEngine on&lt;/code&gt;. Cek dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep -n SSLEngine /etc/letsencrypt/options-ssl-apache.conf&lt;/code&gt; dan, kalau ada, tambahkan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLEngine on&lt;/code&gt; ke virtual host itu sendiri. Tanpa baris itu, Apache melayani HTTP biasa di port 443 tanpa pesan error.&lt;/p&gt;

&lt;h2 id=&quot;langkah-2-aktifkan-modul-dan-atur-tls-secara-global&quot;&gt;Langkah 2: Aktifkan modul dan atur TLS secara global&lt;/h2&gt;

&lt;p&gt;Aktifkan modul yang dipakai di tulisan ini:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;a2enmod ssl headers rewrite http2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a2enmod ssl&lt;/code&gt; sekaligus mengaktifkan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socache_shmcb&lt;/code&gt; untuk session cache. Di Debian 13, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/apache2/mods-available/ssl.conf&lt;/code&gt; bawaan lalu berisi baris-baris ini (komentar dibuang):&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;SSLSessionCache&lt;/span&gt;     shmcb:${APACHE_RUN_DIR}/ssl_scache(512000)
&lt;span class=&quot;nc&quot;&gt;SSLSessionCacheTimeout&lt;/span&gt;  300
&lt;span class=&quot;nc&quot;&gt;SSLCipherSuite&lt;/span&gt; HIGH:!aNULL
&lt;span class=&quot;nc&quot;&gt;SSLProtocol&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;all&lt;/span&gt; -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
&lt;span class=&quot;nc&quot;&gt;SSLSessionTickets&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;off&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Protokolnya sudah benar. Daftar cipher-nya yang terlalu longgar. Dengan pengaturan bawaan saja, server tes masih menerima suite CBC, key exchange RSA biasa tanpa forward secrecy, dan DHE:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-cipher &apos;ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA&apos;  -&amp;gt;  Cipher is ECDHE-ECDSA-AES128-SHA
-cipher &apos;AES256-GCM-SHA384&apos;                            -&amp;gt;  Cipher is AES256-GCM-SHA384
-cipher &apos;DHE-RSA-AES256-GCM-SHA384&apos;                    -&amp;gt;  Cipher is DHE-RSA-AES256-GCM-SHA384
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;SSL Labs menandai suite CBC dan RSA biasa dengan label WEAK di daftar cipher-nya, dan TLSRef tidak memasukkan DHE sama sekali. Tidak ada alasan untuk tetap menawarkan semuanya. Rilis lain bisa punya nilai bawaan berbeda, jadi cek punya Anda dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep -v &apos;^\s*#&apos; /etc/apache2/mods-available/ssl.conf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Biarkan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl.conf&lt;/code&gt; apa adanya, lalu taruh pengaturan di &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/apache2/conf-available/tls.conf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Pengaturan TLS untuk semua virtual host HTTPS (konteks server config)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLProtocol&lt;/span&gt;             -all +TLSv1.2 +TLSv1.3

&lt;span class=&quot;c&quot;&gt;# OpenSSL 3.5+: grup hybrid post-quantum di depan.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Di OpenSSL 3.0-3.4, hapus X25519MLKEM768 dari daftar ini.&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLOpenSSLConfCmd&lt;/span&gt;       Curves X25519MLKEM768:X25519:prime256v1:secp384r1

&lt;span class=&quot;c&quot;&gt;# TLS 1.2: hanya key exchange ECDHE + AEAD. TLS 1.3: tiga suite standar.&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLCipherSuite&lt;/span&gt;          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
&lt;span class=&quot;nc&quot;&gt;SSLCipherSuite&lt;/span&gt;          TLSv1.3 TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
&lt;span class=&quot;nc&quot;&gt;SSLHonorCipherOrder&lt;/span&gt;     &lt;span class=&quot;ss&quot;&gt;off&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLSessionTickets&lt;/span&gt;       &lt;span class=&quot;ss&quot;&gt;off&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Aktifkan:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;a2enconf tls
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apache2.conf&lt;/code&gt; di Debian membaca &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mods-enabled/*.conf&lt;/code&gt; lebih dulu dan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conf-enabled/*.conf&lt;/code&gt; belakangan. Untuk directive-directive ini, nilai global yang datang belakangan menggantikan yang sebelumnya, jadi &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt; menang atas &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl.conf&lt;/code&gt; tanpa perlu mengedit file itu. Di server tes, ketiga suite lemah di atas ditolak begitu &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt; aktif.&lt;/p&gt;

&lt;p&gt;Penjelasan per baris:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLProtocol -all +TLSv1.2 +TLSv1.3&lt;/code&gt;&lt;/strong&gt; mulai dari kosong dan hanya mengizinkan TLS 1.2 dan 1.3. TLS 1.0 atau 1.1 membuat grade mentok di B; tanpa TLS 1.3 mentok di A-.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLOpenSSLConfCmd Curves&lt;/code&gt;&lt;/strong&gt; meneruskan daftar grup key exchange ke OpenSSL. Daftarnya diambil dari &lt;a href=&quot;https://data.tlsref.org/guidelines/6.0.json&quot;&gt;TLSRef guideline 6.0&lt;/a&gt;, penerus Server Side TLS guidelines dari Mozilla, dan sama dengan yang dihasilkan &lt;a href=&quot;https://configurator.tlsref.org/&quot;&gt;TLSRef Configurator&lt;/a&gt; untuk Apache. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt; menggabungkan X25519 dengan algoritma post-quantum ML-KEM; klien yang belum mendukungnya turun ke X25519.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCipherSuite&lt;/code&gt; pertama&lt;/strong&gt; hanya berisi suite ECDHE dengan GCM atau ChaCha20-Poly1305: forward secrecy dan AEAD, tidak ada yang lain. Menurut TLSRef, klien tertua yang masih bisa tersambung adalah Firefox 31, Chrome 49, Safari 9, Android 4.4.2, IE 11 di Windows 10, dan Java 8u161.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCipherSuite TLSv1.3 ...&lt;/code&gt;&lt;/strong&gt; mengatur suite TLS 1.3. Ketiganya memang default OpenSSL; baris ini membuatnya eksplisit.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLHonorCipherOrder off&lt;/code&gt;&lt;/strong&gt; membiarkan klien memilih dari daftar. Semua pilihan sudah kuat, dan ponsel tanpa akselerasi AES di hardware akan memilih ChaCha20.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLSessionTickets off&lt;/code&gt;&lt;/strong&gt;. Dokumentasi mod_ssl memperingatkan bahwa ticket yang dipakai tanpa me-restart web server secara berkala (misalnya harian) merusak forward secrecy. Apache tidak merotasi key ticket sendiri, jadi TLSRef mematikannya. Session resumption tetap jalan lewat session cache &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shmcb&lt;/code&gt; dari &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl.conf&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tanpa parameter DH.&lt;/strong&gt; Daftar cipher tidak berisi suite DHE, jadi parameter DH tidak perlu ditambahkan ke file sertifikat.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;langkah-3-virtual-host-hsts-dan-redirect-http&quot;&gt;Langkah 3: Virtual host, HSTS, dan redirect HTTP&lt;/h2&gt;

&lt;p&gt;Buat &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/apache2/sites-available/example.com.conf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; *:80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;nc&quot;&gt;ServerName&lt;/span&gt; example.com
    &lt;span class=&quot;nc&quot;&gt;ServerAlias&lt;/span&gt; www.example.com

    &lt;span class=&quot;nc&quot;&gt;RewriteEngine&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;On&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;RewriteCond&lt;/span&gt; %{REQUEST_URI} !^/\.well-known/acme-challenge/
    &lt;span class=&quot;nc&quot;&gt;RewriteRule&lt;/span&gt; ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [R=308,QSA,L]
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; *:443&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;nc&quot;&gt;ServerName&lt;/span&gt; example.com
    &lt;span class=&quot;nc&quot;&gt;ServerAlias&lt;/span&gt; www.example.com
    &lt;span class=&quot;nc&quot;&gt;DocumentRoot&lt;/span&gt; /var/www/example.com

    &lt;span class=&quot;nc&quot;&gt;SSLEngine&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;on&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;SSLCertificateFile&lt;/span&gt;    /etc/letsencrypt/live/example.com/fullchain.pem
    &lt;span class=&quot;nc&quot;&gt;SSLCertificateKeyFile&lt;/span&gt; /etc/letsencrypt/live/example.com/privkey.pem

    &lt;span class=&quot;nc&quot;&gt;Protocols&lt;/span&gt; h2 http/1.1

    &lt;span class=&quot;c&quot;&gt;# HSTS: 2 tahun. &quot;always&quot; juga mengirimnya di redirect dan halaman error.&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Header&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;always&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;set&lt;/span&gt; Strict-Transport-Security &quot;max-age=63072000; includeSubDomains&quot;
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Lalu aktifkan site-nya dan reload:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;a2ensite example.com
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apache2ctl configtest &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl reload apache2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Baris &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RewriteCond&lt;/code&gt; membiarkan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/.well-known/acme-challenge/&lt;/code&gt; tetap di HTTP biasa, supaya validasi HTTP-01 Let’s Encrypt dijawab langsung di port 80, tanpa bergantung pada redirect dan konfigurasi HTTPS. Redirect-nya 308, sama dengan config TLSRef.&lt;/p&gt;

&lt;h3 id=&quot;kenapa-harus-header-always-set&quot;&gt;Kenapa harus &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header always set&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod_headers&lt;/code&gt; menyimpan dua daftar header respons. Daftar default (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onsuccess&lt;/code&gt;) dipakai untuk respons normal; &lt;a href=&quot;https://httpd.apache.org/docs/2.4/mod/mod_headers.html#header&quot;&gt;dokumentasi mod_headers&lt;/a&gt; menyebut bahwa untuk respons non-2xx yang dibuat server sendiri, seperti redirect, hanya daftar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;always&lt;/code&gt; yang dipakai.&lt;/p&gt;

&lt;p&gt;Di server tes, dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header set&lt;/code&gt; alih-alih &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header always set&lt;/code&gt; dan baris &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Redirect 302 /old /&lt;/code&gt; di virtual host &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*:443&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;GET /      -&amp;gt;  HTTP/2 200   strict-transport-security: max-age=63072000; includeSubDomains
GET /old   -&amp;gt;  HTTP/2 302   (tanpa header HSTS)
GET /nope  -&amp;gt;  HTTP/2 404   (tanpa header HSTS)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header always set&lt;/code&gt;, ketiga respons membawa header itu. Ini paling terasa kalau halaman utama Anda me-redirect, misalnya &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; ke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/en/&lt;/code&gt; atau ke halaman login: respons HTTPS pertama yang diterima pengunjung adalah redirect itu, dan tanpa &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;always&lt;/code&gt; ia tidak membawa HSTS.&lt;/p&gt;

&lt;p&gt;Catatan HSTS lainnya:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age=63072000&lt;/code&gt;&lt;/strong&gt; sama dengan dua tahun, nilai dari TLSRef. SSL Labs butuh minimal 15768000 (enam bulan) untuk A+.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;includeSubDomains&lt;/code&gt;&lt;/strong&gt; membuat semua subdomain wajib HTTPS di browser yang pernah menerima header ini. Jangan dipasang sebelum itu benar untuk semua subdomain.&lt;/li&gt;
  &lt;li&gt;Header ini hanya di virtual host &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*:443&lt;/code&gt;. Browser mengabaikan HSTS lewat HTTP biasa, dan &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc6797#section-7.2&quot;&gt;RFC 6797 bagian 7.2&lt;/a&gt; melarang server mengirimnya di sana.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apache tidak punya masalah pewarisan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header&lt;/code&gt; seperti nginx. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header set Cache-Control ...&lt;/code&gt; di dalam blok &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Location&amp;gt;&lt;/code&gt; ditambahkan ke header dari virtual host; di server tes, header HSTS tetap ada di respons tersebut.&lt;/p&gt;

&lt;h2 id=&quot;langkah-4-waspadai-virtual-host-yang-menimpa-pengaturan-global&quot;&gt;Langkah 4: Waspadai virtual host yang menimpa pengaturan global&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt; mengatur nilai default untuk seluruh server. Virtual host yang punya &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLProtocol&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCipherSuite&lt;/code&gt; sendiri, atau meng-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Include&lt;/code&gt; file yang mengaturnya, akan memakai nilai itu. Sejak Apache 2.4.42 dengan OpenSSL 1.1.1 ke atas, &lt;a href=&quot;https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslprotocol&quot;&gt;dokumentasi SSLProtocol&lt;/a&gt; menyebut &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLProtocol&lt;/code&gt; milik tiap virtual host name-based dihormati kalau klien mengirim SNI. Sebelum itu, protokol dari virtual host pertama di IP dan port tersebut berlaku untuk semuanya.&lt;/p&gt;

&lt;p&gt;Cari semua tempat yang mengatur opsi TLS:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rn&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; SSLProtocol &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; SSLCipherSuite &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; SSLHonorCipherOrder &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; options-ssl-apache /etc/apache2/
apache2ctl &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Perintah pertama seharusnya hanya menampilkan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mods-available/ssl.conf&lt;/code&gt; dan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt; Anda. Perintah kedua menunjukkan virtual host mana yang menjawab di alamat mana, berguna kalau SSL Labs memberi nilai berbeda untuk IP yang berbeda.&lt;/p&gt;

&lt;h2 id=&quot;langkah-5-ocsp-stapling-dan-lets-encrypt&quot;&gt;Langkah 5: OCSP stapling dan Let’s Encrypt&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLUseStapling&lt;/code&gt; mati secara default di Apache, dan untuk sertifikat Let’s Encrypt sebaiknya tetap begitu. Let’s Encrypt &lt;a href=&quot;https://letsencrypt.org/2024/12/05/ending-ocsp/&quot;&gt;menghentikan dukungan OCSP&lt;/a&gt;: sejak 7 Mei 2025 sertifikatnya tidak lagi memuat URL OCSP, dan responder-nya dimatikan pada 6 Agustus 2025. Tidak ada yang bisa di-staple. (Tulisan saya tahun 2015, &lt;a href=&quot;/2015/04/12/ocsp-stapling-di-nginx&quot;&gt;OCSP Stapling di nginx&lt;/a&gt;, ditulis sebelum perubahan ini.) OCSP stapling juga tidak memengaruhi grade SSL Labs.&lt;/p&gt;

&lt;p&gt;Untuk sertifikat dari CA yang masih menjalankan OCSP, aktifkan di server config (di luar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;VirtualHost&amp;gt;&lt;/code&gt;), misalnya di akhir &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;SSLUseStapling&lt;/span&gt;          &lt;span class=&quot;ss&quot;&gt;on&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLStaplingCache&lt;/span&gt;        &quot;shmcb:${APACHE_RUN_DIR}/ssl_stapling(32768)&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;langkah-6-jebakan-configtest&quot;&gt;Langkah 6: Jebakan configtest&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apache2ctl configtest&lt;/code&gt; hanya mengecek sintaks, bukan apakah OpenSSL menerima nilai yang Anda tulis. Di server tes, nama kurva yang tidak dikenal OpenSSL lolos cek sintaks lalu menghentikan Apache:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ apache2ctl configtest
Syntax OK
$ apache2ctl graceful
# error log:
[ssl:emerg] AH02407: &quot;SSLOpenSSLConfCmd Curves FakeGroup999:X25519:prime256v1:secp384r1&quot; failed for example.test:443
[ssl:emerg] AH02312: Fatal error initialising mod_ssl, exiting.
[:emerg] AH00020: Configuration Failed, exiting
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Graceful reload tidak menyelamatkan Anda di sini. Setelah reload itu, tidak ada satu pun proses Apache yang tersisa, jadi HTTP biasa ikut mati. OpenSSL sebelum 3.5 tidak mengenal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt;, jadi nama itu bisa memicu kegagalan yang sama.&lt;/p&gt;

&lt;p&gt;Karena itu, cek nama grup ke OpenSSL sebelum reload. Di server tes (OpenSSL 3.5.7):&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;openssl list &lt;span class=&quot;nt&quot;&gt;-tls-groups&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;tr&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;:&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\n&apos;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; X25519MLKEM768
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Kalau tidak ada output, atau &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl&lt;/code&gt; Anda tidak mengenal opsi &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-tls-groups&lt;/code&gt;, hapus &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt; dari &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt;. Debian dan Ubuntu membangun Apache dengan OpenSSL sistem, jadi perintah &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl&lt;/code&gt; mengecek library yang sama; untuk build sendiri, bandingkan dengan versi di baris log saat Apache start. Setiap kali mengubah TLS, reload lalu pastikan situs masih menjawab (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl -sI https://example.com/&lt;/code&gt;) sebelum logout.&lt;/p&gt;

&lt;h2 id=&quot;langkah-7-uji-di-lokal-lalu-jalankan-ssl-labs&quot;&gt;Langkah 7: Uji di lokal, lalu jalankan SSL Labs&lt;/h2&gt;

&lt;p&gt;Ganti &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.com&lt;/code&gt; dengan host Anda:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# TLS 1.1 harus ditolak. SECLEVEL=0 supaya klien modern mau mencobanya.&lt;/span&gt;
openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-tls1_1&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-cipher&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;DEFAULT@SECLEVEL=0&apos;&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;alert|Cipher is&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# TLS 1.3 harus jalan. Dengan OpenSSL 3.5+ di kedua sisi, grupnya X25519MLKEM768.&lt;/span&gt;
openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-tls1_3&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Negotiated TLS1.3 group|Cipher is&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Suite CBC, RSA biasa, dan DHE harus ditolak.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;c &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA&apos;&lt;/span&gt; AES256-GCM-SHA384 DHE-RSA-AES256-GCM-SHA384&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
  &lt;/span&gt;openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &lt;span class=&quot;nt&quot;&gt;-tls1_2&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-cipher&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$c&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;alert|Cipher is&apos;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Full chain: server harus mengirim minimal 2 sertifikat (milik Anda + intermediate).&lt;/span&gt;
openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &lt;span class=&quot;nt&quot;&gt;-showcerts&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;/dev/null | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BEGIN CERTIFICATE&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# HSTS di halaman normal dan halaman error, plus redirect HTTP.&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;-sI&lt;/span&gt; https://example.com/ | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; strict-transport-security
curl &lt;span class=&quot;nt&quot;&gt;-sI&lt;/span&gt; https://example.com/does-not-exist | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;^HTTP&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; strict-transport-security
curl &lt;span class=&quot;nt&quot;&gt;-sI&lt;/span&gt; http://example.com/ | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;^HTTP&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;^location&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Di server tes, hasilnya seperti ini (diringkas):&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tls1_1 :  tlsv1 alert protocol version ... Cipher is (NONE)
tls1_3 :  Negotiated TLS1.3 group: X25519MLKEM768
          New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
CBC    :  ssl/tls alert handshake failure
RSA    :  ssl/tls alert handshake failure
DHE    :  ssl/tls alert handshake failure
404    :  HTTP/2 404 + strict-transport-security: max-age=63072000; includeSubDomains
HTTP   :  HTTP/1.1 308 Permanent Redirect
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Setelah itu buka &lt;a href=&quot;https://www.ssllabs.com/ssltest/&quot;&gt;ssllabs.com/ssltest&lt;/a&gt;, masukkan hostname, dan centang “Do not show the results on the boards” kalau tidak ingin hasilnya tampil di daftar publik. Setelah mengubah konfigurasi, klik “Clear cache” di halaman hasil supaya scan diulang.&lt;/p&gt;

&lt;h2 id=&quot;troubleshooting-arti-pesan-di-laporan-dan-cara-memperbaikinya&quot;&gt;Troubleshooting: arti pesan di laporan dan cara memperbaikinya&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Yang muncul&lt;/th&gt;
      &lt;th&gt;Penyebab&lt;/th&gt;
      &lt;th&gt;Perbaikan&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade B, “This server supports TLS 1.0 and TLS 1.1”&lt;/td&gt;
      &lt;td&gt;Ada virtual host atau include yang mengatur &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLProtocol&lt;/code&gt; sendiri&lt;/td&gt;
      &lt;td&gt;Jalankan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; dari Langkah 4; hapus pengaturan itu&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Suite WEAK (CBC, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TLS_RSA_*&lt;/code&gt;) di daftar cipher&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCipherSuite&lt;/code&gt; bawaan distro, atau pengaturan di virtual host&lt;/td&gt;
      &lt;td&gt;Aktifkan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt;; cek dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; dari Langkah 4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade B, “Chain issues: Incomplete”&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCertificateFile&lt;/code&gt; mengarah ke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cert.pem&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Pakai &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fullchain.pem&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade A-, “This server does not support TLS 1.3”&lt;/td&gt;
      &lt;td&gt;Apache sebelum 2.4.37, OpenSSL sebelum 1.1.1, atau &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLProtocol&lt;/code&gt; tanpa &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+TLSv1.3&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Upgrade; cek kedua versi di baris log saat Apache start&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade A-, HSTS tidak terdeteksi padahal sudah dipasang&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod_headers&lt;/code&gt; belum aktif, header dipasang di virtual host yang salah, atau &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header set&lt;/code&gt; tanpa &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;always&lt;/code&gt; di halaman yang me-redirect&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a2enmod headers&lt;/code&gt;; pasang &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header always set&lt;/code&gt; di virtual host &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*:443&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Invalid command &apos;Header&apos;&lt;/code&gt; atau &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;RewriteEngine&apos;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Modul belum aktif&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a2enmod headers rewrite&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Apache berhenti setelah reload padahal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configtest&lt;/code&gt; bilang Syntax OK (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AH02407&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AH02312&lt;/code&gt;)&lt;/td&gt;
      &lt;td&gt;OpenSSL menolak suatu nilai, sering &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt; di OpenSSL sebelum 3.5&lt;/td&gt;
      &lt;td&gt;Hapus grup itu, start Apache lagi; lihat Langkah 6&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;A+ di satu IP, A- di IP lain&lt;/td&gt;
      &lt;td&gt;IPv6 dilayani virtual host atau mesin lain&lt;/td&gt;
      &lt;td&gt;Cek &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apache2ctl -S&lt;/code&gt; dan record AAAA&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade tidak berubah walau Apache sudah diubah&lt;/td&gt;
      &lt;td&gt;Yang diuji CDN, bukan server Anda&lt;/td&gt;
      &lt;td&gt;Lihat di bawah&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Pakai Cloudflare atau CDN lain?&lt;/strong&gt; Kalau proxy aktif, SSL Labs menguji edge CDN, bukan Apache Anda. Grade-nya bergantung pada pengaturan CDN (versi TLS minimum, TLS 1.3, HSTS). Tetap pasang konfigurasi di atas di server origin dan pakai mode “Full (strict)” di Cloudflare supaya koneksi ke server Anda juga diverifikasi.&lt;/p&gt;

&lt;h2 id=&quot;opsional-hsts-preload&quot;&gt;Opsional: HSTS preload&lt;/h2&gt;

&lt;p&gt;HSTS preload memasukkan domain Anda ke daftar yang ditanam di dalam browser. SSL Labs tidak mensyaratkannya untuk A+. &lt;a href=&quot;https://hstspreload.org/&quot;&gt;hstspreload.org&lt;/a&gt; mensyaratkan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age&lt;/code&gt; minimal satu tahun, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;includeSubDomains&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;preload&lt;/code&gt;, HTTPS di semua subdomain, dan redirect HTTP ke HTTPS di host yang sama. Keluar dari daftar itu butuh berbulan-bulan sampai ke pengguna, jadi daftarkan hanya domain yang pasti tetap HTTPS-only di semua subdomain.&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Header&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;always&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;set&lt;/span&gt; Strict-Transport-Security &quot;max-age=63072000; includeSubDomains; preload&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;konfigurasi-lengkap&quot;&gt;Konfigurasi lengkap&lt;/h2&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# /etc/apache2/conf-available/tls.conf   (a2enconf tls)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLProtocol&lt;/span&gt;             -all +TLSv1.2 +TLSv1.3
&lt;span class=&quot;nc&quot;&gt;SSLOpenSSLConfCmd&lt;/span&gt;       Curves X25519MLKEM768:X25519:prime256v1:secp384r1
&lt;span class=&quot;nc&quot;&gt;SSLCipherSuite&lt;/span&gt;          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
&lt;span class=&quot;nc&quot;&gt;SSLCipherSuite&lt;/span&gt;          TLSv1.3 TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
&lt;span class=&quot;nc&quot;&gt;SSLHonorCipherOrder&lt;/span&gt;     &lt;span class=&quot;ss&quot;&gt;off&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLSessionTickets&lt;/span&gt;       &lt;span class=&quot;ss&quot;&gt;off&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# /etc/apache2/sites-available/example.com.conf   (a2ensite example.com)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; *:80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;nc&quot;&gt;ServerName&lt;/span&gt; example.com
    &lt;span class=&quot;nc&quot;&gt;ServerAlias&lt;/span&gt; www.example.com
    &lt;span class=&quot;nc&quot;&gt;RewriteEngine&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;On&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;RewriteCond&lt;/span&gt; %{REQUEST_URI} !^/\.well-known/acme-challenge/
    &lt;span class=&quot;nc&quot;&gt;RewriteRule&lt;/span&gt; ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [R=308,QSA,L]
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; *:443&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;nc&quot;&gt;ServerName&lt;/span&gt; example.com
    &lt;span class=&quot;nc&quot;&gt;ServerAlias&lt;/span&gt; www.example.com
    &lt;span class=&quot;nc&quot;&gt;DocumentRoot&lt;/span&gt; /var/www/example.com
    &lt;span class=&quot;nc&quot;&gt;SSLEngine&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;on&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;SSLCertificateFile&lt;/span&gt;    /etc/letsencrypt/live/example.com/fullchain.pem
    &lt;span class=&quot;nc&quot;&gt;SSLCertificateKeyFile&lt;/span&gt; /etc/letsencrypt/live/example.com/privkey.pem
    &lt;span class=&quot;nc&quot;&gt;Protocols&lt;/span&gt; h2 http/1.1
    &lt;span class=&quot;nc&quot;&gt;Header&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;always&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;set&lt;/span&gt; Strict-Transport-Security &quot;max-age=63072000; includeSubDomains&quot;
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Modul: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a2enmod ssl headers rewrite http2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Untuk melayani sertifikat ECDSA dan RSA sekaligus, ulangi pasangan sertifikat di virtual host yang sama; mod_ssl memilih yang cocok untuk tiap klien:&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Pasangan ECDSA, dari Langkah 1&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLCertificateFile&lt;/span&gt;    /etc/letsencrypt/live/example.com/fullchain.pem
&lt;span class=&quot;nc&quot;&gt;SSLCertificateKeyFile&lt;/span&gt; /etc/letsencrypt/live/example.com/privkey.pem
&lt;span class=&quot;c&quot;&gt;# Pasangan RSA&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLCertificateFile&lt;/span&gt;    /etc/letsencrypt/live/example.com-rsa/fullchain.pem
&lt;span class=&quot;nc&quot;&gt;SSLCertificateKeyFile&lt;/span&gt; /etc/letsencrypt/live/example.com-rsa/privkey.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Di server tes, klien TLS 1.2 yang hanya menawarkan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ECDHE-RSA-AES128-GCM-SHA256&lt;/code&gt; menerima sertifikat RSA 2048 bit, sementara klien lain mendapat ECDSA. Dengan Certbot, jalankan sekali lagi dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--key-type rsa --cert-name example.com-rsa&lt;/code&gt; untuk mendapat pasangan RSA.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Mahyuddin Susanto adalah sysadmin Linux dan jaringan yang mengelola server sendiri dan menulis soal Apache di blog ini sejak 2007, dimulai dari &lt;a href=&quot;/2007/09/27/apache-server-dengan-module-openssl&quot;&gt;Apache server dengan module OpenSSL&lt;/a&gt;. &lt;a href=&quot;/about&quot;&gt;Tentang penulis&lt;/a&gt; · &lt;a href=&quot;/contact&quot;&gt;Kontak&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;sumber&quot;&gt;Sumber&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Qualys SSL Labs, &lt;a href=&quot;https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide&quot;&gt;SSL Server Rating Guide&lt;/a&gt;, versi 2009r, 16 Mei 2025&lt;/li&gt;
  &lt;li&gt;TLSRef, &lt;a href=&quot;https://data.tlsref.org/guidelines/6.0.json&quot;&gt;Server Side TLS guideline 6.0&lt;/a&gt; dan &lt;a href=&quot;https://configurator.tlsref.org/&quot;&gt;TLS Configurator&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Apache HTTP Server 2.4, &lt;a href=&quot;https://httpd.apache.org/docs/2.4/mod/mod_ssl.html&quot;&gt;mod_ssl&lt;/a&gt; dan &lt;a href=&quot;https://httpd.apache.org/docs/2.4/mod/mod_headers.html&quot;&gt;mod_headers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Let’s Encrypt, &lt;a href=&quot;https://letsencrypt.org/2024/12/05/ending-ocsp/&quot;&gt;Ending OCSP Support in 2025&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://hstspreload.org/&quot;&gt;HSTS Preload List Submission&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;IETF, &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc6797&quot;&gt;RFC 6797: HTTP Strict Transport Security&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Mahyuddin Susanto</name></author><category term="Linux" /><category term="apache" /><category term="tls" /><category term="ssl" /><category term="security" /><category term="hsts" /><summary type="html">Untuk dapat A+ di SSL Labs Server Test dari Qualys dengan Apache httpd, syaratnya sama dengan web server lain: hanya TLS 1.2 dan TLS 1.3, cipher ECDHE dengan AEAD (GCM atau ChaCha20-Poly1305), sertifikat dikirim bersama chain lengkapnya, header HSTS dengan max-age minimal enam bulan, dan konfigurasi yang sama di semua alamat IP hostname tersebut. Di Apache, ada dua hal yang menentukan berhasil atau tidaknya: header HSTS harus memakai Header always set, bukan Header set, dan virtual host yang punya SSLProtocol atau SSLCipherSuite sendiri akan diam-diam mengalahkan pengaturan global.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.udienz.web.id/img/ssl-labs-a-plus-apache-id.png" /><media:content medium="image" url="https://www.udienz.web.id/img/ssl-labs-a-plus-apache-id.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">How to Get an A+ on SSL Labs with Apache httpd (2026 Guide)</title><link href="https://www.udienz.web.id/2026/11/05/ssl-labs-a-plus-apache" rel="alternate" type="text/html" title="How to Get an A+ on SSL Labs with Apache httpd (2026 Guide)" /><published>2026-11-05T00:00:00+00:00</published><updated>2026-11-05T00:00:00+00:00</updated><id>https://www.udienz.web.id/2026/11/05/ssl-labs-a-plus-apache</id><content type="html" xml:base="https://www.udienz.web.id/2026/11/05/ssl-labs-a-plus-apache">&lt;p&gt;To get an A+ on the &lt;a href=&quot;https://www.ssllabs.com/ssltest/&quot;&gt;Qualys SSL Labs server test&lt;/a&gt; with Apache httpd, you need the same five things as on any web server: TLS 1.2 and TLS 1.3 only, ECDHE key exchange with AEAD ciphers (GCM or ChaCha20-Poly1305), a certificate served with its full chain, an HSTS header with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age&lt;/code&gt; of at least six months, and the same setup on every IP address your hostname resolves to. On Apache, two details decide whether you get there: the HSTS header needs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header always set&lt;/code&gt;, not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header set&lt;/code&gt;, and a virtual host with its own &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLProtocol&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCipherSuite&lt;/code&gt; silently overrides your global settings.&lt;/p&gt;

&lt;p&gt;This guide gives you a config you can paste into a Debian or Ubuntu Apache, explains each line, and shows how to check the result before you run SSL Labs.&lt;/p&gt;

&lt;p&gt;The configuration below was tested on Apache 2.4.69 with OpenSSL 3.5.7, using the stock Debian 13 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/apache2&lt;/code&gt; layout with the modules, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt; and site file from this guide enabled, and checked with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl s_client&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Baca dalam Bahasa Indonesia:&lt;/strong&gt; &lt;a href=&quot;/2026/11/05/ssl-labs-a-plus-apache-id&quot;&gt;Cara Mendapat A+ di SSL Labs dengan Apache&lt;/a&gt;. Running nginx? See &lt;a href=&quot;/2026/11/05/ssl-labs-a-plus-nginx&quot;&gt;How to Get an A+ on SSL Labs with nginx&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/ssl-labs-a-plus-apache.png&quot; alt=&quot;SSL Labs grade ladder for Apache: what caps a server at B or A-, and what an A+ needs&quot; /&gt;&lt;/p&gt;

&lt;details class=&quot;toc&quot;&gt;
  &lt;summary&gt;Contents&lt;/summary&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#how-ssl-labs-grades-your-server&quot; id=&quot;markdown-toc-how-ssl-labs-grades-your-server&quot;&gt;How SSL Labs grades your server&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#check-your-apache-and-openssl-versions-first&quot; id=&quot;markdown-toc-check-your-apache-and-openssl-versions-first&quot;&gt;Check your Apache and OpenSSL versions first&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#step-1-get-a-certificate-and-serve-the-full-chain&quot; id=&quot;markdown-toc-step-1-get-a-certificate-and-serve-the-full-chain&quot;&gt;Step 1: Get a certificate and serve the full chain&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#step-2-enable-the-modules-and-set-tls-globally&quot; id=&quot;markdown-toc-step-2-enable-the-modules-and-set-tls-globally&quot;&gt;Step 2: Enable the modules and set TLS globally&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#step-3-the-virtual-hosts-hsts-and-the-http-redirect&quot; id=&quot;markdown-toc-step-3-the-virtual-hosts-hsts-and-the-http-redirect&quot;&gt;Step 3: The virtual hosts, HSTS and the HTTP redirect&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#why-header-always-set-matters&quot; id=&quot;markdown-toc-why-header-always-set-matters&quot;&gt;Why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header always set&lt;/code&gt; matters&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#step-4-watch-for-virtual-hosts-that-override-the-global-settings&quot; id=&quot;markdown-toc-step-4-watch-for-virtual-hosts-that-override-the-global-settings&quot;&gt;Step 4: Watch for virtual hosts that override the global settings&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#step-5-ocsp-stapling-and-lets-encrypt&quot; id=&quot;markdown-toc-step-5-ocsp-stapling-and-lets-encrypt&quot;&gt;Step 5: OCSP stapling and Let’s Encrypt&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#step-6-the-configtest-trap&quot; id=&quot;markdown-toc-step-6-the-configtest-trap&quot;&gt;Step 6: The configtest trap&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#step-7-test-locally-then-run-ssl-labs&quot; id=&quot;markdown-toc-step-7-test-locally-then-run-ssl-labs&quot;&gt;Step 7: Test locally, then run SSL Labs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#troubleshooting-what-the-report-says-and-how-to-fix-it&quot; id=&quot;markdown-toc-troubleshooting-what-the-report-says-and-how-to-fix-it&quot;&gt;Troubleshooting: what the report says and how to fix it&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#optional-hsts-preload&quot; id=&quot;markdown-toc-optional-hsts-preload&quot;&gt;Optional: HSTS preload&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-complete-config&quot; id=&quot;markdown-toc-the-complete-config&quot;&gt;The complete config&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sources&quot; id=&quot;markdown-toc-sources&quot;&gt;Sources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/details&gt;

&lt;h2 id=&quot;how-ssl-labs-grades-your-server&quot;&gt;How SSL Labs grades your server&lt;/h2&gt;

&lt;p&gt;SSL Labs scores protocol support (30%), key exchange (30%) and cipher strength (40%), then applies caps for specific problems. The A+ is a bonus on top of an A with no warnings. The current rules are version 2009r of the &lt;a href=&quot;https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide&quot;&gt;SSL Server Rating Guide&lt;/a&gt;, dated 16 May 2025. The caps that matter for a typical Apache server:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Problem&lt;/th&gt;
      &lt;th&gt;Grade limit&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;SSLv2, SSLv3 as the best protocol, export ciphers, Heartbleed-class bugs&lt;/td&gt;
      &lt;td&gt;F&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;TLS 1.2 not supported&lt;/td&gt;
      &lt;td&gt;C&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;TLS 1.0 or TLS 1.1 enabled&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;No forward secrecy (no ECDHE/DHE)&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;No AEAD cipher (GCM or ChaCha20-Poly1305)&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Incomplete certificate chain&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Key or DH parameters under 2048 bits&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;TLS 1.3 not supported&lt;/td&gt;
      &lt;td&gt;A-&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;HSTS missing or invalid&lt;/td&gt;
      &lt;td&gt;A-&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;For the A+, the guide asks for a configuration with no warnings and HSTS with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age&lt;/code&gt; of at least six months (15768000 seconds). Since the May 2025 revision, a plain A needs both TLS 1.3 and a valid HSTS header, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TLS_FALLBACK_SCSV&lt;/code&gt; no longer counts.&lt;/p&gt;

&lt;p&gt;An ECDSA P-256 or RSA 2048 certificate is enough. It scores 90 on key exchange and still gets an A+.&lt;/p&gt;

&lt;h2 id=&quot;check-your-apache-and-openssl-versions-first&quot;&gt;Check your Apache and OpenSSL versions first&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apache2 &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
apache2ctl &lt;span class=&quot;nt&quot;&gt;-M&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; ssl &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; headers &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; rewrite &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; http2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The OpenSSL version that Apache uses is printed in the error log at startup, in a line like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Apache/2.4.69 (Debian) OpenSSL/3.5.7 configured -- resuming normal operations&lt;/code&gt;.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Feature&lt;/th&gt;
      &lt;th&gt;Needs&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;TLS 1.3 (and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCipherSuite TLSv1.3 ...&lt;/code&gt; line)&lt;/td&gt;
      &lt;td&gt;Apache 2.4.37+ with OpenSSL 1.1.1+ (TLS 1.3 support is listed under 2.4.36, which was never released)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Intermediates in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCertificateFile&lt;/code&gt; (no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCertificateChainFile&lt;/code&gt;)&lt;/td&gt;
      &lt;td&gt;Apache 2.4.8+&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLOpenSSLConfCmd&lt;/code&gt; (used here to set curves)&lt;/td&gt;
      &lt;td&gt;Apache 2.4.8+ with OpenSSL 1.0.2+&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Protocols h2 http/1.1&lt;/code&gt; (HTTP/2)&lt;/td&gt;
      &lt;td&gt;Apache 2.4.17+&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Per-virtual-host &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLProtocol&lt;/code&gt; honored with SNI&lt;/td&gt;
      &lt;td&gt;Apache 2.4.42+ with OpenSSL 1.1.1+&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Hybrid post-quantum group &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;OpenSSL 3.5+&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;step-1-get-a-certificate-and-serve-the-full-chain&quot;&gt;Step 1: Get a certificate and serve the full chain&lt;/h2&gt;

&lt;p&gt;With Let’s Encrypt and Certbot, get the certificate only and write the TLS config yourself:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;certbot certonly &lt;span class=&quot;nt&quot;&gt;--apache&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; example.com &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; www.example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Certbot 2.0 and newer create an ECDSA key by default.&lt;/p&gt;

&lt;p&gt;Point Apache at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fullchain.pem&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;SSLCertificateFile&lt;/span&gt;    /etc/letsencrypt/live/example.com/fullchain.pem
&lt;span class=&quot;nc&quot;&gt;SSLCertificateKeyFile&lt;/span&gt; /etc/letsencrypt/live/example.com/privkey.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since Apache 2.4.8, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCertificateFile&lt;/code&gt; can hold the intermediate certificates after your own certificate, and the &lt;a href=&quot;https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslcertificatefile&quot;&gt;mod_ssl documentation&lt;/a&gt; marks &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCertificateChainFile&lt;/code&gt; as obsolete. If you point &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCertificateFile&lt;/code&gt; at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cert.pem&lt;/code&gt; and drop the chain file, the intermediate is missing. Browsers often fill it in themselves, but SSL Labs reports “Chain issues: Incomplete” and caps the grade at B.&lt;/p&gt;

&lt;p&gt;If you use Certbot’s installer (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;certbot --apache&lt;/code&gt; without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;certonly&lt;/code&gt;), it adds &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Include /etc/letsencrypt/options-ssl-apache.conf&lt;/code&gt; inside your virtual host. That file sets its own protocols and ciphers, and because it sits in the virtual host, it wins over the global file from Step 2. Remove the include, but first look at what else the file sets: the current &lt;a href=&quot;https://github.com/certbot/certbot/blob/main/certbot/src/certbot/_internal/plugins/apache/tls_configs/current-options-ssl-apache.conf&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;options-ssl-apache.conf&lt;/code&gt;&lt;/a&gt; starts with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLEngine on&lt;/code&gt;. Check with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep -n SSLEngine /etc/letsencrypt/options-ssl-apache.conf&lt;/code&gt; and, if it is there, add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLEngine on&lt;/code&gt; to the virtual host itself. Without it, Apache serves plain HTTP on port 443 and reports no error.&lt;/p&gt;

&lt;h2 id=&quot;step-2-enable-the-modules-and-set-tls-globally&quot;&gt;Step 2: Enable the modules and set TLS globally&lt;/h2&gt;

&lt;p&gt;Enable the modules this guide uses:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;a2enmod ssl headers rewrite http2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a2enmod ssl&lt;/code&gt; also enables &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;socache_shmcb&lt;/code&gt; for the session cache. On Debian 13, the stock &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/apache2/mods-available/ssl.conf&lt;/code&gt; then contains these lines (comments removed):&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;SSLSessionCache&lt;/span&gt;     shmcb:${APACHE_RUN_DIR}/ssl_scache(512000)
&lt;span class=&quot;nc&quot;&gt;SSLSessionCacheTimeout&lt;/span&gt;  300
&lt;span class=&quot;nc&quot;&gt;SSLCipherSuite&lt;/span&gt; HIGH:!aNULL
&lt;span class=&quot;nc&quot;&gt;SSLProtocol&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;all&lt;/span&gt; -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
&lt;span class=&quot;nc&quot;&gt;SSLSessionTickets&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;off&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The protocols are already fine. The cipher list is wider than it needs to be. With only these defaults, the test server accepted CBC suites, plain RSA key exchange without forward secrecy, and DHE:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;-cipher &apos;ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA&apos;  -&amp;gt;  Cipher is ECDHE-ECDSA-AES128-SHA
-cipher &apos;AES256-GCM-SHA384&apos;                            -&amp;gt;  Cipher is AES256-GCM-SHA384
-cipher &apos;DHE-RSA-AES256-GCM-SHA384&apos;                    -&amp;gt;  Cipher is DHE-RSA-AES256-GCM-SHA384
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;SSL Labs marks CBC and plain RSA suites as WEAK in its cipher list, and TLSRef leaves DHE out entirely. There is no reason to keep offering any of them. Other releases may ship different defaults, so check yours with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep -v &apos;^\s*#&apos; /etc/apache2/mods-available/ssl.conf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Leave &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl.conf&lt;/code&gt; as it is and put your settings in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/apache2/conf-available/tls.conf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# TLS settings for every HTTPS virtual host (server config context)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLProtocol&lt;/span&gt;             -all +TLSv1.2 +TLSv1.3

&lt;span class=&quot;c&quot;&gt;# OpenSSL 3.5+: hybrid post-quantum group first.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# On OpenSSL 3.0-3.4, remove X25519MLKEM768 from this list.&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLOpenSSLConfCmd&lt;/span&gt;       Curves X25519MLKEM768:X25519:prime256v1:secp384r1

&lt;span class=&quot;c&quot;&gt;# TLS 1.2: ECDHE key exchange + AEAD only. TLS 1.3: the three standard suites.&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLCipherSuite&lt;/span&gt;          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
&lt;span class=&quot;nc&quot;&gt;SSLCipherSuite&lt;/span&gt;          TLSv1.3 TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
&lt;span class=&quot;nc&quot;&gt;SSLHonorCipherOrder&lt;/span&gt;     &lt;span class=&quot;ss&quot;&gt;off&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLSessionTickets&lt;/span&gt;       &lt;span class=&quot;ss&quot;&gt;off&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Enable it:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;a2enconf tls
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Debian’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apache2.conf&lt;/code&gt; reads &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mods-enabled/*.conf&lt;/code&gt; first and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conf-enabled/*.conf&lt;/code&gt; later. For these directives, the later global value replaces the earlier one, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt; wins over &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl.conf&lt;/code&gt; without any edits there. On the test server, the three weak suites above were refused once &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt; was enabled.&lt;/p&gt;

&lt;p&gt;Line by line:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLProtocol -all +TLSv1.2 +TLSv1.3&lt;/code&gt;&lt;/strong&gt; starts from nothing and allows only TLS 1.2 and 1.3. TLS 1.0 or 1.1 would cap you at B; missing TLS 1.3 caps you at A-.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLOpenSSLConfCmd Curves&lt;/code&gt;&lt;/strong&gt; passes the key exchange groups to OpenSSL. The list comes from the &lt;a href=&quot;https://data.tlsref.org/guidelines/6.0.json&quot;&gt;TLSRef guideline 6.0&lt;/a&gt;, the successor of Mozilla’s Server Side TLS guidelines, and matches what the &lt;a href=&quot;https://configurator.tlsref.org/&quot;&gt;TLSRef Configurator&lt;/a&gt; generates for Apache. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt; combines X25519 with the ML-KEM post-quantum algorithm; clients without it fall back to X25519.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCipherSuite&lt;/code&gt;&lt;/strong&gt; lists only ECDHE suites with GCM or ChaCha20-Poly1305: forward secrecy and AEAD, nothing else. TLSRef lists the oldest clients this still serves as Firefox 31, Chrome 49, Safari 9, Android 4.4.2, IE 11 on Windows 10 and Java 8u161.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCipherSuite TLSv1.3 ...&lt;/code&gt;&lt;/strong&gt; sets the TLS 1.3 suites. These three are OpenSSL’s defaults anyway; the line makes them explicit.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLHonorCipherOrder off&lt;/code&gt;&lt;/strong&gt; lets the client choose from the list. Every option is strong, and phones without AES hardware pick ChaCha20.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLSessionTickets off&lt;/code&gt;&lt;/strong&gt;. The mod_ssl documentation warns that tickets used “without restarting the web server with an appropriate frequency (e.g. daily)” compromise forward secrecy. Apache does not rotate the ticket key on its own, so TLSRef turns tickets off. Session resumption still works through the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shmcb&lt;/code&gt; session cache from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl.conf&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No DH parameters.&lt;/strong&gt; The list has no DHE suites, so you do not need to append DH parameters to the certificate file.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;step-3-the-virtual-hosts-hsts-and-the-http-redirect&quot;&gt;Step 3: The virtual hosts, HSTS and the HTTP redirect&lt;/h2&gt;

&lt;p&gt;Create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/apache2/sites-available/example.com.conf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; *:80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;nc&quot;&gt;ServerName&lt;/span&gt; example.com
    &lt;span class=&quot;nc&quot;&gt;ServerAlias&lt;/span&gt; www.example.com

    &lt;span class=&quot;nc&quot;&gt;RewriteEngine&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;On&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;RewriteCond&lt;/span&gt; %{REQUEST_URI} !^/\.well-known/acme-challenge/
    &lt;span class=&quot;nc&quot;&gt;RewriteRule&lt;/span&gt; ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [R=308,QSA,L]
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; *:443&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;nc&quot;&gt;ServerName&lt;/span&gt; example.com
    &lt;span class=&quot;nc&quot;&gt;ServerAlias&lt;/span&gt; www.example.com
    &lt;span class=&quot;nc&quot;&gt;DocumentRoot&lt;/span&gt; /var/www/example.com

    &lt;span class=&quot;nc&quot;&gt;SSLEngine&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;on&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;SSLCertificateFile&lt;/span&gt;    /etc/letsencrypt/live/example.com/fullchain.pem
    &lt;span class=&quot;nc&quot;&gt;SSLCertificateKeyFile&lt;/span&gt; /etc/letsencrypt/live/example.com/privkey.pem

    &lt;span class=&quot;nc&quot;&gt;Protocols&lt;/span&gt; h2 http/1.1

    &lt;span class=&quot;c&quot;&gt;# HSTS: 2 years. &quot;always&quot; also sends it on redirects and error pages.&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Header&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;always&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;set&lt;/span&gt; Strict-Transport-Security &quot;max-age=63072000; includeSubDomains&quot;
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then enable the site and reload:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;a2ensite example.com
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apache2ctl configtest &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl reload apache2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RewriteCond&lt;/code&gt; line keeps &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/.well-known/acme-challenge/&lt;/code&gt; on plain HTTP, so Let’s Encrypt HTTP-01 validation is answered directly on port 80 and does not depend on the redirect or the HTTPS setup. The redirect is a 308, as in the TLSRef config.&lt;/p&gt;

&lt;h3 id=&quot;why-header-always-set-matters&quot;&gt;Why &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header always set&lt;/code&gt; matters&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod_headers&lt;/code&gt; keeps two lists of response headers. The default one (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onsuccess&lt;/code&gt;) is used for normal responses; the &lt;a href=&quot;https://httpd.apache.org/docs/2.4/mod/mod_headers.html#header&quot;&gt;mod_headers documentation&lt;/a&gt; says that for a locally generated non-2xx response, “such as a redirect”, only the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;always&lt;/code&gt; list is used.&lt;/p&gt;

&lt;p&gt;On the test server, with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header set&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header always set&lt;/code&gt; and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Redirect 302 /old /&lt;/code&gt; line in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*:443&lt;/code&gt; virtual host:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;GET /      -&amp;gt;  HTTP/2 200   strict-transport-security: max-age=63072000; includeSubDomains
GET /old   -&amp;gt;  HTTP/2 302   (no HSTS header)
GET /nope  -&amp;gt;  HTTP/2 404   (no HSTS header)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header always set&lt;/code&gt;, all three responses carried the header. This matters most when your home page redirects, for example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/en/&lt;/code&gt; or to a login page: the first HTTPS response a visitor gets is that redirect, and without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;always&lt;/code&gt; it has no HSTS header.&lt;/p&gt;

&lt;p&gt;Other HSTS notes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age=63072000&lt;/code&gt;&lt;/strong&gt; is two years, the TLSRef value. SSL Labs needs at least 15768000 (six months) for the A+.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;includeSubDomains&lt;/code&gt;&lt;/strong&gt; makes every subdomain HTTPS-only in browsers that have seen the header. Leave it out until that is true for all of them.&lt;/li&gt;
  &lt;li&gt;The header belongs only in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*:443&lt;/code&gt; virtual host. Browsers ignore HSTS on plain HTTP, and &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc6797#section-7.2&quot;&gt;RFC 6797, section 7.2&lt;/a&gt; says servers must not send it there.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apache does not have nginx’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header&lt;/code&gt; inheritance problem. A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header set Cache-Control ...&lt;/code&gt; inside a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Location&amp;gt;&lt;/code&gt; block is added to the headers from the virtual host; on the test server the HSTS header stayed on those responses.&lt;/p&gt;

&lt;h2 id=&quot;step-4-watch-for-virtual-hosts-that-override-the-global-settings&quot;&gt;Step 4: Watch for virtual hosts that override the global settings&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt; sets the server-wide default. Any virtual host that has its own &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLProtocol&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCipherSuite&lt;/code&gt; or an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Include&lt;/code&gt; of a file that sets them uses those values instead. Since Apache 2.4.42 with OpenSSL 1.1.1 or newer, the &lt;a href=&quot;https://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslprotocol&quot;&gt;SSLProtocol documentation&lt;/a&gt; says each name-based virtual host’s own &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLProtocol&lt;/code&gt; is honored when the client sends SNI. Before that, the protocol of the first virtual host on the IP and port applied to all of them.&lt;/p&gt;

&lt;p&gt;Find every place that sets TLS options:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rn&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; SSLProtocol &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; SSLCipherSuite &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; SSLHonorCipherOrder &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; options-ssl-apache /etc/apache2/
apache2ctl &lt;span class=&quot;nt&quot;&gt;-S&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first command should show only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mods-available/ssl.conf&lt;/code&gt; and your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt;. The second lists which virtual host answers on which address, which helps when SSL Labs grades one IP differently from another.&lt;/p&gt;

&lt;h2 id=&quot;step-5-ocsp-stapling-and-lets-encrypt&quot;&gt;Step 5: OCSP stapling and Let’s Encrypt&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLUseStapling&lt;/code&gt; is off by default in Apache, and for Let’s Encrypt certificates it should stay off. Let’s Encrypt &lt;a href=&quot;https://letsencrypt.org/2024/12/05/ending-ocsp/&quot;&gt;ended OCSP support&lt;/a&gt;: from 7 May 2025 its certificates no longer contain an OCSP URL, and the responders were switched off on 6 August 2025. There is nothing to staple. (My 2015 post on &lt;a href=&quot;/2015/04/12/ocsp-stapling-di-nginx&quot;&gt;OCSP stapling in nginx&lt;/a&gt; predates this change.) OCSP stapling has no effect on the SSL Labs grade.&lt;/p&gt;

&lt;p&gt;For a certificate from a CA that still runs OCSP, enable it in the server config (outside any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;VirtualHost&amp;gt;&lt;/code&gt;), for example at the end of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;SSLUseStapling&lt;/span&gt;          &lt;span class=&quot;ss&quot;&gt;on&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLStaplingCache&lt;/span&gt;        &quot;shmcb:${APACHE_RUN_DIR}/ssl_stapling(32768)&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;step-6-the-configtest-trap&quot;&gt;Step 6: The configtest trap&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apache2ctl configtest&lt;/code&gt; checks the syntax, not whether OpenSSL accepts your values. On the test server, a curve name that OpenSSL does not know passed the syntax check and then stopped Apache:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ apache2ctl configtest
Syntax OK
$ apache2ctl graceful
# error log:
[ssl:emerg] AH02407: &quot;SSLOpenSSLConfCmd Curves FakeGroup999:X25519:prime256v1:secp384r1&quot; failed for example.test:443
[ssl:emerg] AH02312: Fatal error initialising mod_ssl, exiting.
[:emerg] AH00020: Configuration Failed, exiting
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A graceful reload does not protect you here. After that reload, no Apache process was left running, so plain HTTP was down too. OpenSSL older than 3.5 does not know &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt;, so that name can cause the same failure there.&lt;/p&gt;

&lt;p&gt;So check the group names against OpenSSL before you reload. On the test server (OpenSSL 3.5.7):&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;openssl list &lt;span class=&quot;nt&quot;&gt;-tls-groups&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;tr&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;:&apos;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;\n&apos;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-x&lt;/span&gt; X25519MLKEM768
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If that prints nothing, or your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl&lt;/code&gt; does not know the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-tls-groups&lt;/code&gt; option, remove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt;. Debian and Ubuntu build Apache against the system OpenSSL, so the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl&lt;/code&gt; command checks the same library; on a custom build, compare with the version in Apache’s startup log line. After any TLS change, reload and then confirm the site still answers (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl -sI https://example.com/&lt;/code&gt;) before you log out.&lt;/p&gt;

&lt;h2 id=&quot;step-7-test-locally-then-run-ssl-labs&quot;&gt;Step 7: Test locally, then run SSL Labs&lt;/h2&gt;

&lt;p&gt;Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.com&lt;/code&gt; with your host:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# TLS 1.1 must be refused. SECLEVEL=0 lets a modern client even try it.&lt;/span&gt;
openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-tls1_1&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-cipher&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;DEFAULT@SECLEVEL=0&apos;&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;alert|Cipher is&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# TLS 1.3 must work. With OpenSSL 3.5+ on both sides the group is X25519MLKEM768.&lt;/span&gt;
openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-tls1_3&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Negotiated TLS1.3 group|Cipher is&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# CBC, plain RSA and DHE suites must be refused.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;c &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA&apos;&lt;/span&gt; AES256-GCM-SHA384 DHE-RSA-AES256-GCM-SHA384&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
  &lt;/span&gt;openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &lt;span class=&quot;nt&quot;&gt;-tls1_2&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;-cipher&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$c&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;alert|Cipher is&apos;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Full chain: the server must send at least 2 certificates (yours + intermediate).&lt;/span&gt;
openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &lt;span class=&quot;nt&quot;&gt;-showcerts&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;/dev/null | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;BEGIN CERTIFICATE&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# HSTS on a normal page and on an error page, plus the HTTP redirect.&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;-sI&lt;/span&gt; https://example.com/ | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; strict-transport-security
curl &lt;span class=&quot;nt&quot;&gt;-sI&lt;/span&gt; https://example.com/does-not-exist | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;^HTTP&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; strict-transport-security
curl &lt;span class=&quot;nt&quot;&gt;-sI&lt;/span&gt; http://example.com/ | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;^HTTP&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;^location&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On the test setup, the output looked like this (condensed):&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tls1_1 :  tlsv1 alert protocol version ... Cipher is (NONE)
tls1_3 :  Negotiated TLS1.3 group: X25519MLKEM768
          New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
CBC    :  ssl/tls alert handshake failure
RSA    :  ssl/tls alert handshake failure
DHE    :  ssl/tls alert handshake failure
404    :  HTTP/2 404 + strict-transport-security: max-age=63072000; includeSubDomains
HTTP   :  HTTP/1.1 308 Permanent Redirect
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then open &lt;a href=&quot;https://www.ssllabs.com/ssltest/&quot;&gt;ssllabs.com/ssltest&lt;/a&gt;, enter your hostname, and tick “Do not show the results on the boards” if you do not want the result listed. After a config change, use “Clear cache” on the results page to force a new scan.&lt;/p&gt;

&lt;h2 id=&quot;troubleshooting-what-the-report-says-and-how-to-fix-it&quot;&gt;Troubleshooting: what the report says and how to fix it&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;What you see&lt;/th&gt;
      &lt;th&gt;Cause&lt;/th&gt;
      &lt;th&gt;Fix&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade B, “This server supports TLS 1.0 and TLS 1.1”&lt;/td&gt;
      &lt;td&gt;A virtual host or include sets its own &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLProtocol&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; from Step 4; remove the override&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;WEAK suites (CBC, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TLS_RSA_*&lt;/code&gt;) in the cipher list&lt;/td&gt;
      &lt;td&gt;Distribution default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCipherSuite&lt;/code&gt;, or an override in a virtual host&lt;/td&gt;
      &lt;td&gt;Enable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt;; check with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; from Step 4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade B, “Chain issues: Incomplete”&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLCertificateFile&lt;/code&gt; points to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cert.pem&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fullchain.pem&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade A-, “This server does not support TLS 1.3”&lt;/td&gt;
      &lt;td&gt;Apache older than 2.4.37, OpenSSL older than 1.1.1, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSLProtocol&lt;/code&gt; without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+TLSv1.3&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Upgrade; check both versions in the startup line of the error log&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade A-, HSTS missing although it is configured&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mod_headers&lt;/code&gt; not enabled, the header set in the wrong virtual host, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header set&lt;/code&gt; without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;always&lt;/code&gt; on a redirecting page&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a2enmod headers&lt;/code&gt;; put &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Header always set&lt;/code&gt; in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*:443&lt;/code&gt; virtual host&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Invalid command &apos;Header&apos;&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;RewriteEngine&apos;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Module not enabled&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a2enmod headers rewrite&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Apache stops after a reload although &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configtest&lt;/code&gt; said Syntax OK (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AH02407&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AH02312&lt;/code&gt;)&lt;/td&gt;
      &lt;td&gt;OpenSSL rejects a value, often &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt; on OpenSSL older than 3.5&lt;/td&gt;
      &lt;td&gt;Remove that group, start Apache again; see Step 6&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;A+ on one IP, A- on another&lt;/td&gt;
      &lt;td&gt;IPv6 served by another virtual host or machine&lt;/td&gt;
      &lt;td&gt;Check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apache2ctl -S&lt;/code&gt; and the AAAA record&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade does not change after you edit Apache&lt;/td&gt;
      &lt;td&gt;You are testing a CDN, not your server&lt;/td&gt;
      &lt;td&gt;See below&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Behind Cloudflare or another CDN?&lt;/strong&gt; With the proxy on, SSL Labs tests the CDN’s edge, not your Apache. The grade then depends on the CDN settings (minimum TLS version, TLS 1.3, HSTS). Keep the setup above on the origin and use Cloudflare’s “Full (strict)” mode so the connection to your server is checked too.&lt;/p&gt;

&lt;h2 id=&quot;optional-hsts-preload&quot;&gt;Optional: HSTS preload&lt;/h2&gt;

&lt;p&gt;HSTS preload puts your domain on a list built into browsers. SSL Labs does not need it for an A+. &lt;a href=&quot;https://hstspreload.org/&quot;&gt;hstspreload.org&lt;/a&gt; requires a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age&lt;/code&gt; of at least one year, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;includeSubDomains&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;preload&lt;/code&gt;, HTTPS on every subdomain, and an HTTP to HTTPS redirect on the same host. Removal takes months to reach users, so only submit a domain that will stay HTTPS-only everywhere.&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;Header&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;always&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;set&lt;/span&gt; Strict-Transport-Security &quot;max-age=63072000; includeSubDomains; preload&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-complete-config&quot;&gt;The complete config&lt;/h2&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# /etc/apache2/conf-available/tls.conf   (a2enconf tls)&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLProtocol&lt;/span&gt;             -all +TLSv1.2 +TLSv1.3
&lt;span class=&quot;nc&quot;&gt;SSLOpenSSLConfCmd&lt;/span&gt;       Curves X25519MLKEM768:X25519:prime256v1:secp384r1
&lt;span class=&quot;nc&quot;&gt;SSLCipherSuite&lt;/span&gt;          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
&lt;span class=&quot;nc&quot;&gt;SSLCipherSuite&lt;/span&gt;          TLSv1.3 TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
&lt;span class=&quot;nc&quot;&gt;SSLHonorCipherOrder&lt;/span&gt;     &lt;span class=&quot;ss&quot;&gt;off&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLSessionTickets&lt;/span&gt;       &lt;span class=&quot;ss&quot;&gt;off&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# /etc/apache2/sites-available/example.com.conf   (a2ensite example.com)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; *:80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;nc&quot;&gt;ServerName&lt;/span&gt; example.com
    &lt;span class=&quot;nc&quot;&gt;ServerAlias&lt;/span&gt; www.example.com
    &lt;span class=&quot;nc&quot;&gt;RewriteEngine&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;On&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;RewriteCond&lt;/span&gt; %{REQUEST_URI} !^/\.well-known/acme-challenge/
    &lt;span class=&quot;nc&quot;&gt;RewriteRule&lt;/span&gt; ^.*$ https://%{HTTP_HOST}%{REQUEST_URI} [R=308,QSA,L]
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt; *:443&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;    &lt;span class=&quot;nc&quot;&gt;ServerName&lt;/span&gt; example.com
    &lt;span class=&quot;nc&quot;&gt;ServerAlias&lt;/span&gt; www.example.com
    &lt;span class=&quot;nc&quot;&gt;DocumentRoot&lt;/span&gt; /var/www/example.com
    &lt;span class=&quot;nc&quot;&gt;SSLEngine&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;on&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;SSLCertificateFile&lt;/span&gt;    /etc/letsencrypt/live/example.com/fullchain.pem
    &lt;span class=&quot;nc&quot;&gt;SSLCertificateKeyFile&lt;/span&gt; /etc/letsencrypt/live/example.com/privkey.pem
    &lt;span class=&quot;nc&quot;&gt;Protocols&lt;/span&gt; h2 http/1.1
    &lt;span class=&quot;nc&quot;&gt;Header&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;always&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;set&lt;/span&gt; Strict-Transport-Security &quot;max-age=63072000; includeSubDomains&quot;
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;VirtualHost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Modules: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a2enmod ssl headers rewrite http2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To serve both ECDSA and RSA certificates, repeat the certificate pair in the same virtual host; mod_ssl picks the right one per client:&lt;/p&gt;

&lt;div class=&quot;language-apache highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# ECDSA pair, from Step 1&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLCertificateFile&lt;/span&gt;    /etc/letsencrypt/live/example.com/fullchain.pem
&lt;span class=&quot;nc&quot;&gt;SSLCertificateKeyFile&lt;/span&gt; /etc/letsencrypt/live/example.com/privkey.pem
&lt;span class=&quot;c&quot;&gt;# RSA pair&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;SSLCertificateFile&lt;/span&gt;    /etc/letsencrypt/live/example.com-rsa/fullchain.pem
&lt;span class=&quot;nc&quot;&gt;SSLCertificateKeyFile&lt;/span&gt; /etc/letsencrypt/live/example.com-rsa/privkey.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On the test server, a TLS 1.2 client that only offered &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ECDHE-RSA-AES128-GCM-SHA256&lt;/code&gt; received the 2048-bit RSA certificate, and other clients got ECDSA. With Certbot, run it again with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--key-type rsa --cert-name example.com-rsa&lt;/code&gt; for the RSA pair.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Mahyuddin Susanto is a Linux and networking sysadmin who runs his own servers and has written about Apache on this blog since 2007, starting with &lt;a href=&quot;/2007/09/27/apache-server-dengan-module-openssl&quot;&gt;Apache server dengan module OpenSSL&lt;/a&gt;. &lt;a href=&quot;/about&quot;&gt;About&lt;/a&gt; · &lt;a href=&quot;/contact&quot;&gt;Contact&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;sources&quot;&gt;Sources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Qualys SSL Labs, &lt;a href=&quot;https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide&quot;&gt;SSL Server Rating Guide&lt;/a&gt;, version 2009r, 16 May 2025&lt;/li&gt;
  &lt;li&gt;TLSRef, &lt;a href=&quot;https://data.tlsref.org/guidelines/6.0.json&quot;&gt;Server Side TLS guideline 6.0&lt;/a&gt; and &lt;a href=&quot;https://configurator.tlsref.org/&quot;&gt;TLS Configurator&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Apache HTTP Server 2.4, &lt;a href=&quot;https://httpd.apache.org/docs/2.4/mod/mod_ssl.html&quot;&gt;mod_ssl&lt;/a&gt; and &lt;a href=&quot;https://httpd.apache.org/docs/2.4/mod/mod_headers.html&quot;&gt;mod_headers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Let’s Encrypt, &lt;a href=&quot;https://letsencrypt.org/2024/12/05/ending-ocsp/&quot;&gt;Ending OCSP Support in 2025&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://hstspreload.org/&quot;&gt;HSTS Preload List Submission&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;IETF, &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc6797&quot;&gt;RFC 6797: HTTP Strict Transport Security&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Mahyuddin Susanto</name></author><category term="Linux" /><category term="apache" /><category term="tls" /><category term="ssl" /><category term="security" /><category term="hsts" /><summary type="html">To get an A+ on the Qualys SSL Labs server test with Apache httpd, you need the same five things as on any web server: TLS 1.2 and TLS 1.3 only, ECDHE key exchange with AEAD ciphers (GCM or ChaCha20-Poly1305), a certificate served with its full chain, an HSTS header with a max-age of at least six months, and the same setup on every IP address your hostname resolves to. On Apache, two details decide whether you get there: the HSTS header needs Header always set, not Header set, and a virtual host with its own SSLProtocol or SSLCipherSuite silently overrides your global settings.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.udienz.web.id/img/ssl-labs-a-plus-apache.png" /><media:content medium="image" url="https://www.udienz.web.id/img/ssl-labs-a-plus-apache.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Cara Mendapat A+ di SSL Labs dengan nginx (Panduan 2026)</title><link href="https://www.udienz.web.id/2026/11/05/ssl-labs-a-plus-nginx-id" rel="alternate" type="text/html" title="Cara Mendapat A+ di SSL Labs dengan nginx (Panduan 2026)" /><published>2026-11-05T00:00:00+00:00</published><updated>2026-11-05T00:00:00+00:00</updated><id>https://www.udienz.web.id/2026/11/05/ssl-labs-a-plus-nginx-id</id><content type="html" xml:base="https://www.udienz.web.id/2026/11/05/ssl-labs-a-plus-nginx-id">&lt;p&gt;Untuk dapat A+ di &lt;a href=&quot;https://www.ssllabs.com/ssltest/&quot;&gt;SSL Labs Server Test&lt;/a&gt; dari Qualys dengan nginx, ada lima syarat: hanya TLS 1.2 dan TLS 1.3, cipher ECDHE dengan AEAD (GCM atau ChaCha20-Poly1305), sertifikat dikirim bersama chain lengkapnya, header HSTS dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age&lt;/code&gt; minimal enam bulan, dan konfigurasi yang sama di semua alamat IP hostname tersebut. Tanpa TLS 1.3 atau tanpa HSTS, nilainya mentok di A-. Kalau TLS 1.0 atau 1.1 masih aktif, nilainya mentok di B.&lt;/p&gt;

&lt;p&gt;Tulisan ini membahas tiap syarat itu satu per satu, lengkap dengan konfigurasi yang bisa langsung dipakai. Ada juga dua perubahan yang bikin banyak tutorial lama jadi usang: Let’s Encrypt mematikan OCSP di 2025, dan SSL Labs mengubah aturan penilaiannya di Mei 2025.&lt;/p&gt;

&lt;p&gt;Konfigurasi di bawah sudah diuji di nginx 1.26.3 dengan OpenSSL 3.5.7, memakai &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx.conf&lt;/code&gt; bawaan Debian 13 (dua baris SSL-nya diberi &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt;) ditambah file-file dari tulisan ini, lalu dicek dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl s_client&lt;/code&gt; dan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read in English:&lt;/strong&gt; &lt;a href=&quot;/2026/11/05/ssl-labs-a-plus-nginx&quot;&gt;How to Get an A+ on SSL Labs with nginx&lt;/a&gt;. Pakai Apache? Lihat &lt;a href=&quot;/2026/11/05/ssl-labs-a-plus-apache-id&quot;&gt;Cara Mendapat A+ di SSL Labs dengan Apache&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/ssl-labs-a-plus-nginx-id.png&quot; alt=&quot;Tangga grade SSL Labs untuk nginx: apa yang menahan server di B atau A-, dan syarat A+&quot; /&gt;&lt;/p&gt;

&lt;details class=&quot;toc&quot;&gt;
  &lt;summary&gt;Daftar isi&lt;/summary&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#cara-ssl-labs-memberi-nilai&quot; id=&quot;markdown-toc-cara-ssl-labs-memberi-nilai&quot;&gt;Cara SSL Labs memberi nilai&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#cek-versi-nginx-dan-openssl-dulu&quot; id=&quot;markdown-toc-cek-versi-nginx-dan-openssl-dulu&quot;&gt;Cek versi nginx dan OpenSSL dulu&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#langkah-1-sertifikat-dan-full-chain&quot; id=&quot;markdown-toc-langkah-1-sertifikat-dan-full-chain&quot;&gt;Langkah 1: Sertifikat dan full chain&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#langkah-2-taruh-pengaturan-tls-di-satu-file-bersama&quot; id=&quot;markdown-toc-langkah-2-taruh-pengaturan-tls-di-satu-file-bersama&quot;&gt;Langkah 2: Taruh pengaturan TLS di satu file bersama&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#langkah-3-server-block-hsts-dan-redirect-http&quot; id=&quot;markdown-toc-langkah-3-server-block-hsts-dan-redirect-http&quot;&gt;Langkah 3: Server block, HSTS, dan redirect HTTP&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#langkah-4-ocsp-stapling-dan-lets-encrypt&quot; id=&quot;markdown-toc-langkah-4-ocsp-stapling-dan-lets-encrypt&quot;&gt;Langkah 4: OCSP stapling dan Let’s Encrypt&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#langkah-5-hindari-jebakan-add_header&quot; id=&quot;markdown-toc-langkah-5-hindari-jebakan-add_header&quot;&gt;Langkah 5: Hindari jebakan add_header&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#langkah-6-uji-di-lokal-lalu-jalankan-ssl-labs&quot; id=&quot;markdown-toc-langkah-6-uji-di-lokal-lalu-jalankan-ssl-labs&quot;&gt;Langkah 6: Uji di lokal, lalu jalankan SSL Labs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#troubleshooting-arti-pesan-di-laporan-dan-cara-memperbaikinya&quot; id=&quot;markdown-toc-troubleshooting-arti-pesan-di-laporan-dan-cara-memperbaikinya&quot;&gt;Troubleshooting: arti pesan di laporan dan cara memperbaikinya&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#opsional-hsts-preload&quot; id=&quot;markdown-toc-opsional-hsts-preload&quot;&gt;Opsional: HSTS preload&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#konfigurasi-lengkap&quot; id=&quot;markdown-toc-konfigurasi-lengkap&quot;&gt;Konfigurasi lengkap&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sumber&quot; id=&quot;markdown-toc-sumber&quot;&gt;Sumber&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/details&gt;

&lt;h2 id=&quot;cara-ssl-labs-memberi-nilai&quot;&gt;Cara SSL Labs memberi nilai&lt;/h2&gt;

&lt;p&gt;SSL Labs menilai tiga kategori: dukungan protokol (30%), key exchange (30%), dan kekuatan cipher (40%). Skor 80 ke atas berarti A. Setelah itu berlaku batas atas (cap): masalah tertentu membatasi grade setinggi apa pun skornya. A+ adalah bonus untuk server ber-grade A yang tidak punya warning.&lt;/p&gt;

&lt;p&gt;Aturan yang berlaku sekarang adalah versi 2009r dari &lt;a href=&quot;https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide&quot;&gt;SSL Server Rating Guide&lt;/a&gt;, tertanggal 16 Mei 2025. Ini batas-batas yang relevan untuk server nginx pada umumnya:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Masalah&lt;/th&gt;
      &lt;th&gt;Grade maksimal&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;SSLv2, SSLv3 sebagai protokol terbaik, cipher export, bug sekelas Heartbleed&lt;/td&gt;
      &lt;td&gt;F&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Tidak mendukung TLS 1.2&lt;/td&gt;
      &lt;td&gt;C&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;TLS 1.0 atau TLS 1.1 aktif&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Tanpa forward secrecy (tanpa ECDHE/DHE)&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Tanpa cipher AEAD (GCM atau ChaCha20-Poly1305)&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;RC4 aktif&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Chain sertifikat tidak lengkap&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Key atau parameter DH di bawah 2048 bit&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Tidak mendukung TLS 1.3&lt;/td&gt;
      &lt;td&gt;A-&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;HSTS tidak ada atau tidak valid&lt;/td&gt;
      &lt;td&gt;A-&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Untuk A+, panduan itu mensyaratkan konfigurasi tanpa warning dan HSTS dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age&lt;/code&gt; minimal enam bulan (15768000 detik).&lt;/p&gt;

&lt;p&gt;Ada dua perubahan di 2025: sekadar dapat A sekarang butuh TLS 1.3 sekaligus header HSTS yang valid, dan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TLS_FALLBACK_SCSV&lt;/code&gt; tidak dihitung lagi. Kalau ada artikel lama yang menyuruh mengurus fallback SCSV, bagian itu bisa dilewati.&lt;/p&gt;

&lt;p&gt;Nilai 100 di semua kategori tidak diperlukan. Sertifikat ECDSA P-256 atau RSA 2048 dapat 90 di key exchange, dan selama AES-128 masih ditawarkan, kekuatan cipher juga 90. Keduanya tetap dapat A+. Pindah ke RSA 4096 cuma bikin handshake lebih lambat.&lt;/p&gt;

&lt;h2 id=&quot;cek-versi-nginx-dan-openssl-dulu&quot;&gt;Cek versi nginx dan OpenSSL dulu&lt;/h2&gt;

&lt;p&gt;Beberapa directive bergantung pada versi yang terpasang:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nginx &lt;span class=&quot;nt&quot;&gt;-V&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-3&lt;/span&gt;
openssl version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Fitur&lt;/th&gt;
      &lt;th&gt;Butuh&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;TLS 1.3 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TLSv1.3&lt;/code&gt; di &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_protocols&lt;/code&gt;)&lt;/td&gt;
      &lt;td&gt;OpenSSL 1.1.1+; jadi default sejak nginx 1.23.4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http2 on;&lt;/code&gt; sebagai directive terpisah&lt;/td&gt;
      &lt;td&gt;nginx 1.25.1+ (versi lama: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listen 443 ssl http2;&lt;/code&gt;)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Rotasi otomatis key session ticket&lt;/td&gt;
      &lt;td&gt;nginx 1.23.2+ dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_session_cache&lt;/code&gt; shared&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grup hybrid post-quantum &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;OpenSSL 3.5+&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header_inherit merge;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;nginx 1.29.3+&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Yang penting di output &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx -V&lt;/code&gt; adalah baris &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;built with OpenSSL ...&lt;/code&gt;. Itu library yang benar-benar dipakai nginx, dan bisa berbeda dengan perintah &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl&lt;/code&gt; di server yang sama.&lt;/p&gt;

&lt;h2 id=&quot;langkah-1-sertifikat-dan-full-chain&quot;&gt;Langkah 1: Sertifikat dan full chain&lt;/h2&gt;

&lt;p&gt;Sertifikat apa pun yang dipercaya publik bisa dipakai. Dengan Let’s Encrypt dan Certbot, ambil sertifikatnya saja, lalu tulis konfigurasi TLS sendiri:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;certbot certonly &lt;span class=&quot;nt&quot;&gt;--nginx&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; example.com &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; www.example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Certbot versi baru sudah memakai key ECDSA secara default, dan itu yang dibutuhkan. Arahkan nginx ke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fullchain.pem&lt;/code&gt;, bukan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cert.pem&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;ssl_certificate&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_certificate_key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cert.pem&lt;/code&gt; hanya berisi sertifikat leaf. Browser sering melengkapi intermediate yang hilang sendiri, jadi situs terlihat normal, tapi SSL Labs akan menulis “Chain issues: Incomplete” dan membatasi grade di B. &lt;a href=&quot;https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate&quot;&gt;Dokumentasi nginx&lt;/a&gt; juga bilang begitu: sertifikat server ditaruh paling atas di file, diikuti sertifikat intermediate.&lt;/p&gt;

&lt;p&gt;Kalau memakai installer Certbot (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;certbot --nginx&lt;/code&gt; tanpa &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;certonly&lt;/code&gt;), ia menambahkan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;include /etc/letsencrypt/options-ssl-nginx.conf;&lt;/code&gt; ke server block. File itu juga mengatur protokol dan cipher. Hapus baris include tersebut supaya hanya pengaturan dari tulisan ini yang berlaku.&lt;/p&gt;

&lt;h2 id=&quot;langkah-2-taruh-pengaturan-tls-di-satu-file-bersama&quot;&gt;Langkah 2: Taruh pengaturan TLS di satu file bersama&lt;/h2&gt;

&lt;p&gt;Debian dan Ubuntu memuat semua file di &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nginx/conf.d/&lt;/code&gt; di dalam blok &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;, jadi satu file di sana berlaku untuk semua situs HTTPS.&lt;/p&gt;

&lt;p&gt;Pertama, bereskan dulu baris SSL yang sudah dipasang paket di &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nginx/nginx.conf&lt;/code&gt;. File bawaan Debian 13 punya blok ini di dalam &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http { }&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;##&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# SSL Settings&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;##&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;ssl_protocols&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TLSv1.2&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TLSv1.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Dropping SSLv3 (POODLE), TLS 1.0, 1.1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Don&apos;t force server cipher order.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;File di &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conf.d/&lt;/code&gt; masuk ke blok &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt; yang sama, jadi baris-baris ini akan bentrok. nginx menolak &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_prefer_server_ciphers&lt;/code&gt; kedua di level yang sama:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nginx: [emerg] &quot;ssl_prefer_server_ciphers&quot; directive is duplicate in /etc/nginx/conf.d/tls.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_protocols&lt;/code&gt; kedua juga tidak menimpa yang pertama. nginx menggabungkan kedua daftar dan hanya memberi peringatan seperti &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[warn] duplicate value &quot;TLSv1.2&quot;&lt;/code&gt;, bukan error. Beri tanda &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt; pada kedua baris itu (isinya bisa berbeda di rilis lain), lalu pastikan tidak ada file lain yang mengaturnya:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rn&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; ssl_protocols &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; ssl_prefer_server_ciphers &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; ssl_ciphers /etc/nginx/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sekarang buat &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nginx/conf.d/tls.conf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Pengaturan TLS untuk semua server block (konteks http)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_protocols&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TLSv1.2&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TLSv1.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# OpenSSL 3.5+: grup hybrid post-quantum di depan.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Di OpenSSL 3.0-3.4, hapus X25519MLKEM768 dari daftar ini.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_ecdh_curve&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X25519MLKEM768:X25519:prime256v1:secp384r1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Cipher TLS 1.2: hanya key exchange ECDHE + AEAD.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Suite TLS 1.3 diatur OpenSSL dan semuanya AEAD.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_ciphers&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;ssl_session_timeout&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_session_cache&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;shared:TLS:10m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# sekitar 40000 sesi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Penjelasan per baris:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_protocols TLSv1.2 TLSv1.3&lt;/code&gt;&lt;/strong&gt; mematikan TLS 1.0 dan 1.1 (penyebab cap B) dan mengaktifkan TLS 1.3 (tanpanya grade mentok di A-). Ini sudah default sejak nginx 1.23.4, tapi ditulis eksplisit supaya jelas. Baris ini tidak menimpa &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_protocols&lt;/code&gt; lain di blok yang sama, karena itu baris lama tadi harus dimatikan.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_ecdh_curve&lt;/code&gt;&lt;/strong&gt; menentukan grup key exchange. Daftarnya diambil dari &lt;a href=&quot;https://data.tlsref.org/guidelines/6.0.json&quot;&gt;TLSRef guideline 6.0&lt;/a&gt;, penerus Server Side TLS guidelines dari Mozilla. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt; menggabungkan X25519 klasik dengan algoritma post-quantum ML-KEM. Klien yang belum mendukungnya otomatis turun ke X25519.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_ciphers&lt;/code&gt;&lt;/strong&gt; hanya berisi suite ECDHE, yang memberi forward secrecy, dan hanya GCM atau ChaCha20-Poly1305, yang termasuk AEAD. Tidak ada CBC, tidak ada key exchange RSA, tidak ada 3DES. Menurut TLSRef, klien tertua yang masih bisa tersambung dengan profil ini adalah Firefox 31, Chrome 49, Safari 9, Android 4.4.2, IE 11 di Windows 10, dan Java 8u161. Daftar ini sekaligus menggantikan daftar cipher di tulisan saya tahun 2015, &lt;a href=&quot;/2015/04/12/ssl_cipher-di-nginx&quot;&gt;ssl_cipher di nginx&lt;/a&gt;, yang sudah usang.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_prefer_server_ciphers off&lt;/code&gt;&lt;/strong&gt; membiarkan klien yang memilih. Karena semua pilihan di daftar sudah kuat, klien paling tahu mana yang cocok: ponsel tanpa akselerasi AES di hardware akan memilih ChaCha20.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tanpa &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_dhparam&lt;/code&gt;.&lt;/strong&gt; Daftar cipher tidak berisi suite DHE, jadi file parameter DH tidak diperlukan. Risiko lama “parameter DH di bawah 2048 bit” ikut hilang.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Session ticket&lt;/strong&gt; dibiarkan default (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on&lt;/code&gt;). Sejak nginx 1.23.2, key ticket dirotasi otomatis selama &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_session_cache&lt;/code&gt; memakai shared memory, seperti di file di atas. Karena itu TLSRef hanya menambahkan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_session_tickets off;&lt;/code&gt; untuk versi yang lebih lama.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mozilla SSL Configuration Generator sekarang dialihkan ke &lt;a href=&quot;https://configurator.tlsref.org/&quot;&gt;TLSRef Configurator&lt;/a&gt;. File di atas sama dengan profil “Intermediate” di sana, pilihan yang tepat untuk website publik. Profil “Modern” (hanya TLS 1.3) juga dapat A+, tapi memutus klien lama seperti Android 4.4 dan IE 11.&lt;/p&gt;

&lt;h2 id=&quot;langkah-3-server-block-hsts-dan-redirect-http&quot;&gt;Langkah 3: Server block, HSTS, dan redirect HTTP&lt;/h2&gt;

&lt;p&gt;Sekarang konfigurasi situsnya, misalnya &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nginx/sites-available/example.com&lt;/code&gt; yang di-link ke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sites-enabled/&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Port 80: semua dialihkan ke HTTPS&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[::]:80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example.com&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;www.example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;308&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$host$request_uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;443&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[::]:443&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;http2&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;# nginx &amp;lt; 1.25.1: &quot;listen 443 ssl http2;&quot;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example.com&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;www.example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;ssl_certificate&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;ssl_certificate_key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# HSTS: 2 tahun. &quot;always&quot; juga mengirimnya di respons 3xx/4xx/5xx.&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Strict-Transport-Security&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;max-age=63072000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;includeSubDomains&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/var/www/example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;index.html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Catatan soal baris HSTS:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age=63072000&lt;/code&gt;&lt;/strong&gt; sama dengan dua tahun, nilai dari TLSRef. SSL Labs butuh minimal 15768000 (enam bulan) untuk A+. Nilai yang lebih pendek atau salah ketik membuat grade turun ke A-.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;always&lt;/code&gt;&lt;/strong&gt; penting. Tanpa itu, nginx hanya menambahkan header di respons 200, 201, 204, 206, 301, 302, 303, 304, 307, dan 308. Dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;always&lt;/code&gt;, halaman error juga membawa header ini.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;includeSubDomains&lt;/code&gt;&lt;/strong&gt; memberi tahu browser bahwa semua subdomain juga wajib HTTPS. Jangan dipasang sebelum yakin itu benar. Kalau &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;intranet.example.com&lt;/code&gt; masih HTTP biasa, browser yang pernah menerima header ini akan menolak membukanya.&lt;/li&gt;
  &lt;li&gt;Header hanya dipasang di server HTTPS. Browser mengabaikan HSTS yang dikirim lewat HTTP biasa, dan spesifikasi HSTS (&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc6797#section-7.2&quot;&gt;RFC 6797 bagian 7.2&lt;/a&gt;) melarang server mengirimnya di sana.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dua baris &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listen&lt;/code&gt; di tiap blok memang disengaja. Kalau domain punya record AAAA tapi nginx hanya listen di IPv4, SSL Labs akan menguji alamat IPv6 dan mendapat jawaban berbeda. Penjelasannya ada di tabel troubleshooting.&lt;/p&gt;

&lt;h2 id=&quot;langkah-4-ocsp-stapling-dan-lets-encrypt&quot;&gt;Langkah 4: OCSP stapling dan Let’s Encrypt&lt;/h2&gt;

&lt;p&gt;Banyak panduan A+ masih menyuruh menambahkan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_stapling on;&lt;/code&gt;, termasuk tulisan saya sendiri tahun 2015, &lt;a href=&quot;/2015/04/12/ocsp-stapling-di-nginx&quot;&gt;OCSP Stapling di nginx&lt;/a&gt;. Untuk sertifikat Let’s Encrypt, baris itu sebaiknya dibuang.&lt;/p&gt;

&lt;p&gt;Let’s Encrypt &lt;a href=&quot;https://letsencrypt.org/2024/12/05/ending-ocsp/&quot;&gt;menghentikan dukungan OCSP&lt;/a&gt;: sejak 7 Mei 2025 sertifikatnya tidak lagi memuat URL OCSP, dan responder OCSP dimatikan pada 6 Agustus 2025. Pengecekan revokasi sekarang lewat CRL. Dengan stapling aktif dan sertifikat Let’s Encrypt yang baru, nginx menulis peringatan seperti ini setiap kali reload:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[warn] &quot;ssl_stapling&quot; ignored, no OCSP responder URL in the certificate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Situs tetap jalan, tapi log jadi kotor. Hapus &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_stapling&lt;/code&gt; dan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_stapling_verify&lt;/code&gt;. OCSP stapling tidak memengaruhi grade SSL Labs.&lt;/p&gt;

&lt;p&gt;Kalau sertifikat berasal dari CA yang masih menjalankan OCSP, stapling tetap berguna. Yang dibutuhkan adalah resolver dan chain penerbit:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;ssl_stapling&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_stapling_verify&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_trusted_certificate&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/ssl/certs/ca-chain.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# root + intermediate&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;resolver&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;127&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.0.0.53&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;valid=300s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# contoh: systemd-resolved; ganti dengan resolver server Anda&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;langkah-5-hindari-jebakan-add_header&quot;&gt;Langkah 5: Hindari jebakan add_header&lt;/h2&gt;

&lt;p&gt;Di nginx, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header&lt;/code&gt; hanya diwarisi dari blok luar kalau blok saat ini tidak punya &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header&lt;/code&gt; sendiri. Begitu satu header ditambahkan di sebuah &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;location&lt;/code&gt;, semua header dari blok &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server&lt;/code&gt; hilang di location itu, termasuk HSTS. Kalau location itu &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;, grade turun ke A-. Kalau di path lain, laporan tetap A+ padahal sebagian situs jalan tanpa header itu.&lt;/p&gt;

&lt;p&gt;Ini hasil uji di server tes (port 8443) dengan konfigurasi di atas ditambah satu location:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/assets/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Cache-Control&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;public,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;max-age=3600&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ curl -sk -D- -o /dev/null https://127.0.0.1:8443/ | grep -i strict
strict-transport-security: max-age=63072000; includeSubDomains

$ curl -sk -D- -o /dev/null https://127.0.0.1:8443/assets/x | grep -i -e strict -e cache
cache-control: public, max-age=3600
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Respons kedua tidak punya HSTS.&lt;/p&gt;

&lt;p&gt;Ada tiga cara memperbaikinya, urut dari yang paling disarankan:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;nginx 1.29.3 ke atas:&lt;/strong&gt; pasang &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header_inherit merge;&lt;/code&gt; di blok &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;. Header dari level luar akan ditambahkan ke header yang diset di blok dalam (&lt;a href=&quot;https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header_inherit&quot;&gt;dokumentasi&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;nginx lama:&lt;/strong&gt; pindahkan header keamanan ke snippet, lalu include di setiap tempat yang memakai &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header&lt;/code&gt; (contoh di bawah).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Kalau hanya untuk cache:&lt;/strong&gt; pakai &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expires 1h;&lt;/code&gt;, bukan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header Cache-Control&lt;/code&gt;. Directive ini mengirim &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cache-Control&lt;/code&gt; dan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Expires&lt;/code&gt; sendiri, dan berbeda dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header&lt;/code&gt;, tidak memutus header warisan dari blok &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Cara snippet kira-kira seperti ini:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# /etc/nginx/snippets/security-headers.conf&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Strict-Transport-Security&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;max-age=63072000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;includeSubDomains&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/assets/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;snippets/security-headers&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.conf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Cache-Control&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;public,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;max-age=3600&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dan hasil &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;location /assets/ { expires 1h; }&lt;/code&gt; di server tes yang sama:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ curl -sk -D- -o /dev/null https://127.0.0.1:8443/assets/x.css
HTTP/2 200
expires: Thu, 05 Nov 2026 01:41:51 GMT
cache-control: max-age=3600
strict-transport-security: max-age=63072000; includeSubDomains
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Aturan pewarisan yang sama berlaku untuk blok &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; dan location bertingkat.&lt;/p&gt;

&lt;h2 id=&quot;langkah-6-uji-di-lokal-lalu-jalankan-ssl-labs&quot;&gt;Langkah 6: Uji di lokal, lalu jalankan SSL Labs&lt;/h2&gt;

&lt;p&gt;Cek sintaks lalu reload:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nginx &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Sebelum ke SSL Labs, cek poin-poin penting dari terminal sendiri. Ganti &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.com&lt;/code&gt; dengan host Anda:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# TLS 1.1 harus ditolak. SECLEVEL=0 supaya klien modern mau mencobanya.&lt;/span&gt;
openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-tls1_1&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-cipher&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;DEFAULT@SECLEVEL=0&apos;&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;alert|Cipher is&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# TLS 1.3 harus jalan. Dengan OpenSSL 3.5+ di kedua sisi, grupnya X25519MLKEM768.&lt;/span&gt;
openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-tls1_3&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Negotiated TLS1.3 group|Cipher is&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Suite CBC harus ditolak (berlaku untuk sertifikat ECDSA maupun RSA).&lt;/span&gt;
openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &lt;span class=&quot;nt&quot;&gt;-tls1_2&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-cipher&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA&apos;&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;alert|Cipher is&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Full chain: harus ada baris &quot;depth=1&quot; (intermediate yang dikirim server).&lt;/span&gt;
openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &amp;lt;/dev/null 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;depth

&lt;span class=&quot;c&quot;&gt;# Header HSTS dan redirect.&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;-sI&lt;/span&gt; https://example.com/ | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; strict-transport-security
curl &lt;span class=&quot;nt&quot;&gt;-sI&lt;/span&gt; http://example.com/  | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;^HTTP&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;^location&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Di server tes, hasilnya seperti ini (diringkas):&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tls1_1 :  tlsv1 alert protocol version ... Cipher is (NONE)
tls1_3 :  Negotiated TLS1.3 group: X25519MLKEM768
          New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
CBC    :  ssl/tls alert handshake failure ... Cipher is (NONE)
HSTS   :  strict-transport-security: max-age=63072000; includeSubDomains
HTTP   :  HTTP/1.1 308 Permanent Redirect
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Kalau semuanya sudah sesuai, buka &lt;a href=&quot;https://www.ssllabs.com/ssltest/&quot;&gt;ssllabs.com/ssltest&lt;/a&gt;, masukkan hostname, dan centang “Do not show the results on the boards” kalau tidak ingin hasilnya tampil di daftar publik. SSL Labs menyimpan hasil scan untuk beberapa waktu. Setelah mengubah konfigurasi, klik tautan “Clear cache” di halaman hasil supaya scan diulang. Satu scan penuh butuh beberapa menit, lebih lama kalau hostname punya beberapa alamat IP.&lt;/p&gt;

&lt;h2 id=&quot;troubleshooting-arti-pesan-di-laporan-dan-cara-memperbaikinya&quot;&gt;Troubleshooting: arti pesan di laporan dan cara memperbaikinya&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Yang muncul&lt;/th&gt;
      &lt;th&gt;Penyebab&lt;/th&gt;
      &lt;th&gt;Perbaikan&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade B, “This server supports TLS 1.0 and TLS 1.1”&lt;/td&gt;
      &lt;td&gt;Ada baris &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_protocols&lt;/code&gt; lama, sering di &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx.conf&lt;/code&gt; atau include dari Certbot&lt;/td&gt;
      &lt;td&gt;Jalankan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; dari Langkah 2 dan sisakan hanya &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx -t&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;ssl_prefer_server_ciphers&quot; directive is duplicate&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx.conf&lt;/code&gt; bawaan masih mengaturnya di blok &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt; yang sama&lt;/td&gt;
      &lt;td&gt;Beri tanda &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt; di &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx.conf&lt;/code&gt; (Langkah 2)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade B, “Chain issues: Incomplete”&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_certificate&lt;/code&gt; mengarah ke &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cert.pem&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Pakai &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fullchain.pem&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade B, warning cipher soal forward secrecy atau CBC&lt;/td&gt;
      &lt;td&gt;Daftar &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_ciphers&lt;/code&gt; lama&lt;/td&gt;
      &lt;td&gt;Pakai daftar dari Langkah 2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade A-, “This server does not support TLS 1.3”&lt;/td&gt;
      &lt;td&gt;OpenSSL lebih lama dari 1.1.1, atau &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_protocols&lt;/code&gt; tanpa &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TLSv1.3&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Upgrade OS atau build nginx; cek &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx -V&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade A-, warning HSTS atau “HSTS not set”&lt;/td&gt;
      &lt;td&gt;Header tidak ada di halaman yang diuji, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age&lt;/code&gt; terlalu pendek, atau kena jebakan add_header&lt;/td&gt;
      &lt;td&gt;Cek dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl -sI&lt;/code&gt;; lihat Langkah 5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;A+ di satu IP, A- di IP lain&lt;/td&gt;
      &lt;td&gt;IPv6 dilayani server block lain atau mesin lain&lt;/td&gt;
      &lt;td&gt;Tambahkan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listen [::]:443 ssl;&lt;/code&gt; di semua blok, atau perbaiki record AAAA&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade tidak berubah walau nginx sudah diubah&lt;/td&gt;
      &lt;td&gt;Yang diuji CDN, bukan server Anda&lt;/td&gt;
      &lt;td&gt;Lihat di bawah&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx -t&lt;/code&gt; menulis &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSL_CTX_set1_curves_list(...) failed&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;OpenSSL di balik nginx tidak mengenal salah satu grup di &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_ecdh_curve&lt;/code&gt;, biasanya &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt; di OpenSSL sebelum 3.5&lt;/td&gt;
      &lt;td&gt;Hapus grup itu dari daftar&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Pakai Cloudflare atau CDN lain?&lt;/strong&gt; Kalau proxy Cloudflare (awan oranye) aktif, SSL Labs menguji edge Cloudflare, bukan nginx Anda. Grade-nya bergantung pada pengaturan di Cloudflare: versi TLS minimum, TLS 1.3, dan HSTS di menu SSL/TLS &amp;gt; Edge Certificates. Konfigurasi nginx tetap penting untuk koneksi antara Cloudflare dan server origin, jadi pakai mode “Full (strict)” dan tetap pasang konfigurasi di atas di origin. (Blog ini juga ada di belakang Cloudflare; ceritanya ada di &lt;a href=&quot;/2014/11/10/migrasi-ke-cloudflare&quot;&gt;Migrasi ke Cloudflare&lt;/a&gt;.)&lt;/p&gt;

&lt;h2 id=&quot;opsional-hsts-preload&quot;&gt;Opsional: HSTS preload&lt;/h2&gt;

&lt;p&gt;Dengan HSTS preload, domain Anda masuk ke daftar HTTPS-only yang ditanam di dalam browser, jadi kunjungan pertama pun tidak pernah lewat HTTP. SSL Labs tidak mensyaratkannya untuk A+. Syarat di &lt;a href=&quot;https://hstspreload.org/&quot;&gt;hstspreload.org&lt;/a&gt; lebih ketat daripada syarat A+:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age&lt;/code&gt; minimal 31536000 (satu tahun), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;includeSubDomains&lt;/code&gt;, dan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;preload&lt;/code&gt; di header&lt;/li&gt;
  &lt;li&gt;semua subdomain dilayani lewat HTTPS, termasuk subdomain internal&lt;/li&gt;
  &lt;li&gt;HTTP dialihkan ke HTTPS di host yang sama terlebih dulu&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Strict-Transport-Security&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;max-age=63072000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;includeSubDomains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;preload&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Keluar dari daftar itu butuh waktu berbulan-bulan sampai ke pengguna lewat update browser, dan browser lain belum tentu ikut menghapus. Daftarkan hanya domain yang pasti tetap HTTPS-only di semua subdomain.&lt;/p&gt;

&lt;h2 id=&quot;konfigurasi-lengkap&quot;&gt;Konfigurasi lengkap&lt;/h2&gt;

&lt;p&gt;Sebagai rujukan, ini dua file yang dipakai saat pengujian di atas (sesuaikan path dan nama). Ditambah dua baris yang diberi &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt; di &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx.conf&lt;/code&gt; pada Langkah 2, itulah seluruh perubahannya:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# /etc/nginx/conf.d/tls.conf&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_protocols&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TLSv1.2&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TLSv1.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_ecdh_curve&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X25519MLKEM768:X25519:prime256v1:secp384r1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_ciphers&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_session_timeout&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_session_cache&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;shared:TLS:10m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# add_header_inherit merge;   # nginx 1.29.3+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# /etc/nginx/sites-available/example.com&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[::]:80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example.com&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;www.example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;308&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$host$request_uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;443&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[::]:443&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;http2&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example.com&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;www.example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;ssl_certificate&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;ssl_certificate_key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Strict-Transport-Security&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;max-age=63072000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;includeSubDomains&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/var/www/example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;index.html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Kalau perlu melayani klien ECDSA dan RSA sekaligus, nginx bisa memuat dua sertifikat di server block yang sama dan memilih yang cocok untuk tiap klien:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;ssl_certificate&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;# ECDSA, dari Langkah 1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_certificate_key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_certificate&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com-rsa/fullchain.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_certificate_key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com-rsa/privkey.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Di server tes, klien TLS 1.2 yang hanya menawarkan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ECDHE-RSA-AES128-GCM-SHA256&lt;/code&gt; menerima sertifikat RSA 2048 bit, sementara klien lain mendapat ECDSA. Dengan Certbot, jalankan sekali lagi dengan &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--key-type rsa --cert-name example.com-rsa&lt;/code&gt; untuk mendapat pasangan RSA.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Mahyuddin Susanto adalah sysadmin Linux dan jaringan yang mengelola server sendiri dan menulis soal nginx di blog ini sejak 2009, dimulai dari &lt;a href=&quot;/2009/05/09/nginx-dari-nol&quot;&gt;nginx, dari nol&lt;/a&gt;. &lt;a href=&quot;/about&quot;&gt;Tentang penulis&lt;/a&gt; · &lt;a href=&quot;/contact&quot;&gt;Kontak&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;sumber&quot;&gt;Sumber&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Qualys SSL Labs, &lt;a href=&quot;https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide&quot;&gt;SSL Server Rating Guide&lt;/a&gt;, versi 2009r, 16 Mei 2025&lt;/li&gt;
  &lt;li&gt;TLSRef, &lt;a href=&quot;https://data.tlsref.org/guidelines/6.0.json&quot;&gt;Server Side TLS guideline 6.0&lt;/a&gt; dan &lt;a href=&quot;https://configurator.tlsref.org/&quot;&gt;TLS Configurator&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;nginx, &lt;a href=&quot;https://nginx.org/en/docs/http/ngx_http_ssl_module.html&quot;&gt;ngx_http_ssl_module&lt;/a&gt;, &lt;a href=&quot;https://nginx.org/en/docs/http/ngx_http_headers_module.html&quot;&gt;ngx_http_headers_module&lt;/a&gt;, dan &lt;a href=&quot;https://nginx.org/en/CHANGES&quot;&gt;CHANGES&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Let’s Encrypt, &lt;a href=&quot;https://letsencrypt.org/2024/12/05/ending-ocsp/&quot;&gt;Ending OCSP Support in 2025&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://hstspreload.org/&quot;&gt;HSTS Preload List Submission&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;IETF, &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc6797&quot;&gt;RFC 6797: HTTP Strict Transport Security&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Mahyuddin Susanto</name></author><category term="Linux" /><category term="nginx" /><category term="tls" /><category term="ssl" /><category term="security" /><category term="hsts" /><summary type="html">Untuk dapat A+ di SSL Labs Server Test dari Qualys dengan nginx, ada lima syarat: hanya TLS 1.2 dan TLS 1.3, cipher ECDHE dengan AEAD (GCM atau ChaCha20-Poly1305), sertifikat dikirim bersama chain lengkapnya, header HSTS dengan max-age minimal enam bulan, dan konfigurasi yang sama di semua alamat IP hostname tersebut. Tanpa TLS 1.3 atau tanpa HSTS, nilainya mentok di A-. Kalau TLS 1.0 atau 1.1 masih aktif, nilainya mentok di B.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.udienz.web.id/img/ssl-labs-a-plus-nginx-id.png" /><media:content medium="image" url="https://www.udienz.web.id/img/ssl-labs-a-plus-nginx-id.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">How to Get an A+ on SSL Labs with nginx (2026 Guide)</title><link href="https://www.udienz.web.id/2026/11/05/ssl-labs-a-plus-nginx" rel="alternate" type="text/html" title="How to Get an A+ on SSL Labs with nginx (2026 Guide)" /><published>2026-11-05T00:00:00+00:00</published><updated>2026-11-05T00:00:00+00:00</updated><id>https://www.udienz.web.id/2026/11/05/ssl-labs-a-plus-nginx</id><content type="html" xml:base="https://www.udienz.web.id/2026/11/05/ssl-labs-a-plus-nginx">&lt;p&gt;To get an A+ on the &lt;a href=&quot;https://www.ssllabs.com/ssltest/&quot;&gt;Qualys SSL Labs server test&lt;/a&gt; with nginx, you need five things: TLS 1.2 and TLS 1.3 only, ECDHE key exchange with AEAD ciphers (GCM or ChaCha20-Poly1305), a certificate served with its full chain, an HSTS header with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age&lt;/code&gt; of at least six months, and the same setup on every IP address your hostname resolves to. Miss TLS 1.3 or HSTS and you land on A-. Leave TLS 1.0 or 1.1 on and you are stuck at B.&lt;/p&gt;

&lt;p&gt;This guide walks through each piece, gives you a config you can paste, and covers the two changes that break older tutorials: Let’s Encrypt shutting down OCSP in 2025, and the grading update SSL Labs shipped in May 2025.&lt;/p&gt;

&lt;p&gt;The configuration below was tested on nginx 1.26.3 with OpenSSL 3.5.7, using the stock Debian 13 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx.conf&lt;/code&gt; with its two SSL lines commented out and the files from this guide added, and checked with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl s_client&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Baca dalam Bahasa Indonesia:&lt;/strong&gt; &lt;a href=&quot;/2026/11/05/ssl-labs-a-plus-nginx-id&quot;&gt;Cara Mendapat A+ di SSL Labs dengan nginx&lt;/a&gt;. Running Apache? See &lt;a href=&quot;/2026/11/05/ssl-labs-a-plus-apache&quot;&gt;How to Get an A+ on SSL Labs with Apache httpd&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/ssl-labs-a-plus-nginx.png&quot; alt=&quot;SSL Labs grade ladder for nginx: what caps a server at B or A-, and what an A+ needs&quot; /&gt;&lt;/p&gt;

&lt;details class=&quot;toc&quot;&gt;
  &lt;summary&gt;Contents&lt;/summary&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#how-ssl-labs-grades-your-server&quot; id=&quot;markdown-toc-how-ssl-labs-grades-your-server&quot;&gt;How SSL Labs grades your server&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#check-your-nginx-and-openssl-versions-first&quot; id=&quot;markdown-toc-check-your-nginx-and-openssl-versions-first&quot;&gt;Check your nginx and OpenSSL versions first&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#step-1-get-a-certificate-and-serve-the-full-chain&quot; id=&quot;markdown-toc-step-1-get-a-certificate-and-serve-the-full-chain&quot;&gt;Step 1: Get a certificate and serve the full chain&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#step-2-put-the-tls-settings-in-one-shared-file&quot; id=&quot;markdown-toc-step-2-put-the-tls-settings-in-one-shared-file&quot;&gt;Step 2: Put the TLS settings in one shared file&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#step-3-the-server-blocks-hsts-and-the-http-redirect&quot; id=&quot;markdown-toc-step-3-the-server-blocks-hsts-and-the-http-redirect&quot;&gt;Step 3: The server blocks, HSTS and the HTTP redirect&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#step-4-ocsp-stapling-and-lets-encrypt&quot; id=&quot;markdown-toc-step-4-ocsp-stapling-and-lets-encrypt&quot;&gt;Step 4: OCSP stapling and Let’s Encrypt&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#step-5-avoid-the-add_header-trap&quot; id=&quot;markdown-toc-step-5-avoid-the-add_header-trap&quot;&gt;Step 5: Avoid the add_header trap&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#step-6-test-locally-then-run-ssl-labs&quot; id=&quot;markdown-toc-step-6-test-locally-then-run-ssl-labs&quot;&gt;Step 6: Test locally, then run SSL Labs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#troubleshooting-what-the-report-says-and-how-to-fix-it&quot; id=&quot;markdown-toc-troubleshooting-what-the-report-says-and-how-to-fix-it&quot;&gt;Troubleshooting: what the report says and how to fix it&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#optional-hsts-preload&quot; id=&quot;markdown-toc-optional-hsts-preload&quot;&gt;Optional: HSTS preload&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#the-complete-config&quot; id=&quot;markdown-toc-the-complete-config&quot;&gt;The complete config&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sources&quot; id=&quot;markdown-toc-sources&quot;&gt;Sources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/details&gt;

&lt;h2 id=&quot;how-ssl-labs-grades-your-server&quot;&gt;How SSL Labs grades your server&lt;/h2&gt;

&lt;p&gt;SSL Labs scores three categories: protocol support (30%), key exchange (30%) and cipher strength (40%). A score of 80 or more is an A. Then it applies caps: specific problems limit the grade no matter how high the score is. The A+ is a bonus on top of an A with no warnings.&lt;/p&gt;

&lt;p&gt;The current rules are version 2009r of the &lt;a href=&quot;https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide&quot;&gt;SSL Server Rating Guide&lt;/a&gt;, dated 16 May 2025. These are the caps that matter for a typical nginx server:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Problem&lt;/th&gt;
      &lt;th&gt;Grade limit&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;SSLv2, SSLv3 as the best protocol, export ciphers, Heartbleed-class bugs&lt;/td&gt;
      &lt;td&gt;F&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;TLS 1.2 not supported&lt;/td&gt;
      &lt;td&gt;C&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;TLS 1.0 or TLS 1.1 enabled&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;No forward secrecy (no ECDHE/DHE)&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;No AEAD cipher (GCM or ChaCha20-Poly1305)&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;RC4 enabled&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Incomplete certificate chain&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Key or DH parameters under 2048 bits&lt;/td&gt;
      &lt;td&gt;B&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;TLS 1.3 not supported&lt;/td&gt;
      &lt;td&gt;A-&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;HSTS missing or invalid&lt;/td&gt;
      &lt;td&gt;A-&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;For the A+, the guide asks for a configuration with no warnings and HSTS with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age&lt;/code&gt; of at least six months (15768000 seconds).&lt;/p&gt;

&lt;p&gt;Two things changed in 2025: a plain A now needs both TLS 1.3 and a valid HSTS header, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TLS_FALLBACK_SCSV&lt;/code&gt; no longer counts. If an older article tells you to chase fallback SCSV, skip that part.&lt;/p&gt;

&lt;p&gt;You do not need 100 in every category. An ECDSA P-256 or RSA 2048 certificate scores 90 on key exchange, and offering AES-128 keeps cipher strength at 90. Both still get an A+. Switching to RSA 4096 only makes handshakes slower.&lt;/p&gt;

&lt;h2 id=&quot;check-your-nginx-and-openssl-versions-first&quot;&gt;Check your nginx and OpenSSL versions first&lt;/h2&gt;

&lt;p&gt;A few directives depend on the version you run:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nginx &lt;span class=&quot;nt&quot;&gt;-V&lt;/span&gt; 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-3&lt;/span&gt;
openssl version
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Feature&lt;/th&gt;
      &lt;th&gt;Needs&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;TLS 1.3 (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TLSv1.3&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_protocols&lt;/code&gt;)&lt;/td&gt;
      &lt;td&gt;OpenSSL 1.1.1+; default since nginx 1.23.4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http2 on;&lt;/code&gt; as a separate directive&lt;/td&gt;
      &lt;td&gt;nginx 1.25.1+ (older: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listen 443 ssl http2;&lt;/code&gt;)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Automatic session ticket key rotation&lt;/td&gt;
      &lt;td&gt;nginx 1.23.2+ with a shared &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_session_cache&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Hybrid post-quantum group &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;OpenSSL 3.5+&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header_inherit merge;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;nginx 1.29.3+&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx -V&lt;/code&gt; line that matters is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;built with OpenSSL ...&lt;/code&gt;. That is the library nginx actually uses, and it can differ from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl&lt;/code&gt; command on the same box.&lt;/p&gt;

&lt;h2 id=&quot;step-1-get-a-certificate-and-serve-the-full-chain&quot;&gt;Step 1: Get a certificate and serve the full chain&lt;/h2&gt;

&lt;p&gt;Any publicly trusted certificate works. With Let’s Encrypt and Certbot, get the certificate only and write the TLS config yourself:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;certbot certonly &lt;span class=&quot;nt&quot;&gt;--nginx&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; example.com &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; www.example.com
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Recent Certbot releases issue ECDSA keys by default, which is what you want. Point nginx at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fullchain.pem&lt;/code&gt;, not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cert.pem&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;ssl_certificate&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_certificate_key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cert.pem&lt;/code&gt; holds only your leaf certificate. Browsers often fill in the missing intermediate on their own, so the site looks fine, but SSL Labs reports “Chain issues: Incomplete” and caps the grade at B. The &lt;a href=&quot;https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate&quot;&gt;nginx docs&lt;/a&gt; say the same: the server certificate comes first in the file, followed by the intermediates.&lt;/p&gt;

&lt;p&gt;If you use Certbot’s own installer (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;certbot --nginx&lt;/code&gt; without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;certonly&lt;/code&gt;), it adds &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;include /etc/letsencrypt/options-ssl-nginx.conf;&lt;/code&gt; to your server block. That file sets protocols and ciphers too. Remove the include so your own settings are the only ones in play.&lt;/p&gt;

&lt;h2 id=&quot;step-2-put-the-tls-settings-in-one-shared-file&quot;&gt;Step 2: Put the TLS settings in one shared file&lt;/h2&gt;

&lt;p&gt;Debian and Ubuntu load every file in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nginx/conf.d/&lt;/code&gt; inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt; block, so a single file there applies to all your HTTPS sites.&lt;/p&gt;

&lt;p&gt;First, clear the SSL lines that the package already put in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nginx/nginx.conf&lt;/code&gt;. The stock Debian 13 file has this block inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http { }&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;##&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# SSL Settings&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;##&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;ssl_protocols&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TLSv1.2&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TLSv1.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Dropping SSLv3 (POODLE), TLS 1.0, 1.1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Don&apos;t force server cipher order.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conf.d/&lt;/code&gt; file lands in the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt; block, so these lines would collide with it. nginx refuses a second &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_prefer_server_ciphers&lt;/code&gt; at the same level:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;nginx: [emerg] &quot;ssl_prefer_server_ciphers&quot; directive is duplicate in /etc/nginx/conf.d/tls.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;A second &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_protocols&lt;/code&gt; does not replace the first one either. nginx merges the two lists and only prints warnings such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[warn] duplicate value &quot;TLSv1.2&quot;&lt;/code&gt;, not an error. Comment out both lines with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#&lt;/code&gt; (your release may have different values there), then check that nothing else sets them:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rn&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; ssl_protocols &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; ssl_prefer_server_ciphers &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; ssl_ciphers /etc/nginx/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now create &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nginx/conf.d/tls.conf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# TLS settings for every server block (http context)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_protocols&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TLSv1.2&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TLSv1.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# OpenSSL 3.5+: hybrid post-quantum group first.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# On OpenSSL 3.0-3.4, remove X25519MLKEM768 from this list.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_ecdh_curve&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X25519MLKEM768:X25519:prime256v1:secp384r1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# TLS 1.2 ciphers: ECDHE key exchange + AEAD only.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# TLS 1.3 suites are managed by OpenSSL and are all AEAD.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_ciphers&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;ssl_session_timeout&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_session_cache&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;shared:TLS:10m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# about 40000 sessions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Line by line:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_protocols TLSv1.2 TLSv1.3&lt;/code&gt;&lt;/strong&gt; turns off TLS 1.0 and 1.1 (the B cap) and turns on TLS 1.3 (without it you stop at A-). It is the default since nginx 1.23.4, but writing it here makes the intent clear. It does not override other &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_protocols&lt;/code&gt; lines in the same block, which is why you removed them above.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_ecdh_curve&lt;/code&gt;&lt;/strong&gt; sets the key exchange groups. The list comes from the &lt;a href=&quot;https://data.tlsref.org/guidelines/6.0.json&quot;&gt;TLSRef guideline 6.0&lt;/a&gt;, the successor of Mozilla’s Server Side TLS guidelines. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt; combines classic X25519 with the ML-KEM post-quantum algorithm. Clients that do not support it fall back to X25519.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_ciphers&lt;/code&gt;&lt;/strong&gt; lists only ECDHE suites, which gives forward secrecy, and only GCM or ChaCha20-Poly1305, which are AEAD. No CBC, no RSA key exchange, no 3DES. TLSRef lists the oldest clients this profile still serves as Firefox 31, Chrome 49, Safari 9, Android 4.4.2, IE 11 on Windows 10 and Java 8u161. It also replaces the cipher list from my &lt;a href=&quot;/2015/04/12/ssl_cipher-di-nginx&quot;&gt;2015 post on ssl_cipher in nginx&lt;/a&gt; (in Indonesian), which is out of date now.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_prefer_server_ciphers off&lt;/code&gt;&lt;/strong&gt; lets the client pick. With an all-strong list, the client knows best: phones without AES hardware choose ChaCha20.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;No &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_dhparam&lt;/code&gt;.&lt;/strong&gt; The list has no DHE suites, so you do not need a DH parameters file. That also removes the old “DH parameters under 2048 bits” risk.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Session tickets&lt;/strong&gt; stay at the default (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;on&lt;/code&gt;). Since nginx 1.23.2 the ticket keys rotate automatically when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_session_cache&lt;/code&gt; uses shared memory, as it does here. That is why TLSRef only adds &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_session_tickets off;&lt;/code&gt; for older versions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Mozilla SSL Configuration Generator now redirects to the &lt;a href=&quot;https://configurator.tlsref.org/&quot;&gt;TLSRef Configurator&lt;/a&gt;. This file matches its “Intermediate” profile, which is the right choice for public websites. The “Modern” profile (TLS 1.3 only) also gets an A+, but cuts off older clients such as Android 4.4 and IE 11.&lt;/p&gt;

&lt;h2 id=&quot;step-3-the-server-blocks-hsts-and-the-http-redirect&quot;&gt;Step 3: The server blocks, HSTS and the HTTP redirect&lt;/h2&gt;

&lt;p&gt;Now the site itself, for example &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nginx/sites-available/example.com&lt;/code&gt;, linked into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sites-enabled/&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Port 80: redirect everything to HTTPS&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[::]:80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example.com&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;www.example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;308&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$host$request_uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;443&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[::]:443&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;http2&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;# nginx &amp;lt; 1.25.1: &quot;listen 443 ssl http2;&quot;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example.com&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;www.example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;ssl_certificate&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;ssl_certificate_key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# HSTS: 2 years. &quot;always&quot; also sends it on 3xx/4xx/5xx responses.&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Strict-Transport-Security&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;max-age=63072000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;includeSubDomains&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/var/www/example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;index.html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Notes on the HSTS line:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age=63072000&lt;/code&gt;&lt;/strong&gt; is two years, the TLSRef value. SSL Labs needs at least 15768000 (six months) for the A+. A shorter value or a typo drops you to A-.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;always&lt;/code&gt;&lt;/strong&gt; matters. Without it, nginx adds the header only to 200, 201, 204, 206, 301, 302, 303, 304, 307 and 308 responses. With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;always&lt;/code&gt;, error pages carry it too.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;includeSubDomains&lt;/code&gt;&lt;/strong&gt; tells browsers that every subdomain is HTTPS-only as well. Leave it out until you are sure that is true. If &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;intranet.example.com&lt;/code&gt; still serves plain HTTP, browsers that have seen the header will refuse to load it.&lt;/li&gt;
  &lt;li&gt;The header goes only on the HTTPS server. Browsers ignore HSTS on plain HTTP, and the HSTS spec (&lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc6797#section-7.2&quot;&gt;RFC 6797, section 7.2&lt;/a&gt;) says servers must not send it there.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listen&lt;/code&gt; lines in each block are deliberate. If your domain has an AAAA record and nginx listens only on IPv4, SSL Labs tests the IPv6 address and gets a different answer. More on that in the troubleshooting table.&lt;/p&gt;

&lt;h2 id=&quot;step-4-ocsp-stapling-and-lets-encrypt&quot;&gt;Step 4: OCSP stapling and Let’s Encrypt&lt;/h2&gt;

&lt;p&gt;Many A+ guides still tell you to add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_stapling on;&lt;/code&gt;, including my own &lt;a href=&quot;/2015/04/12/ocsp-stapling-di-nginx&quot;&gt;OCSP stapling post from 2015&lt;/a&gt;. For Let’s Encrypt certificates, drop it.&lt;/p&gt;

&lt;p&gt;Let’s Encrypt &lt;a href=&quot;https://letsencrypt.org/2024/12/05/ending-ocsp/&quot;&gt;ended OCSP support&lt;/a&gt;: from 7 May 2025 its certificates no longer contain an OCSP URL, and the OCSP responders were switched off on 6 August 2025. Revocation now goes through CRLs. With stapling on and a current Let’s Encrypt certificate, nginx logs a warning like this on every reload:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[warn] &quot;ssl_stapling&quot; ignored, no OCSP responder URL in the certificate
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The site keeps working, but the line is noise. Remove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_stapling&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_stapling_verify&lt;/code&gt;. OCSP stapling has no effect on the SSL Labs grade.&lt;/p&gt;

&lt;p&gt;If your certificate comes from a CA that still runs OCSP, stapling is still useful. You need a resolver and the issuer chain:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;ssl_stapling&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_stapling_verify&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_trusted_certificate&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/ssl/certs/ca-chain.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# root + intermediates&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;resolver&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;127&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.0.0.53&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;valid=300s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;# e.g. systemd-resolved; use your server&apos;s resolver&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;step-5-avoid-the-add_header-trap&quot;&gt;Step 5: Avoid the add_header trap&lt;/h2&gt;

&lt;p&gt;In nginx, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header&lt;/code&gt; is inherited from the outer block only if the current block has no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header&lt;/code&gt; of its own. Add one header in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;location&lt;/code&gt; and every header from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server&lt;/code&gt; block disappears in that location, HSTS included. If that location is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;, the grade drops to A-. If it is another path, the report stays A+ while part of the site runs without the header.&lt;/p&gt;

&lt;p&gt;Here is the result on the test server (port 8443) with the config above plus one extra location:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/assets/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Cache-Control&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;public,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;max-age=3600&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ curl -sk -D- -o /dev/null https://127.0.0.1:8443/ | grep -i strict
strict-transport-security: max-age=63072000; includeSubDomains

$ curl -sk -D- -o /dev/null https://127.0.0.1:8443/assets/x | grep -i -e strict -e cache
cache-control: public, max-age=3600
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The second response has no HSTS.&lt;/p&gt;

&lt;p&gt;Three fixes, in order of preference:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;nginx 1.29.3 or newer:&lt;/strong&gt; put &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header_inherit merge;&lt;/code&gt; in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt; block. Headers from outer levels are then added to the ones you set in the inner block (&lt;a href=&quot;https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header_inherit&quot;&gt;docs&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Older nginx:&lt;/strong&gt; move the security headers into a snippet and include it wherever you use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header&lt;/code&gt; (example below).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;For caching only:&lt;/strong&gt; use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;expires 1h;&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header Cache-Control&lt;/code&gt;. It sets &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cache-Control&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Expires&lt;/code&gt; itself and, unlike &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add_header&lt;/code&gt;, does not cancel the headers inherited from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;server&lt;/code&gt; block.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The snippet approach looks like this:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# /etc/nginx/snippets/security-headers.conf&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Strict-Transport-Security&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;max-age=63072000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;includeSubDomains&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/assets/&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;snippets/security-headers&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.conf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Cache-Control&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;public,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;max-age=3600&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;location /assets/ { expires 1h; }&lt;/code&gt; on the same test server:&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ curl -sk -D- -o /dev/null https://127.0.0.1:8443/assets/x.css
HTTP/2 200
expires: Thu, 05 Nov 2026 01:41:51 GMT
cache-control: max-age=3600
strict-transport-security: max-age=63072000; includeSubDomains
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The same inheritance rule applies to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if&lt;/code&gt; blocks and nested locations.&lt;/p&gt;

&lt;h2 id=&quot;step-6-test-locally-then-run-ssl-labs&quot;&gt;Step 6: Test locally, then run SSL Labs&lt;/h2&gt;

&lt;p&gt;Check the syntax and reload:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nginx &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Before you go to SSL Labs, check the important points from your own terminal. Replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;example.com&lt;/code&gt; with your host:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# TLS 1.1 must be refused. SECLEVEL=0 lets a modern client even try it.&lt;/span&gt;
openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-tls1_1&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-cipher&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;DEFAULT@SECLEVEL=0&apos;&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;alert|Cipher is&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# TLS 1.3 must work. With OpenSSL 3.5+ on both sides the group is X25519MLKEM768.&lt;/span&gt;
openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-tls1_3&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;Negotiated TLS1.3 group|Cipher is&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# CBC suites must be refused (covers both ECDSA and RSA certificates).&lt;/span&gt;
openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &lt;span class=&quot;nt&quot;&gt;-tls1_2&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;-cipher&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA&apos;&lt;/span&gt; &amp;lt;/dev/null 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;alert|Cipher is&apos;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Full chain: there must be a &quot;depth=1&quot; line (the intermediate sent by the server).&lt;/span&gt;
openssl s_client &lt;span class=&quot;nt&quot;&gt;-connect&lt;/span&gt; example.com:443 &lt;span class=&quot;nt&quot;&gt;-servername&lt;/span&gt; example.com &amp;lt;/dev/null 2&amp;gt;&amp;amp;1 | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;depth

&lt;span class=&quot;c&quot;&gt;# HSTS header and redirect.&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;-sI&lt;/span&gt; https://example.com/ | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; strict-transport-security
curl &lt;span class=&quot;nt&quot;&gt;-sI&lt;/span&gt; http://example.com/  | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;^HTTP&apos;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;^location&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On the test setup, the output looked like this (condensed):&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;tls1_1 :  tlsv1 alert protocol version ... Cipher is (NONE)
tls1_3 :  Negotiated TLS1.3 group: X25519MLKEM768
          New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
CBC    :  ssl/tls alert handshake failure ... Cipher is (NONE)
HSTS   :  strict-transport-security: max-age=63072000; includeSubDomains
HTTP   :  HTTP/1.1 308 Permanent Redirect
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When all of that looks right, open &lt;a href=&quot;https://www.ssllabs.com/ssltest/&quot;&gt;ssllabs.com/ssltest&lt;/a&gt;, enter your hostname, and tick “Do not show the results on the boards” if you do not want the result listed publicly. SSL Labs caches results for a while. After a config change, use the “Clear cache” link on the results page to force a new scan. A full scan takes a few minutes, longer when the hostname has several IP addresses.&lt;/p&gt;

&lt;h2 id=&quot;troubleshooting-what-the-report-says-and-how-to-fix-it&quot;&gt;Troubleshooting: what the report says and how to fix it&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;What you see&lt;/th&gt;
      &lt;th&gt;Cause&lt;/th&gt;
      &lt;th&gt;Fix&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade B, “This server supports TLS 1.0 and TLS 1.1”&lt;/td&gt;
      &lt;td&gt;Old &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_protocols&lt;/code&gt; line somewhere, often in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx.conf&lt;/code&gt; or a Certbot include&lt;/td&gt;
      &lt;td&gt;Run the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grep&lt;/code&gt; from Step 2 and keep only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tls.conf&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx -t&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;ssl_prefer_server_ciphers&quot; directive is duplicate&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;The stock &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx.conf&lt;/code&gt; still sets it in the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt; block&lt;/td&gt;
      &lt;td&gt;Comment it out in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx.conf&lt;/code&gt; (Step 2)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade B, “Chain issues: Incomplete”&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_certificate&lt;/code&gt; points to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cert.pem&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fullchain.pem&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade B, cipher warnings about forward secrecy or CBC&lt;/td&gt;
      &lt;td&gt;Old &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_ciphers&lt;/code&gt; list&lt;/td&gt;
      &lt;td&gt;Use the list from Step 2&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade A-, “This server does not support TLS 1.3”&lt;/td&gt;
      &lt;td&gt;OpenSSL older than 1.1.1, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_protocols&lt;/code&gt; without &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TLSv1.3&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Upgrade the OS or nginx build; check &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx -V&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade A-, HSTS warning or “HSTS not set”&lt;/td&gt;
      &lt;td&gt;Header missing on the tested page, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age&lt;/code&gt; too short, or the add_header trap&lt;/td&gt;
      &lt;td&gt;Check with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl -sI&lt;/code&gt;; see Step 5&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;A+ on one IP, A- on another&lt;/td&gt;
      &lt;td&gt;IPv6 handled by a different server block or a different machine&lt;/td&gt;
      &lt;td&gt;Add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;listen [::]:443 ssl;&lt;/code&gt; everywhere, or fix the AAAA record&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Grade does not change after you edit nginx&lt;/td&gt;
      &lt;td&gt;You are testing a CDN, not your server&lt;/td&gt;
      &lt;td&gt;See below&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx -t&lt;/code&gt; says &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSL_CTX_set1_curves_list(...) failed&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;The OpenSSL behind nginx does not know a group in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssl_ecdh_curve&lt;/code&gt;, usually &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X25519MLKEM768&lt;/code&gt; on OpenSSL older than 3.5&lt;/td&gt;
      &lt;td&gt;Remove that group from the list&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;strong&gt;Behind Cloudflare or another CDN?&lt;/strong&gt; If the orange cloud is on, SSL Labs tests Cloudflare’s edge, not your nginx. The grade then depends on your Cloudflare settings: minimum TLS version, TLS 1.3, and HSTS under SSL/TLS &amp;gt; Edge Certificates. Your nginx config still matters for the connection between Cloudflare and your origin, so use “Full (strict)” mode and keep the setup above on the origin. (This blog sits behind Cloudflare too; the move is described in &lt;a href=&quot;/2014/11/10/migrasi-ke-cloudflare&quot;&gt;Migrasi ke Cloudflare&lt;/a&gt;, in Indonesian.)&lt;/p&gt;

&lt;h2 id=&quot;optional-hsts-preload&quot;&gt;Optional: HSTS preload&lt;/h2&gt;

&lt;p&gt;With HSTS preload, browsers ship with your domain on a built-in HTTPS-only list, so even the very first visit never uses HTTP. SSL Labs does not need it for an A+. The requirements on &lt;a href=&quot;https://hstspreload.org/&quot;&gt;hstspreload.org&lt;/a&gt; are stricter than the A+ ones:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;max-age&lt;/code&gt; of at least 31536000 (one year), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;includeSubDomains&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;preload&lt;/code&gt; in the header&lt;/li&gt;
  &lt;li&gt;every subdomain served over HTTPS, including internal ones&lt;/li&gt;
  &lt;li&gt;HTTP redirected to HTTPS on the same host first&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Strict-Transport-Security&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;max-age=63072000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;includeSubDomains&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;preload&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Getting off the list takes months to reach users through browser updates, and other browsers are not guaranteed to follow. Only submit a domain you know will stay HTTPS-only on every subdomain.&lt;/p&gt;

&lt;h2 id=&quot;the-complete-config&quot;&gt;The complete config&lt;/h2&gt;

&lt;p&gt;For reference, here are the two files used in the test above (adjust paths and names). Together with the two commented lines in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx.conf&lt;/code&gt; from Step 2, that is the whole change:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# /etc/nginx/conf.d/tls.conf&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_protocols&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TLSv1.2&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;TLSv1.3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_ecdh_curve&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;X25519MLKEM768:X25519:prime256v1:secp384r1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_ciphers&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_session_timeout&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_session_cache&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;shared:TLS:10m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# add_header_inherit merge;   # nginx 1.29.3+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# /etc/nginx/sites-available/example.com&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[::]:80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example.com&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;www.example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;308&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;https://&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$host$request_uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;443&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;listen&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;[::]:443&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;http2&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;server_name&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;example.com&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;www.example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;ssl_certificate&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;ssl_certificate_key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;add_header&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Strict-Transport-Security&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;max-age=63072000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;includeSubDomains&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;always&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kn&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/var/www/example.com&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;index.html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you need to support both ECDSA and RSA clients, nginx can load two certificates in the same server block, and it picks the right one per client:&lt;/p&gt;

&lt;div class=&quot;language-nginx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;ssl_certificate&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/fullchain.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;# ECDSA, from Step 1&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_certificate_key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com/privkey.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_certificate&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com-rsa/fullchain.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;ssl_certificate_key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;/etc/letsencrypt/live/example.com-rsa/privkey.pem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On the test server, a TLS 1.2 client that only offered &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ECDHE-RSA-AES128-GCM-SHA256&lt;/code&gt; received the 2048-bit RSA certificate, and everyone else got ECDSA. With Certbot, run it a second time with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--key-type rsa --cert-name example.com-rsa&lt;/code&gt; to get the RSA pair.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Mahyuddin Susanto is a Linux and networking sysadmin who runs his own servers and has written about nginx on this blog since 2009, starting with &lt;a href=&quot;/2009/05/09/nginx-dari-nol&quot;&gt;nginx, dari nol&lt;/a&gt;. &lt;a href=&quot;/about&quot;&gt;About&lt;/a&gt; · &lt;a href=&quot;/contact&quot;&gt;Contact&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;sources&quot;&gt;Sources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Qualys SSL Labs, &lt;a href=&quot;https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide&quot;&gt;SSL Server Rating Guide&lt;/a&gt;, version 2009r, 16 May 2025&lt;/li&gt;
  &lt;li&gt;TLSRef, &lt;a href=&quot;https://data.tlsref.org/guidelines/6.0.json&quot;&gt;Server Side TLS guideline 6.0&lt;/a&gt; and &lt;a href=&quot;https://configurator.tlsref.org/&quot;&gt;TLS Configurator&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;nginx, &lt;a href=&quot;https://nginx.org/en/docs/http/ngx_http_ssl_module.html&quot;&gt;ngx_http_ssl_module&lt;/a&gt;, &lt;a href=&quot;https://nginx.org/en/docs/http/ngx_http_headers_module.html&quot;&gt;ngx_http_headers_module&lt;/a&gt; and &lt;a href=&quot;https://nginx.org/en/CHANGES&quot;&gt;CHANGES&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Let’s Encrypt, &lt;a href=&quot;https://letsencrypt.org/2024/12/05/ending-ocsp/&quot;&gt;Ending OCSP Support in 2025&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://hstspreload.org/&quot;&gt;HSTS Preload List Submission&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;IETF, &lt;a href=&quot;https://www.rfc-editor.org/rfc/rfc6797&quot;&gt;RFC 6797: HTTP Strict Transport Security&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Mahyuddin Susanto</name></author><category term="Linux" /><category term="nginx" /><category term="tls" /><category term="ssl" /><category term="security" /><category term="hsts" /><summary type="html">To get an A+ on the Qualys SSL Labs server test with nginx, you need five things: TLS 1.2 and TLS 1.3 only, ECDHE key exchange with AEAD ciphers (GCM or ChaCha20-Poly1305), a certificate served with its full chain, an HSTS header with a max-age of at least six months, and the same setup on every IP address your hostname resolves to. Miss TLS 1.3 or HSTS and you land on A-. Leave TLS 1.0 or 1.1 on and you are stuck at B.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.udienz.web.id/img/ssl-labs-a-plus-nginx.png" /><media:content medium="image" url="https://www.udienz.web.id/img/ssl-labs-a-plus-nginx.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Mobil Listrik (1/3): Pengertian dan Jenis-Jenisnya</title><link href="https://www.udienz.web.id/2026/11/04/mobil-listrik-pengertian-jenis-cara-kerja" rel="alternate" type="text/html" title="Mobil Listrik (1/3): Pengertian dan Jenis-Jenisnya" /><published>2026-11-04T00:00:03+00:00</published><updated>2026-11-04T00:00:03+00:00</updated><id>https://www.udienz.web.id/2026/11/04/mobil-listrik-pengertian-jenis-cara-kerja</id><content type="html" xml:base="https://www.udienz.web.id/2026/11/04/mobil-listrik-pengertian-jenis-cara-kerja">&lt;p&gt;Pada September 2026, BYD Atto 1 tercatat 4.840 unit dalam data Gaikindo, peringkat kedua dalam daftar 20 model terlaris di seluruh pasar mobil Indonesia bulan itu dan yang tertinggi di antara mobil listrik (&lt;a href=&quot;https://www.gaikindo.or.id/20-model-mobil-terlaris-september-2026-atto-1-menempel-gran-max/&quot;&gt;Gaikindo, 25 Oktober 2026&lt;/a&gt;). Gaikindo sendiri menulis bahwa mobil listrik “mulai menembus jajaran model terlaris”. Harga mobil listrik terlaris sekarang mulai dari sekitar Rp150 jutaan, yaitu VinFast VF 3 dengan sewa baterai. Data di tulisan ini diperiksa pada 4 November 2026, dan tanggal terbit tiap sumber ada di sampingnya.&lt;/p&gt;

&lt;p&gt;Tulisan ini menjelaskan apa itu mobil listrik dan apa bedanya dengan hybrid, bagaimana mobil itu bekerja dari colokan sampai roda, dan mobil listrik mana yang paling banyak tercatat penjualannya di Indonesia sepanjang 2026, lengkap dengan harga, kapasitas baterai, dan klaim jarak tempuhnya. Setiap harga dan angka penjualan saya beri tanggal sumbernya, karena angkanya berubah cepat dan beberapa media menulis angka berbeda untuk model yang sama.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/mobil-listrik-pengertian-jenis-cara-kerja.jpg&quot; alt=&quot;Mobil listrik putih yang sedang diisi daya lewat kabel dari wall charger di depan gedung kaca&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Foto: &lt;a href=&quot;https://unsplash.com/photos/a-white-car-plugged-in-to-a-charging-station-JkTjKEVcckg&quot;&gt;JUICE&lt;/a&gt; di &lt;a href=&quot;https://unsplash.com&quot;&gt;Unsplash&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Poin Penting&lt;/strong&gt;&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;Mobil listrik murni (BEV) bergerak dengan motor listrik yang disuplai baterai besar dan diisi dari colokan. Hybrid biasa dan plug-in hybrid masih punya mesin bensin, jadi bukan mobil listrik murni.&lt;/li&gt;
    &lt;li&gt;Mobil listrik mengubah lebih dari 77% energi listrik menjadi tenaga di roda, sedangkan mobil bensin hanya 12% sampai 30% dari energi bensinnya (U.S. Department of Energy).&lt;/li&gt;
    &lt;li&gt;Pengisian di rumah dengan tarif listrik rumah tangga Rp1.444,70 per kWh menghabiskan sekitar Rp60 ribu sampai Rp67 ribu untuk mengisi baterai 38,88 kWh dari kosong sampai penuh, menurut hitungan di tulisan ini. Di SPKLU umum tarifnya sampai Rp2.475 per kWh.&lt;/li&gt;
    &lt;li&gt;Sepuluh mobil listrik dengan penjualan terbesar pada Januari sampai September 2026 berharga dari Rp152 juta (VinFast VF 3 dengan sewa baterai) sampai Rp950 juta (Denza D9). Tiga yang terlaris, yaitu Jaecoo J5 EV, BYD Atto 1, dan Geely EX2, berada di kisaran Rp200 jutaan sampai Rp300 jutaan.&lt;/li&gt;
    &lt;li&gt;Insentif PPN ditanggung pemerintah dan keringanan bea masuk untuk mobil listrik tidak berlanjut pada 2026. Penggantinya masih dikaji pada Juni 2026, jadi harga bisa berubah lagi.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;details class=&quot;toc&quot;&gt;
  &lt;summary&gt;Daftar isi bagian ini&lt;/summary&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#apa-itu-mobil-listrik&quot; id=&quot;markdown-toc-apa-itu-mobil-listrik&quot;&gt;Apa itu mobil listrik?&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#kenapa-orang-beralih&quot; id=&quot;markdown-toc-kenapa-orang-beralih&quot;&gt;Kenapa orang beralih&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#skala-globalnya&quot; id=&quot;markdown-toc-skala-globalnya&quot;&gt;Skala globalnya&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#jenis-jenis-mobil-listrik&quot; id=&quot;markdown-toc-jenis-jenis-mobil-listrik&quot;&gt;Jenis-jenis mobil listrik&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#pembanding-mobil-konvensional-ice&quot; id=&quot;markdown-toc-pembanding-mobil-konvensional-ice&quot;&gt;Pembanding: mobil konvensional (ICE)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#bev-mobil-listrik-murni&quot; id=&quot;markdown-toc-bev-mobil-listrik-murni&quot;&gt;BEV: mobil listrik murni&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#phev-hybrid-yang-bisa-dicolok&quot; id=&quot;markdown-toc-phev-hybrid-yang-bisa-dicolok&quot;&gt;PHEV: hybrid yang bisa dicolok&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#hev-hybrid-biasa&quot; id=&quot;markdown-toc-hev-hybrid-biasa&quot;&gt;HEV: hybrid biasa&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#fcev-mobil-listrik-berbahan-bakar-hidrogen&quot; id=&quot;markdown-toc-fcev-mobil-listrik-berbahan-bakar-hidrogen&quot;&gt;FCEV: mobil listrik berbahan bakar hidrogen&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;/details&gt;

&lt;h2 id=&quot;apa-itu-mobil-listrik&quot;&gt;Apa itu mobil listrik?&lt;/h2&gt;

&lt;p&gt;Mobil listrik adalah mobil yang digerakkan oleh motor listrik, bukan mesin pembakaran. Departemen Energi Amerika Serikat menyebut jenis yang paling murni sebagai all-electric vehicle atau battery electric vehicle (BEV): mobilnya punya baterai yang diisi dengan mencolokkan kendaraan ke peralatan pengisian, dan selalu berjalan dalam mode listrik penuh (&lt;a href=&quot;https://afdc.energy.gov/vehicles/electric&quot;&gt;U.S. DOE, Alternative Fuels Data Center&lt;/a&gt;). Tidak ada tangki bensin, pompa bahan bakar, atau saluran bahan bakar. Kendaraan seperti ini juga tidak mengeluarkan gas buang dari knalpot (&lt;a href=&quot;https://afdc.energy.gov/vehicles/how-do-all-electric-cars-work&quot;&gt;U.S. DOE&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Dalam aturan Indonesia, istilah resminya Kendaraan Bermotor Listrik Berbasis Baterai atau KBLBB. Istilah itu dipakai dalam &lt;a href=&quot;https://peraturan.bpk.go.id/Details/116973/perpres-no-55&quot;&gt;Perpres 55 Tahun 2019&lt;/a&gt; tentang percepatan program KBLBB untuk transportasi jalan, yang kemudian diubah dengan &lt;a href=&quot;https://peraturan.bpk.go.id/Details/273447&quot;&gt;Perpres 79 Tahun 2023&lt;/a&gt;. Di dealer dan di media otomotif, kamu akan lebih sering mendengar singkatan BEV atau sebutan “mobil listrik” saja.&lt;/p&gt;

&lt;h3 id=&quot;kenapa-orang-beralih&quot;&gt;Kenapa orang beralih&lt;/h3&gt;

&lt;p&gt;Alasan pertama adalah efisiensi. Menurut U.S. Department of Energy, mobil listrik mengubah lebih dari 77% energi listrik dari jaringan menjadi tenaga di roda. Mobil bensin konvensional hanya mengubah sekitar 12% sampai 30% energi tersimpan dalam bensin menjadi tenaga di roda (&lt;a href=&quot;https://www.fueleconomy.gov/feg/evtech.shtml&quot;&gt;FuelEconomy.gov&lt;/a&gt;). Angka itu berasal dari konteks Amerika Serikat, tetapi prinsip fisikanya sama di mana pun: motor listrik membuang jauh lebih sedikit energi sebagai panas dibanding mesin bensin.&lt;/p&gt;

&lt;p&gt;Alasan kedua adalah biaya energi per kilometer. Listrik rumah tangga di Indonesia dihargai Rp1.352 sampai Rp1.699,53 per kWh, tergantung golongan, untuk triwulan IV 2026 (&lt;a href=&quot;https://www.metrotvnews.com/read/NA0CzpEz-daftar-lengkap-tarif-listrik-pln-akhir-oktober-2026-per-kwh&quot;&gt;Metro TV, 29 Oktober 2026&lt;/a&gt;). Bagian hitung-hitungan ada di bawah, di bagian pengisian daya.&lt;/p&gt;

&lt;p&gt;Alasan ketiga adalah pengalaman berkendara. Menurut pengetahuan umum, motor listrik memberikan torsi sejak putaran pertama dan tidak memakai perpindahan gigi bertahap, jadi akselerasinya halus. Sisi lemahnya juga ada: jarak tempuh nyata bisa jauh di bawah angka brosur, dan pengisian bergantung pada colokan yang tersedia. Dua hal itu saya hitung dengan angka di bawah.&lt;/p&gt;

&lt;h3 id=&quot;skala-globalnya&quot;&gt;Skala globalnya&lt;/h3&gt;

&lt;p&gt;Mobil listrik bukan fenomena satu negara. Badan Energi Internasional (IEA) menulis dalam siaran pers Global EV Outlook 2026 bahwa hampir 30% mobil yang terjual pada 2026 diperkirakan berupa mobil listrik, seiring negara dan konsumen merespons krisis energi (&lt;a href=&quot;https://www.iea.org/reports/global-ev-outlook-2026&quot;&gt;IEA, Global EV Outlook 2026&lt;/a&gt;). Di Indonesia, sepuluh mobil listrik terlaris saja mencapai 89.502 unit pada sembilan bulan pertama 2026 menurut data Gaikindo, seperti yang dirinci di bagian daftar model.&lt;/p&gt;

&lt;h2 id=&quot;jenis-jenis-mobil-listrik&quot;&gt;Jenis-jenis mobil listrik&lt;/h2&gt;

&lt;p&gt;Istilah “mobil listrik” dipakai longgar untuk beberapa teknologi yang berbeda. Perbedaannya menentukan apakah kamu perlu mencari colokan, apakah masih harus ke SPBU, dan seberapa besar biaya bulanannya. Tabel berikut membandingkan mobil konvensional dengan empat jenis yang sering disebut mobil listrik. Tiap jenis dijabarkan di bawahnya dengan diagram alur energi.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Jenis&lt;/th&gt;
      &lt;th&gt;Singkatan&lt;/th&gt;
      &lt;th&gt;Sumber tenaga&lt;/th&gt;
      &lt;th&gt;Dicolok untuk diisi?&lt;/th&gt;
      &lt;th&gt;Masih pakai bensin?&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Mobil konvensional&lt;/td&gt;
      &lt;td&gt;ICE&lt;/td&gt;
      &lt;td&gt;Mesin pembakaran&lt;/td&gt;
      &lt;td&gt;Tidak&lt;/td&gt;
      &lt;td&gt;Ya&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Battery electric vehicle&lt;/td&gt;
      &lt;td&gt;BEV&lt;/td&gt;
      &lt;td&gt;Baterai besar dan motor listrik&lt;/td&gt;
      &lt;td&gt;Ya&lt;/td&gt;
      &lt;td&gt;Tidak&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Plug-in hybrid electric vehicle&lt;/td&gt;
      &lt;td&gt;PHEV&lt;/td&gt;
      &lt;td&gt;Baterai sedang, motor listrik, dan mesin bensin&lt;/td&gt;
      &lt;td&gt;Ya&lt;/td&gt;
      &lt;td&gt;Ya&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Hybrid electric vehicle&lt;/td&gt;
      &lt;td&gt;HEV&lt;/td&gt;
      &lt;td&gt;Mesin bensin dibantu motor listrik dan baterai kecil&lt;/td&gt;
      &lt;td&gt;Tidak&lt;/td&gt;
      &lt;td&gt;Ya&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Fuel cell electric vehicle&lt;/td&gt;
      &lt;td&gt;FCEV&lt;/td&gt;
      &lt;td&gt;Hidrogen yang diubah menjadi listrik oleh sel bahan bakar&lt;/td&gt;
      &lt;td&gt;Tidak (isi hidrogen)&lt;/td&gt;
      &lt;td&gt;Tidak&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Di semua diagram, garis oranye adalah bensin, biru listrik, hijau hidrogen, ungu energi yang kembali ke baterai saat mobil melambat, dan abu-abu tenaga mekanik atau sisa.&lt;/p&gt;

&lt;h3 id=&quot;pembanding-mobil-konvensional-ice&quot;&gt;Pembanding: mobil konvensional (ICE)&lt;/h3&gt;

&lt;p&gt;Mobil konvensional memakai mesin pembakaran dalam (internal combustion engine, ICE) yang membakar bensin atau solar. Semua jenis lain di bawah menambahkan atau menggantikan sebagian dari rantai ini.&lt;/p&gt;

&lt;figure class=&quot;blog-chart&quot;&gt;
&lt;svg viewBox=&quot;0 0 400 189&quot; width=&quot;400&quot; height=&quot;189&quot; role=&quot;img&quot; aria-label=&quot;Diagram mobil konvensional: bensin dari tangki masuk ke mesin pembakaran, tenaga mekanik diteruskan lewat transmisi ke roda, dan gas buang keluar lewat knalpot.&quot;&gt;
&lt;rect x=&quot;8.0&quot; y=&quot;13.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#f97316&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;62&quot; y=&quot;33&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Tangki&lt;/text&gt;
&lt;text x=&quot;62&quot; y=&quot;49&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;bensin&lt;/text&gt;
&lt;rect x=&quot;146.0&quot; y=&quot;13.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;200&quot; y=&quot;33&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Mesin&lt;/text&gt;
&lt;text x=&quot;200&quot; y=&quot;49&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;pembakaran&lt;/text&gt;
&lt;rect x=&quot;284.0&quot; y=&quot;13.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;338&quot; y=&quot;33&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Transmisi&lt;/text&gt;
&lt;text x=&quot;338&quot; y=&quot;49&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;(rasio gigi)&lt;/text&gt;
&lt;rect x=&quot;146.0&quot; y=&quot;97.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;200&quot; y=&quot;117&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Knalpot&lt;/text&gt;
&lt;text x=&quot;200&quot; y=&quot;133&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;gas buang&lt;/text&gt;
&lt;rect x=&quot;284.0&quot; y=&quot;97.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;338&quot; y=&quot;125&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Roda&lt;/text&gt;
&lt;line x1=&quot;116.0&quot; y1=&quot;36.0&quot; x2=&quot;140.0&quot; y2=&quot;36.0&quot; stroke=&quot;#f97316&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;146.0,36.0 139.0,40.0 139.0,32.0&quot; fill=&quot;#f97316&quot; stroke=&quot;#f97316&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;254.0&quot; y1=&quot;36.0&quot; x2=&quot;278.0&quot; y2=&quot;36.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;284.0,36.0 277.0,40.0 277.0,32.0&quot; fill=&quot;#9ca3af&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;338.0&quot; y1=&quot;59.0&quot; x2=&quot;338.0&quot; y2=&quot;91.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;338.0,97.0 334.0,90.0 342.0,90.0&quot; fill=&quot;#9ca3af&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;200.0&quot; y1=&quot;59.0&quot; x2=&quot;200.0&quot; y2=&quot;91.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;200.0,97.0 196.0,90.0 204.0,90.0&quot; fill=&quot;#9ca3af&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;8.0&quot; y1=&quot;173.0&quot; x2=&quot;26.0&quot; y2=&quot;173.0&quot; stroke=&quot;#f97316&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;32.0&quot; y=&quot;177&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Bensin&lt;/text&gt;
&lt;line x1=&quot;208.0&quot; y1=&quot;173.0&quot; x2=&quot;226.0&quot; y2=&quot;173.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;232.0&quot; y=&quot;177&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Mekanik&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption&gt;Alur energi mobil konvensional: bensin dibakar di mesin, tenaganya lewat transmisi ke roda, sisanya keluar sebagai gas buang dan panas.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Alurnya begini, menurut pengetahuan umum tentang mesin bensin. Pompa mengalirkan bahan bakar dari tangki ke mesin. Di dalam silinder, bahan bakar bercampur dengan udara lalu dibakar, dan pembakaran itu mendorong piston. Piston memutar poros engkol, dan putaran itu diteruskan lewat transmisi ke roda. Transmisi diperlukan karena mesin hanya bekerja baik pada rentang putaran tertentu, jadi rasio gigi diubah menurut kecepatan. Sisa pembakaran keluar lewat knalpot. Aki 12 volt menyalakan starter dan menyuplai listrik aksesori, lalu diisi ulang oleh alternator yang diputar mesin.&lt;/p&gt;

&lt;p&gt;Kelemahan utamanya ada pada efisiensi. Seperti sudah dikutip di atas, mobil bensin hanya mengubah sekitar 12% sampai 30% energi bensin menjadi tenaga di roda (&lt;a href=&quot;https://www.fueleconomy.gov/feg/evtech.shtml&quot;&gt;FuelEconomy.gov&lt;/a&gt;). Sisanya hilang sebagai panas. Kelebihannya sederhana: mengisi bahan bakar memakan beberapa menit, dan kebiasaan itu sudah dikenal semua orang. Itulah celah yang coba diisi oleh keempat jenis di bawah.&lt;/p&gt;

&lt;h3 id=&quot;bev-mobil-listrik-murni&quot;&gt;BEV: mobil listrik murni&lt;/h3&gt;

&lt;p&gt;BEV hanya punya motor listrik. Seluruh sepuluh model di daftar tulisan ini adalah BEV.&lt;/p&gt;

&lt;figure class=&quot;blog-chart&quot;&gt;
&lt;svg viewBox=&quot;0 0 400 189&quot; width=&quot;400&quot; height=&quot;189&quot; role=&quot;img&quot; aria-label=&quot;Diagram mobil listrik murni: listrik dari soket pengisian lewat pengisi daya onboard disimpan di baterai, lalu lewat elektronika daya ke motor listrik dan roda. Saat melambat, energi kembali dari motor ke baterai.&quot;&gt;
&lt;rect x=&quot;8.0&quot; y=&quot;13.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;62&quot; y=&quot;33&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Soket&lt;/text&gt;
&lt;text x=&quot;62&quot; y=&quot;49&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;pengisian&lt;/text&gt;
&lt;rect x=&quot;146.0&quot; y=&quot;13.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;200&quot; y=&quot;33&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Pengisi daya&lt;/text&gt;
&lt;text x=&quot;200&quot; y=&quot;49&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;onboard&lt;/text&gt;
&lt;rect x=&quot;284.0&quot; y=&quot;13.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;338&quot; y=&quot;33&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Baterai&lt;/text&gt;
&lt;text x=&quot;338&quot; y=&quot;49&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;traksi&lt;/text&gt;
&lt;rect x=&quot;284.0&quot; y=&quot;97.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;338&quot; y=&quot;117&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Elektronika&lt;/text&gt;
&lt;text x=&quot;338&quot; y=&quot;133&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;daya&lt;/text&gt;
&lt;rect x=&quot;146.0&quot; y=&quot;97.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;200&quot; y=&quot;117&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Motor&lt;/text&gt;
&lt;text x=&quot;200&quot; y=&quot;133&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;listrik&lt;/text&gt;
&lt;rect x=&quot;8.0&quot; y=&quot;97.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;62&quot; y=&quot;125&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Roda&lt;/text&gt;
&lt;line x1=&quot;116.0&quot; y1=&quot;36.0&quot; x2=&quot;140.0&quot; y2=&quot;36.0&quot; stroke=&quot;#38bdf8&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;146.0,36.0 139.0,40.0 139.0,32.0&quot; fill=&quot;#38bdf8&quot; stroke=&quot;#38bdf8&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;254.0&quot; y1=&quot;36.0&quot; x2=&quot;278.0&quot; y2=&quot;36.0&quot; stroke=&quot;#38bdf8&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;284.0,36.0 277.0,40.0 277.0,32.0&quot; fill=&quot;#38bdf8&quot; stroke=&quot;#38bdf8&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;333.0&quot; y1=&quot;59.0&quot; x2=&quot;333.0&quot; y2=&quot;91.0&quot; stroke=&quot;#38bdf8&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;333.0,97.0 329.0,90.0 337.0,90.0&quot; fill=&quot;#38bdf8&quot; stroke=&quot;#38bdf8&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;343.0&quot; y1=&quot;97.0&quot; x2=&quot;343.0&quot; y2=&quot;65.0&quot; stroke=&quot;#a78bfa&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;343.0,59.0 347.0,66.0 339.0,66.0&quot; fill=&quot;#a78bfa&quot; stroke=&quot;#a78bfa&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;284.0&quot; y1=&quot;115.0&quot; x2=&quot;260.0&quot; y2=&quot;115.0&quot; stroke=&quot;#38bdf8&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;254.0,115.0 261.0,111.0 261.0,119.0&quot; fill=&quot;#38bdf8&quot; stroke=&quot;#38bdf8&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;254.0&quot; y1=&quot;125.0&quot; x2=&quot;278.0&quot; y2=&quot;125.0&quot; stroke=&quot;#a78bfa&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;284.0,125.0 277.0,129.0 277.0,121.0&quot; fill=&quot;#a78bfa&quot; stroke=&quot;#a78bfa&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;146.0&quot; y1=&quot;120.0&quot; x2=&quot;122.0&quot; y2=&quot;120.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;116.0,120.0 123.0,116.0 123.0,124.0&quot; fill=&quot;#9ca3af&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;8.0&quot; y1=&quot;173.0&quot; x2=&quot;26.0&quot; y2=&quot;173.0&quot; stroke=&quot;#38bdf8&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;32.0&quot; y=&quot;177&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Listrik&lt;/text&gt;
&lt;line x1=&quot;141.3&quot; y1=&quot;173.0&quot; x2=&quot;159.3&quot; y2=&quot;173.0&quot; stroke=&quot;#a78bfa&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;165.3&quot; y=&quot;177&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Regenerasi&lt;/text&gt;
&lt;line x1=&quot;274.7&quot; y1=&quot;173.0&quot; x2=&quot;292.7&quot; y2=&quot;173.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;298.7&quot; y=&quot;177&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Mekanik&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption&gt;Alur energi mobil listrik murni (BEV) saat diisi lewat colokan AC, tanpa tangki bensin dan mesin. Pengisian cepat DC mengalir langsung ke baterai tanpa melewati pengisi daya onboard. Garis ungu menunjukkan energi yang kembali ke baterai saat mobil melambat.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h4 id=&quot;cara-kerja-bev&quot;&gt;Cara kerja BEV&lt;/h4&gt;

&lt;p&gt;Listrik masuk lewat soket pengisian. Pengisi daya onboard mengubah arus bolak-balik (AC) menjadi arus searah (DC) dan menyimpannya di baterai traksi. Saat kamu menginjak gas, elektronika daya mengatur seberapa banyak energi mengalir dari baterai ke motor, dan motor memutar roda. Saat kamu melepas gas atau mengerem, motor berbalik menjadi generator dan mengirim sebagian energi kembali ke baterai (garis ungu di diagram). Tidak ada tangki bensin, pompa bahan bakar, atau saluran bahan bakar (&lt;a href=&quot;https://afdc.energy.gov/vehicles/how-do-all-electric-cars-work&quot;&gt;U.S. DOE&lt;/a&gt;).&lt;/p&gt;

&lt;h4 id=&quot;kelebihan-dan-batas-bev&quot;&gt;Kelebihan dan batas BEV&lt;/h4&gt;

&lt;p&gt;Departemen Energi AS menyebut jarak tempuh khas BEV antara 150 dan 400 mil (&lt;a href=&quot;https://afdc.energy.gov/vehicles/electric&quot;&gt;U.S. DOE&lt;/a&gt;), atau sekitar 240 sampai 640 km. Rentang itu terlihat juga di Indonesia: VinFast VF 3 mengklaim 210 km, sedangkan BYD Sealion 7 mengklaim lebih dari 540 km, keduanya berdasarkan siklus uji NEDC.&lt;/p&gt;

&lt;p&gt;Kelebihan BEV adalah efisiensi yang tinggi (lebih dari 77% energi listrik sampai ke roda), tidak ada gas buang dari knalpot, dan, menurut pengetahuan umum, mekanis yang lebih sederhana karena tidak ada oli mesin, busi, atau knalpot yang perlu dirawat. Kelemahannya adalah ketergantungan penuh pada pengisian: kalau baterai habis, tidak ada mesin cadangan. Baterainya juga mahal dan penggantiannya bisa mahal kalau rusak (&lt;a href=&quot;https://www.fueleconomy.gov/feg/evtech.shtml&quot;&gt;FuelEconomy.gov&lt;/a&gt;), dan jarak tempuh nyata bisa jauh di bawah klaim, seperti hitungan dari dua uji jalan Geely di bagian model.&lt;/p&gt;

&lt;h4 id=&quot;bev-cocok-untuk-siapa&quot;&gt;BEV cocok untuk siapa&lt;/h4&gt;

&lt;p&gt;BEV paling masuk akal untuk orang yang bisa mengisi di rumah atau kantor dan jarak hariannya jauh di bawah klaim jarak mobil. Di Indonesia pilihannya paling luas: dari Rp152 juta (VinFast VF 3 dengan sewa baterai) sampai Rp950 juta (Denza D9) di daftar sepuluh model terlaris pada September 2026.&lt;/p&gt;

&lt;h3 id=&quot;phev-hybrid-yang-bisa-dicolok&quot;&gt;PHEV: hybrid yang bisa dicolok&lt;/h3&gt;

&lt;p&gt;PHEV punya baterai dan motor listrik, tetapi juga mesin bensin dan tangki bensin. Menurut Departemen Energi AS, sebagian besar PHEV bisa menempuh sekitar 20 sampai 40 mil dengan listrik saja (&lt;a href=&quot;https://afdc.energy.gov/vehicles/electric&quot;&gt;U.S. DOE&lt;/a&gt;), kira-kira 32 sampai 64 km, sebelum berjalan seperti hybrid biasa dengan bensin.&lt;/p&gt;

&lt;figure class=&quot;blog-chart&quot;&gt;
&lt;svg viewBox=&quot;0 0 400 273&quot; width=&quot;400&quot; height=&quot;273&quot; role=&quot;img&quot; aria-label=&quot;Diagram plug-in hybrid: baterai diisi lewat soket pengisian dan menggerakkan motor listrik, sementara mesin bensin dari tangki bensin ikut menggerakkan roda lewat transmisi penggabung. Energi pengereman kembali ke baterai.&quot;&gt;
&lt;rect x=&quot;8.0&quot; y=&quot;13.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;62&quot; y=&quot;33&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Soket&lt;/text&gt;
&lt;text x=&quot;62&quot; y=&quot;49&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;pengisian&lt;/text&gt;
&lt;rect x=&quot;146.0&quot; y=&quot;13.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;200&quot; y=&quot;33&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Baterai&lt;/text&gt;
&lt;text x=&quot;200&quot; y=&quot;49&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;sedang&lt;/text&gt;
&lt;rect x=&quot;284.0&quot; y=&quot;13.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#f97316&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;338&quot; y=&quot;33&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Tangki&lt;/text&gt;
&lt;text x=&quot;338&quot; y=&quot;49&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;bensin&lt;/text&gt;
&lt;rect x=&quot;146.0&quot; y=&quot;97.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;200&quot; y=&quot;117&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Motor&lt;/text&gt;
&lt;text x=&quot;200&quot; y=&quot;133&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;listrik&lt;/text&gt;
&lt;rect x=&quot;284.0&quot; y=&quot;97.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;338&quot; y=&quot;117&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Mesin&lt;/text&gt;
&lt;text x=&quot;338&quot; y=&quot;133&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;bensin&lt;/text&gt;
&lt;rect x=&quot;146.0&quot; y=&quot;181.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;200&quot; y=&quot;201&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Transmisi /&lt;/text&gt;
&lt;text x=&quot;200&quot; y=&quot;217&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;penggabung&lt;/text&gt;
&lt;rect x=&quot;8.0&quot; y=&quot;181.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;62&quot; y=&quot;209&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Roda&lt;/text&gt;
&lt;line x1=&quot;116.0&quot; y1=&quot;36.0&quot; x2=&quot;140.0&quot; y2=&quot;36.0&quot; stroke=&quot;#38bdf8&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;146.0,36.0 139.0,40.0 139.0,32.0&quot; fill=&quot;#38bdf8&quot; stroke=&quot;#38bdf8&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;195.0&quot; y1=&quot;59.0&quot; x2=&quot;195.0&quot; y2=&quot;91.0&quot; stroke=&quot;#38bdf8&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;195.0,97.0 191.0,90.0 199.0,90.0&quot; fill=&quot;#38bdf8&quot; stroke=&quot;#38bdf8&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;205.0&quot; y1=&quot;97.0&quot; x2=&quot;205.0&quot; y2=&quot;65.0&quot; stroke=&quot;#a78bfa&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;205.0,59.0 209.0,66.0 201.0,66.0&quot; fill=&quot;#a78bfa&quot; stroke=&quot;#a78bfa&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;338.0&quot; y1=&quot;59.0&quot; x2=&quot;338.0&quot; y2=&quot;91.0&quot; stroke=&quot;#f97316&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;338.0,97.0 334.0,90.0 342.0,90.0&quot; fill=&quot;#f97316&quot; stroke=&quot;#f97316&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;200.0&quot; y1=&quot;143.0&quot; x2=&quot;200.0&quot; y2=&quot;175.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;200.0,181.0 196.0,174.0 204.0,174.0&quot; fill=&quot;#9ca3af&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;338.0&quot; y1=&quot;143.0&quot; x2=&quot;338.0&quot; y2=&quot;204.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;line x1=&quot;338.0&quot; y1=&quot;204.0&quot; x2=&quot;260.0&quot; y2=&quot;204.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;254.0,204.0 261.0,200.0 261.0,208.0&quot; fill=&quot;#9ca3af&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;146.0&quot; y1=&quot;204.0&quot; x2=&quot;122.0&quot; y2=&quot;204.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;116.0,204.0 123.0,200.0 123.0,208.0&quot; fill=&quot;#9ca3af&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;8.0&quot; y1=&quot;257.0&quot; x2=&quot;26.0&quot; y2=&quot;257.0&quot; stroke=&quot;#f97316&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;32.0&quot; y=&quot;261&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Bensin&lt;/text&gt;
&lt;line x1=&quot;108.0&quot; y1=&quot;257.0&quot; x2=&quot;126.0&quot; y2=&quot;257.0&quot; stroke=&quot;#38bdf8&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;132.0&quot; y=&quot;261&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Listrik&lt;/text&gt;
&lt;line x1=&quot;208.0&quot; y1=&quot;257.0&quot; x2=&quot;226.0&quot; y2=&quot;257.0&quot; stroke=&quot;#a78bfa&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;232.0&quot; y=&quot;261&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Regenerasi&lt;/text&gt;
&lt;line x1=&quot;308.0&quot; y1=&quot;257.0&quot; x2=&quot;326.0&quot; y2=&quot;257.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;332.0&quot; y=&quot;261&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Mekanik&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption&gt;Alur energi plug-in hybrid (PHEV): dua sumber tenaga, listrik dari colokan dan bensin dari tangki, bertemu di transmisi sebelum ke roda.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h4 id=&quot;cara-kerja-phev&quot;&gt;Cara kerja PHEV&lt;/h4&gt;

&lt;p&gt;Baterai PHEV diisi lewat colokan, lebih besar dari baterai hybrid biasa tetapi lebih kecil dari baterai BEV. Selama baterai terisi, mobil bisa berjalan hanya dengan motor listrik. Setelah baterai turun, mesin bensin ikut bekerja, dan dua sumber tenaga itu bertemu di transmisi atau penggabung tenaga sebelum ke roda. Pengereman regeneratif tetap mengisi sebagian baterai.&lt;/p&gt;

&lt;h4 id=&quot;kelebihan-dan-batas-phev&quot;&gt;Kelebihan dan batas PHEV&lt;/h4&gt;

&lt;p&gt;Kelebihannya adalah fleksibilitas. Untuk pemakaian harian dalam kota, PHEV bisa berjalan hampir sepenuhnya dengan listrik kalau dicolok tiap malam, dan untuk perjalanan jauh mesin bensinnya menjadi cadangan sehingga kamu tidak perlu mencari SPKLU. Batasnya ada dua. Mobil ini membawa dua sistem penggerak sekaligus, jadi lebih kompleks, dan pada contoh Darion di bawah harganya lebih tinggi dari versi listrik murninya. Dan manfaatnya hilang kalau jarang dicolok: tanpa listrik dari colokan, mobil bergantung pada mesin bensin dan membawa baterai yang jarang terpakai.&lt;/p&gt;

&lt;p&gt;Contoh di Indonesia adalah Wuling Darion, yang dijual dalam varian EV dan PHEV. Menurut daftar harga Otodriver edisi September 2026, Darion PHEV CE dan EX masing-masing dijual Rp449 juta dan Rp499 juta, sedangkan Darion EV CE dan EX Rp399 juta dan Rp459 juta (&lt;a href=&quot;https://otodriver.com/daftar-harga/2026/daftar-harga-wuling-terbaru-september-2026-dafefcff026&quot;&gt;Otodriver&lt;/a&gt;). Selisih Rp40 juta sampai Rp50 juta itu membeli mesin bensin sebagai cadangan.&lt;/p&gt;

&lt;h4 id=&quot;phev-cocok-untuk-siapa&quot;&gt;PHEV cocok untuk siapa&lt;/h4&gt;

&lt;p&gt;PHEV masuk akal untuk orang yang bisa mencolok di rumah tetapi sering menempuh perjalanan jauh tanpa jaminan ada SPKLU di rute. Kalau kamu hampir tidak pernah mencolok, PHEV kehilangan alasannya.&lt;/p&gt;

&lt;h3 id=&quot;hev-hybrid-biasa&quot;&gt;HEV: hybrid biasa&lt;/h3&gt;

&lt;p&gt;Pada HEV, baterai diisi lewat pengereman regeneratif dan mesin, bukan lewat colokan. Departemen Energi AS menegaskan hal itu: baterai hybrid diisi “through regenerative braking, not by plugging in” (&lt;a href=&quot;https://afdc.energy.gov/vehicles/electric&quot;&gt;U.S. DOE&lt;/a&gt;). Karena itu HEV tidak butuh SPKLU sama sekali.&lt;/p&gt;

&lt;figure class=&quot;blog-chart&quot;&gt;
&lt;svg viewBox=&quot;0 0 400 273&quot; width=&quot;400&quot; height=&quot;273&quot; role=&quot;img&quot; aria-label=&quot;Diagram hybrid biasa: bensin dari tangki masuk ke mesin. Mesin dan motor-generator bersama menggerakkan roda lewat transmisi penggabung. Baterai kecil diisi oleh mesin dan pengereman, tanpa soket pengisian.&quot;&gt;
&lt;rect x=&quot;8.0&quot; y=&quot;13.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#f97316&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;62&quot; y=&quot;33&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Tangki&lt;/text&gt;
&lt;text x=&quot;62&quot; y=&quot;49&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;bensin&lt;/text&gt;
&lt;rect x=&quot;146.0&quot; y=&quot;13.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;200&quot; y=&quot;33&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Mesin&lt;/text&gt;
&lt;text x=&quot;200&quot; y=&quot;49&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;bensin&lt;/text&gt;
&lt;rect x=&quot;8.0&quot; y=&quot;97.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;62&quot; y=&quot;117&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Baterai&lt;/text&gt;
&lt;text x=&quot;62&quot; y=&quot;133&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;kecil&lt;/text&gt;
&lt;rect x=&quot;146.0&quot; y=&quot;97.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;200&quot; y=&quot;117&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Motor-&lt;/text&gt;
&lt;text x=&quot;200&quot; y=&quot;133&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;generator&lt;/text&gt;
&lt;rect x=&quot;284.0&quot; y=&quot;97.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;338&quot; y=&quot;117&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Transmisi /&lt;/text&gt;
&lt;text x=&quot;338&quot; y=&quot;133&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;penggabung&lt;/text&gt;
&lt;rect x=&quot;284.0&quot; y=&quot;181.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;338&quot; y=&quot;209&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Roda&lt;/text&gt;
&lt;line x1=&quot;116.0&quot; y1=&quot;36.0&quot; x2=&quot;140.0&quot; y2=&quot;36.0&quot; stroke=&quot;#f97316&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;146.0,36.0 139.0,40.0 139.0,32.0&quot; fill=&quot;#f97316&quot; stroke=&quot;#f97316&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;195.0&quot; y1=&quot;59.0&quot; x2=&quot;195.0&quot; y2=&quot;91.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;195.0,97.0 191.0,90.0 199.0,90.0&quot; fill=&quot;#9ca3af&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;254.0&quot; y1=&quot;36.0&quot; x2=&quot;338.0&quot; y2=&quot;36.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;line x1=&quot;338.0&quot; y1=&quot;36.0&quot; x2=&quot;338.0&quot; y2=&quot;91.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;338.0,97.0 334.0,90.0 342.0,90.0&quot; fill=&quot;#9ca3af&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;116.0&quot; y1=&quot;115.0&quot; x2=&quot;140.0&quot; y2=&quot;115.0&quot; stroke=&quot;#38bdf8&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;146.0,115.0 139.0,119.0 139.0,111.0&quot; fill=&quot;#38bdf8&quot; stroke=&quot;#38bdf8&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;146.0&quot; y1=&quot;125.0&quot; x2=&quot;122.0&quot; y2=&quot;125.0&quot; stroke=&quot;#a78bfa&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;116.0,125.0 123.0,121.0 123.0,129.0&quot; fill=&quot;#a78bfa&quot; stroke=&quot;#a78bfa&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;254.0&quot; y1=&quot;120.0&quot; x2=&quot;278.0&quot; y2=&quot;120.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;284.0,120.0 277.0,124.0 277.0,116.0&quot; fill=&quot;#9ca3af&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;338.0&quot; y1=&quot;143.0&quot; x2=&quot;338.0&quot; y2=&quot;175.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;338.0,181.0 334.0,174.0 342.0,174.0&quot; fill=&quot;#9ca3af&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;8.0&quot; y1=&quot;257.0&quot; x2=&quot;26.0&quot; y2=&quot;257.0&quot; stroke=&quot;#f97316&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;32.0&quot; y=&quot;261&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Bensin&lt;/text&gt;
&lt;line x1=&quot;108.0&quot; y1=&quot;257.0&quot; x2=&quot;126.0&quot; y2=&quot;257.0&quot; stroke=&quot;#38bdf8&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;132.0&quot; y=&quot;261&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Listrik&lt;/text&gt;
&lt;line x1=&quot;208.0&quot; y1=&quot;257.0&quot; x2=&quot;226.0&quot; y2=&quot;257.0&quot; stroke=&quot;#a78bfa&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;232.0&quot; y=&quot;261&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Regenerasi&lt;/text&gt;
&lt;line x1=&quot;308.0&quot; y1=&quot;257.0&quot; x2=&quot;326.0&quot; y2=&quot;257.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;332.0&quot; y=&quot;261&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Mekanik&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption&gt;Alur energi hybrid biasa (HEV): bensin tetap sumber utama, motor-generator membantu, dan baterai kecil diisi dari mesin dan pengereman, bukan dari colokan.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h4 id=&quot;cara-kerja-hev&quot;&gt;Cara kerja HEV&lt;/h4&gt;

&lt;p&gt;Mesin bensin tetap sumber tenaga utama. Motor-generator membantu menggerakkan roda, terutama saat mobil mulai bergerak atau berjalan pelan, dan baterai kecilnya menyimpan energi dari pengereman regeneratif serta dari mesin yang memutar generator. Tidak ada soket pengisian, jadi kamu mengisi bensin seperti mobil biasa.&lt;/p&gt;

&lt;h4 id=&quot;kelebihan-dan-batas-hev&quot;&gt;Kelebihan dan batas HEV&lt;/h4&gt;

&lt;p&gt;Kelebihan HEV adalah kebiasaannya tidak berubah: tidak ada colokan, tidak ada kecemasan jarak, dan tidak bergantung pada infrastruktur pengisian. Bagi orang yang belum siap mengubah kebiasaan, HEV paling mudah diadopsi. Batasnya: mesin bensin tetap menjadi sumber tenaga utama, jadi mobil ini tidak menghilangkan gas buang, dan halaman Departemen Energi AS tentang kendaraan listrik tidak menyebut angka jarak listrik murni untuk HEV (&lt;a href=&quot;https://afdc.energy.gov/vehicles/electric&quot;&gt;U.S. DOE&lt;/a&gt;). Karena baterainya kecil, kemampuannya berjalan hanya dengan listrik terbatas, menurut gambaran umum.&lt;/p&gt;

&lt;h4 id=&quot;hev-cocok-untuk-siapa&quot;&gt;HEV cocok untuk siapa&lt;/h4&gt;

&lt;p&gt;HEV cocok untuk pemilik yang tidak punya tempat mengisi daya dan ingin pemakaian bensin lebih hemat tanpa mengubah rutinitas. Tulisan ini fokus ke mobil listrik murni, jadi model HEV tidak dibahas satu per satu.&lt;/p&gt;

&lt;h3 id=&quot;fcev-mobil-listrik-berbahan-bakar-hidrogen&quot;&gt;FCEV: mobil listrik berbahan bakar hidrogen&lt;/h3&gt;

&lt;p&gt;FCEV memakai hidrogen yang disimpan di tangki. Di dalam sel bahan bakar jenis polymer electrolyte membrane (PEM), hidrogen dipecah menjadi proton dan elektron. Elektron mengalir lewat rangkaian luar dan menggerakkan motor listrik, sementara di sisi katoda proton, elektron, dan oksigen dari udara bergabung menjadi air (&lt;a href=&quot;https://afdc.energy.gov/vehicles/fuel-cell&quot;&gt;U.S. DOE&lt;/a&gt;).&lt;/p&gt;

&lt;figure class=&quot;blog-chart&quot;&gt;
&lt;svg viewBox=&quot;0 0 400 303&quot; width=&quot;400&quot; height=&quot;303&quot; role=&quot;img&quot; aria-label=&quot;Diagram mobil sel bahan bakar hidrogen: hidrogen dari tangki dan oksigen dari udara bereaksi di sel bahan bakar menghasilkan listrik dan uap air. Listrik lewat elektronika daya ke motor dan roda, dengan baterai kecil sebagai penyangga.&quot;&gt;
&lt;rect x=&quot;8.0&quot; y=&quot;43.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#22c55e&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;62&quot; y=&quot;63&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Tangki&lt;/text&gt;
&lt;text x=&quot;62&quot; y=&quot;79&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;hidrogen&lt;/text&gt;
&lt;rect x=&quot;146.0&quot; y=&quot;43.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;200&quot; y=&quot;63&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Sel bahan&lt;/text&gt;
&lt;text x=&quot;200&quot; y=&quot;79&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;bakar (PEM)&lt;/text&gt;
&lt;rect x=&quot;284.0&quot; y=&quot;43.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;338&quot; y=&quot;63&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Uap air&lt;/text&gt;
&lt;text x=&quot;338&quot; y=&quot;79&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;keluar&lt;/text&gt;
&lt;rect x=&quot;8.0&quot; y=&quot;127.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;62&quot; y=&quot;147&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Motor&lt;/text&gt;
&lt;text x=&quot;62&quot; y=&quot;163&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;listrik&lt;/text&gt;
&lt;rect x=&quot;146.0&quot; y=&quot;127.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;200&quot; y=&quot;147&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Elektronika&lt;/text&gt;
&lt;text x=&quot;200&quot; y=&quot;163&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;daya&lt;/text&gt;
&lt;rect x=&quot;284.0&quot; y=&quot;127.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;338&quot; y=&quot;147&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Baterai&lt;/text&gt;
&lt;text x=&quot;338&quot; y=&quot;163&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;kecil&lt;/text&gt;
&lt;rect x=&quot;8.0&quot; y=&quot;211.0&quot; width=&quot;108&quot; height=&quot;46&quot; rx=&quot;6&quot; fill=&quot;none&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;62&quot; y=&quot;239&quot; text-anchor=&quot;middle&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Roda&lt;/text&gt;
&lt;line x1=&quot;116.0&quot; y1=&quot;66.0&quot; x2=&quot;140.0&quot; y2=&quot;66.0&quot; stroke=&quot;#22c55e&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;146.0,66.0 139.0,70.0 139.0,62.0&quot; fill=&quot;#22c55e&quot; stroke=&quot;#22c55e&quot;&gt;&lt;/polygon&gt;
&lt;text x=&quot;131.0&quot; y=&quot;61.0&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;H2&lt;/text&gt;
&lt;line x1=&quot;254.0&quot; y1=&quot;66.0&quot; x2=&quot;278.0&quot; y2=&quot;66.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;284.0,66.0 277.0,70.0 277.0,62.0&quot; fill=&quot;#9ca3af&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;200.0&quot; y1=&quot;89.0&quot; x2=&quot;200.0&quot; y2=&quot;121.0&quot; stroke=&quot;#38bdf8&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;200.0,127.0 196.0,120.0 204.0,120.0&quot; fill=&quot;#38bdf8&quot; stroke=&quot;#38bdf8&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;146.0&quot; y1=&quot;145.0&quot; x2=&quot;122.0&quot; y2=&quot;145.0&quot; stroke=&quot;#38bdf8&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;116.0,145.0 123.0,141.0 123.0,149.0&quot; fill=&quot;#38bdf8&quot; stroke=&quot;#38bdf8&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;116.0&quot; y1=&quot;155.0&quot; x2=&quot;140.0&quot; y2=&quot;155.0&quot; stroke=&quot;#a78bfa&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;146.0,155.0 139.0,159.0 139.0,151.0&quot; fill=&quot;#a78bfa&quot; stroke=&quot;#a78bfa&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;284.0&quot; y1=&quot;145.0&quot; x2=&quot;260.0&quot; y2=&quot;145.0&quot; stroke=&quot;#38bdf8&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;254.0,145.0 261.0,141.0 261.0,149.0&quot; fill=&quot;#38bdf8&quot; stroke=&quot;#38bdf8&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;254.0&quot; y1=&quot;155.0&quot; x2=&quot;278.0&quot; y2=&quot;155.0&quot; stroke=&quot;#a78bfa&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;284.0,155.0 277.0,159.0 277.0,151.0&quot; fill=&quot;#a78bfa&quot; stroke=&quot;#a78bfa&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;62.0&quot; y1=&quot;173.0&quot; x2=&quot;62.0&quot; y2=&quot;205.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;62.0,211.0 58.0,204.0 66.0,204.0&quot; fill=&quot;#9ca3af&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/polygon&gt;
&lt;line x1=&quot;200.0&quot; y1=&quot;13.0&quot; x2=&quot;200.0&quot; y2=&quot;37.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;polygon points=&quot;200.0,43.0 196.0,36.0 204.0,36.0&quot; fill=&quot;#9ca3af&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/polygon&gt;
&lt;text x=&quot;208.0&quot; y=&quot;29.0&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;O2 dari udara&lt;/text&gt;
&lt;line x1=&quot;8.0&quot; y1=&quot;287.0&quot; x2=&quot;26.0&quot; y2=&quot;287.0&quot; stroke=&quot;#22c55e&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;32.0&quot; y=&quot;291&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Hidrogen&lt;/text&gt;
&lt;line x1=&quot;108.0&quot; y1=&quot;287.0&quot; x2=&quot;126.0&quot; y2=&quot;287.0&quot; stroke=&quot;#38bdf8&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;132.0&quot; y=&quot;291&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Listrik&lt;/text&gt;
&lt;line x1=&quot;208.0&quot; y1=&quot;287.0&quot; x2=&quot;226.0&quot; y2=&quot;287.0&quot; stroke=&quot;#a78bfa&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;232.0&quot; y=&quot;291&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Regenerasi&lt;/text&gt;
&lt;line x1=&quot;308.0&quot; y1=&quot;287.0&quot; x2=&quot;326.0&quot; y2=&quot;287.0&quot; stroke=&quot;#9ca3af&quot; stroke-width=&quot;2&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;332.0&quot; y=&quot;291&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Mekanik&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption&gt;Alur energi mobil hidrogen (FCEV): sel bahan bakar mengubah hidrogen dan oksigen udara menjadi listrik, dengan uap air dan udara hangat sebagai satu-satunya yang keluar dari knalpot.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h4 id=&quot;cara-kerja-fcev&quot;&gt;Cara kerja FCEV&lt;/h4&gt;

&lt;p&gt;Dari motor ke roda, rantai FCEV mirip BEV: elektronika daya mengatur listrik ke motor, dan pengereman regeneratif menangkap energi yang tadinya hilang lalu menyimpannya di baterai (&lt;a href=&quot;https://afdc.energy.gov/vehicles/fuel-cell&quot;&gt;U.S. DOE&lt;/a&gt;). Bedanya ada di hulu. Listrik tidak berasal dari colokan, tetapi dibuat di dalam mobil dari hidrogen dan oksigen udara.&lt;/p&gt;

&lt;h4 id=&quot;kelebihan-dan-batas-fcev&quot;&gt;Kelebihan dan batas FCEV&lt;/h4&gt;

&lt;p&gt;Departemen Energi AS menyebut pengisian hidrogen memakan sekitar lima menit dengan jarak tempuh lebih dari 300 mil, atau sekitar 480 km (&lt;a href=&quot;https://afdc.energy.gov/vehicles/fuel-cell&quot;&gt;U.S. DOE&lt;/a&gt;). Mobilnya hanya mengeluarkan uap air dan udara hangat dari knalpot, dan lebih efisien dari mobil pembakaran, meski halaman itu tidak memberi angka efisiensinya. Halaman itu juga hanya membahas emisi dari knalpot, bukan emisi dari pembuatan hidrogen.&lt;/p&gt;

&lt;p&gt;Batas terbesarnya infrastruktur: Departemen Energi AS menggambarkan kendaraan dan fasilitas pengisiannya masih di tahap awal (&lt;a href=&quot;https://afdc.energy.gov/vehicles/fuel-cell&quot;&gt;U.S. DOE&lt;/a&gt;).&lt;/p&gt;

&lt;h4 id=&quot;fcev-cocok-untuk-siapa&quot;&gt;FCEV cocok untuk siapa&lt;/h4&gt;

&lt;p&gt;Di daftar sepuluh mobil listrik terlaris tulisan ini tidak ada FCEV, dan saya tidak menempatkannya sebagai pilihan pembelian umum. Kalau kamu tertarik, tanyakan ke agen pemegang merek soal ketersediaan unit dan stasiun pengisian hidrogen di kotamu sebelum mempertimbangkannya.&lt;/p&gt;</content><author><name>Mahyuddin Susanto</name></author><category term="Mobil" /><category term="Otomotif" /><category term="mobil listrik" /><category term="bev" /><category term="baterai" /><category term="spklu" /><category term="harga mobil listrik" /><summary type="html">Pada September 2026, BYD Atto 1 tercatat 4.840 unit dalam data Gaikindo, peringkat kedua dalam daftar 20 model terlaris di seluruh pasar mobil Indonesia bulan itu dan yang tertinggi di antara mobil listrik (Gaikindo, 25 Oktober 2026). Gaikindo sendiri menulis bahwa mobil listrik “mulai menembus jajaran model terlaris”. Harga mobil listrik terlaris sekarang mulai dari sekitar Rp150 jutaan, yaitu VinFast VF 3 dengan sewa baterai. Data di tulisan ini diperiksa pada 4 November 2026, dan tanggal terbit tiap sumber ada di sampingnya.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.udienz.web.id/img/mobil-listrik-pengertian-jenis-cara-kerja.jpg" /><media:content medium="image" url="https://www.udienz.web.id/img/mobil-listrik-pengertian-jenis-cara-kerja.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Mobil Listrik (2/3): Cara Kerja, Pengisian Daya, dan Harga</title><link href="https://www.udienz.web.id/2026/11/04/mobil-listrik-cara-kerja-pengisian-harga" rel="alternate" type="text/html" title="Mobil Listrik (2/3): Cara Kerja, Pengisian Daya, dan Harga" /><published>2026-11-04T00:00:02+00:00</published><updated>2026-11-04T00:00:02+00:00</updated><id>https://www.udienz.web.id/2026/11/04/mobil-listrik-cara-kerja-pengisian-harga</id><content type="html" xml:base="https://www.udienz.web.id/2026/11/04/mobil-listrik-cara-kerja-pengisian-harga">&lt;details class=&quot;toc&quot;&gt;
  &lt;summary&gt;Daftar isi bagian ini&lt;/summary&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#cara-kerja-mobil-listrik&quot; id=&quot;markdown-toc-cara-kerja-mobil-listrik&quot;&gt;Cara kerja mobil listrik&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#satu-perjalanan-dari-colokan-sampai-roda&quot; id=&quot;markdown-toc-satu-perjalanan-dari-colokan-sampai-roda&quot;&gt;Satu perjalanan dari colokan sampai roda&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#baterai-kwh-adalah-tangki-nya&quot; id=&quot;markdown-toc-baterai-kwh-adalah-tangki-nya&quot;&gt;Baterai: kWh adalah “tangki”-nya&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#dua-kimia-baterai-yang-paling-sering-kamu-dengar&quot; id=&quot;markdown-toc-dua-kimia-baterai-yang-paling-sering-kamu-dengar&quot;&gt;Dua kimia baterai yang paling sering kamu dengar&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#pengereman-regeneratif&quot; id=&quot;markdown-toc-pengereman-regeneratif&quot;&gt;Pengereman regeneratif&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#kenapa-pengisian-ac-dan-dc-berbeda&quot; id=&quot;markdown-toc-kenapa-pengisian-ac-dan-dc-berbeda&quot;&gt;Kenapa pengisian AC dan DC berbeda&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#berapa-lama-mengisi-penuh&quot; id=&quot;markdown-toc-berapa-lama-mengisi-penuh&quot;&gt;Berapa lama mengisi penuh&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#istilah-yang-akan-kamu-temui-di-brosur&quot; id=&quot;markdown-toc-istilah-yang-akan-kamu-temui-di-brosur&quot;&gt;Istilah yang akan kamu temui di brosur&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#pengisian-daya-di-indonesia&quot; id=&quot;markdown-toc-pengisian-daya-di-indonesia&quot;&gt;Pengisian daya di Indonesia&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#di-rumah&quot; id=&quot;markdown-toc-di-rumah&quot;&gt;Di rumah&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#di-spklu-umum&quot; id=&quot;markdown-toc-di-spklu-umum&quot;&gt;Di SPKLU umum&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#biaya-mengisi-penuh-untuk-tiap-model&quot; id=&quot;markdown-toc-biaya-mengisi-penuh-untuk-tiap-model&quot;&gt;Biaya mengisi penuh untuk tiap model&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#berapa-harga-mobil-listrik-dan-kenapa-angkanya-berubah-ubah&quot; id=&quot;markdown-toc-berapa-harga-mobil-listrik-dan-kenapa-angkanya-berubah-ubah&quot;&gt;Berapa harga mobil listrik dan kenapa angkanya berubah-ubah&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/details&gt;

&lt;h2 id=&quot;cara-kerja-mobil-listrik&quot;&gt;Cara kerja mobil listrik&lt;/h2&gt;

&lt;p&gt;Alur energinya mudah diikuti kalau dilihat dari colokan sampai roda. Listrik masuk lewat soket pengisian, disimpan di baterai, dikendalikan oleh elektronika daya, lalu diubah menjadi putaran oleh motor. Departemen Energi AS mendaftar komponen utama mobil listrik murni seperti berikut (&lt;a href=&quot;https://afdc.energy.gov/vehicles/how-do-all-electric-cars-work&quot;&gt;U.S. DOE&lt;/a&gt;):&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Komponen&lt;/th&gt;
      &lt;th&gt;Fungsi&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Baterai traksi (traction battery pack)&lt;/td&gt;
      &lt;td&gt;Menyimpan listrik untuk motor penggerak&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Motor traksi listrik&lt;/td&gt;
      &lt;td&gt;Memakai tenaga baterai untuk memutar roda&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Pengendali elektronika daya&lt;/td&gt;
      &lt;td&gt;Mengatur aliran energi dari baterai serta kecepatan dan torsi motor&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Pengisi daya onboard (onboard charger)&lt;/td&gt;
      &lt;td&gt;Mengubah listrik AC dari soket menjadi DC untuk baterai, dan memantau kondisi baterai&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Konverter DC/DC&lt;/td&gt;
      &lt;td&gt;Menurunkan tegangan tinggi baterai untuk aksesori dan aki bantu&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Sistem termal&lt;/td&gt;
      &lt;td&gt;Menjaga motor, elektronika daya, dan komponen lain pada suhu kerja yang tepat&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Soket pengisian&lt;/td&gt;
      &lt;td&gt;Menghubungkan mobil ke sumber listrik luar&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;satu-perjalanan-dari-colokan-sampai-roda&quot;&gt;Satu perjalanan dari colokan sampai roda&lt;/h3&gt;

&lt;p&gt;Ikuti satu siklus penuh dengan komponen di atas. Malam hari kamu mencolokkan mobil ke charger rumah. Listrik AC masuk lewat soket pengisian, dan pengisi daya onboard mengubahnya menjadi DC sambil memantau kondisi baterai. Baterai traksi menyimpan energi itu sampai penuh atau sampai batas yang kamu atur.&lt;/p&gt;

&lt;p&gt;Paginya, saat kamu menekan pedal gas, pengendali elektronika daya mengambil energi dari baterai dan menyalurkannya ke motor dalam jumlah yang sesuai posisi pedal. Motor memutar roda lewat transmisi listrik. Pada saat yang sama, konverter DC/DC menurunkan tegangan sebagian energi untuk lampu, layar, dan aksesori. Sistem termal menjaga semua bagian itu tetap dalam suhu kerjanya, karena baterai dan elektronika daya sama-sama tidak nyaman bekerja terlalu panas.&lt;/p&gt;

&lt;p&gt;Saat kamu melepas pedal dan mobil melambat, arahnya berbalik sebagian: motor menjadi generator dan mengirim sedikit energi kembali ke baterai.&lt;/p&gt;

&lt;h3 id=&quot;baterai-kwh-adalah-tangki-nya&quot;&gt;Baterai: kWh adalah “tangki”-nya&lt;/h3&gt;

&lt;p&gt;Kapasitas baterai diukur dalam kilowatt-jam (kWh). Anggap itu ukuran tangki. Baterai 38,88 kWh pada BYD Atto 1 Premium menyimpan energi lebih sedikit dari baterai 103,36 kWh pada Denza D9, dan itu salah satu sebab klaim jaraknya 380 km berbanding 600 km.&lt;/p&gt;

&lt;p&gt;Satuan kilowatt (kW) mengukur daya, bukan kapasitas. Motor Geely EX2 berdaya 85 kW (&lt;a href=&quot;https://www.carmudi.co.id/journal/harga-geely-ex2-setelah-resmi-meluncur-di-indonesia-mulai-segini/&quot;&gt;Carmudi, 21 Januari 2026&lt;/a&gt;), sedangkan motor Wuling Darion EV berdaya 150 kW (&lt;a href=&quot;https://oto.detik.com/mobil-listrik/d-8197085/spesifikasi-wuling-darion-ada-varian-ev-dan-phev-harga-mulai-rp-356-juta&quot;&gt;detikOto, 6 November 2025&lt;/a&gt;). Kapasitas baterai menentukan seberapa jauh mobil bisa berjalan, sedangkan daya motor menentukan seberapa kuat tarikannya.&lt;/p&gt;

&lt;h3 id=&quot;dua-kimia-baterai-yang-paling-sering-kamu-dengar&quot;&gt;Dua kimia baterai yang paling sering kamu dengar&lt;/h3&gt;

&lt;p&gt;Menurut pengetahuan umum, mobil listrik penumpang memakai baterai lithium-ion. Dua kimianya yang paling sering muncul di brosur adalah LFP (lithium iron phosphate) dan NMC (nikel-mangan-kobalt). Geely EX2 dan Wuling Darion EV, misalnya, memakai baterai LFP menurut sumber di bagian model di bawah.&lt;/p&gt;

&lt;p&gt;Secara umum, LFP dikenal lebih murah dan tahan banyak siklus pengisian, sedangkan NMC dikenal lebih padat energi, sehingga untuk kapasitas yang sama paketnya lebih ringan. Itu gambaran umum, bukan angka dari sumber yang dikutip di sini. Perbedaan kimia ini juga masuk ke kebijakan: rencana PPN DTP pemerintah yang dibahas di bagian harga memberi tarif berbeda untuk baterai berbasis nikel dan non-nikel.&lt;/p&gt;

&lt;h3 id=&quot;pengereman-regeneratif&quot;&gt;Pengereman regeneratif&lt;/h3&gt;

&lt;p&gt;Saat kamu melepas pedal gas atau menginjak rem, motor listrik bisa berbalik fungsi menjadi generator. Energi gerak mobil diubah kembali menjadi listrik dan dimasukkan ke baterai. Halaman Departemen Energi AS tentang mobil hidrogen menjelaskan prinsipnya sebagai penangkapan energi yang tadinya hilang saat pengereman, lalu menyimpannya di baterai (&lt;a href=&quot;https://afdc.energy.gov/vehicles/fuel-cell&quot;&gt;U.S. DOE&lt;/a&gt;). Menurut pengetahuan umum, efeknya paling terasa di lalu lintas macet, tempat kamu sering berhenti dan jalan. Di jalan tol dengan kecepatan konstan, manfaatnya jauh lebih kecil.&lt;/p&gt;

&lt;h3 id=&quot;kenapa-pengisian-ac-dan-dc-berbeda&quot;&gt;Kenapa pengisian AC dan DC berbeda&lt;/h3&gt;

&lt;p&gt;Listrik dari jaringan PLN berupa arus bolak-balik (AC), sedangkan baterai hanya menyimpan arus searah (DC). Pada pengisian AC, pengisi daya onboard di dalam mobil yang mengubahnya. Kemampuan alat itu terbatas, sehingga pengisian AC memakan waktu lama: FuelEconomy.gov menyebut 3 sampai 12 jam untuk mengisi penuh, seperti dikutip di bawah.&lt;/p&gt;

&lt;p&gt;Pengisian cepat DC melewati bagian itu. Charger di luar mobil sudah menyalurkan arus searah langsung ke baterai, sehingga dayanya bisa jauh lebih besar. Itu sebabnya waktu pengisian cepat dihitung dalam menit, bukan jam. Jaecoo J5 EV, misalnya, mendukung pengisian DC sampai 130 kW menurut &lt;a href=&quot;https://oto.detik.com/mobil-listrik/d-8182231/harga-resmi-jaecoo-j5-ev-diumumkan-3-november-ini-bocoran-spesifikasinya&quot;&gt;detikOto&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;berapa-lama-mengisi-penuh&quot;&gt;Berapa lama mengisi penuh&lt;/h3&gt;

&lt;p&gt;FuelEconomy.gov menyebut pengisian baterai penuh bisa memakan 3 sampai 12 jam, sedangkan pengisian cepat sampai 80% kapasitas bisa selesai dalam sekitar 30 menit (&lt;a href=&quot;https://www.fueleconomy.gov/feg/evtech.shtml&quot;&gt;FuelEconomy.gov&lt;/a&gt;). Angka dari produsen di Indonesia sejalan dengan itu: Geely EX5 mengklaim pengisian 30% ke 80% dalam 20 menit (&lt;a href=&quot;https://www.idxchannel.com/technology/hadir-kembali-di-pasar-otomotif-ri-geely-hadirkan-mobil-listrik-dengan-segudang-teknologi&quot;&gt;IDX Channel, 22 Februari 2025&lt;/a&gt;), dan Jaecoo J5 EV mengklaim 28 menit untuk rentang yang sama (&lt;a href=&quot;https://oto.detik.com/mobil-listrik/d-8182231/harga-resmi-jaecoo-j5-ev-diumumkan-3-november-ini-bocoran-spesifikasinya&quot;&gt;detikOto, 28 Oktober 2025&lt;/a&gt;).&lt;/p&gt;

&lt;h3 id=&quot;istilah-yang-akan-kamu-temui-di-brosur&quot;&gt;Istilah yang akan kamu temui di brosur&lt;/h3&gt;

&lt;p&gt;Beberapa singkatan muncul berulang di artikel dan brosur mobil listrik. Memahaminya mencegah salah bandingkan.&lt;/p&gt;

&lt;p&gt;NEDC adalah New European Driving Cycle, siklus uji laboratorium yang dipakai banyak pabrikan untuk mengklaim jarak tempuh. CLTC adalah siklus uji dari Tiongkok. Kedua siklus memakai kecepatan dan pola berhenti yang berbeda, jadi klaim 540 km (CLTC) pada Wuling Darion EV tidak bisa dibandingkan langsung dengan klaim 461 km (NEDC) pada Jaecoo J5 EV. Keduanya juga hasil uji standar, bukan hasil di jalan raya Indonesia.&lt;/p&gt;

&lt;p&gt;OTR berarti on the road, harga yang sudah memasukkan biaya yang diperlukan agar mobil bisa dipakai di jalan, seperti pajak dan pengurusan surat. Harga OTR berbeda antar kota, dan sebagian besar harga di tulisan ini berlaku untuk Jakarta.&lt;/p&gt;

&lt;p&gt;Wholesales adalah jumlah kendaraan yang dikirim dari pabrikan ke dealer, sedangkan penjualan eceran (retail) adalah yang diserahkan ke pembeli akhir. Data Gaikindo yang dikutip media biasanya wholesales. SPK adalah surat pemesanan kendaraan. Harga promo sering berlaku untuk konsumen yang membuat SPK sebelum tanggal tertentu, seperti pada Geely EX2.&lt;/p&gt;

&lt;h2 id=&quot;pengisian-daya-di-indonesia&quot;&gt;Pengisian daya di Indonesia&lt;/h2&gt;

&lt;p&gt;Dua hal menentukan apakah mobil listrik cocok untukmu: kamu bisa mengisi di mana, dan berapa biayanya.&lt;/p&gt;

&lt;h3 id=&quot;di-rumah&quot;&gt;Di rumah&lt;/h3&gt;

&lt;p&gt;Pengisian di rumah semalaman adalah cara termurah, seperti terlihat di hitungan di bawah. Tarif listrik PLN untuk triwulan IV 2026 adalah Rp1.352 per kWh untuk golongan R-1 900 VA nonsubsidi, Rp1.444,70 per kWh untuk R-1 1.300 VA dan 2.200 VA, serta Rp1.699,53 per kWh untuk R-2 dan R-3 (&lt;a href=&quot;https://www.metrotvnews.com/read/NA0CzpEz-daftar-lengkap-tarif-listrik-pln-akhir-oktober-2026-per-kwh&quot;&gt;Metro TV, 29 Oktober 2026&lt;/a&gt;). Tarif bersubsidi untuk 900 VA, yaitu Rp605 per kWh, tidak saya pakai dalam hitungan.&lt;/p&gt;

&lt;p&gt;Contoh hitungan dengan BYD Atto 1 Premium, baterai 38,88 kWh (&lt;a href=&quot;https://listrikindonesia.com/detail/17430/mengupas-kapasitas-baterai-dan-jarak-tempuh-byd-atto-1&quot;&gt;Listrik Indonesia, 2 Agustus 2025&lt;/a&gt;), pelanggan R-1 1.300 VA:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Mengisi 38,88 kWh dari kosong sampai penuh: 38,88 × Rp1.444,70 = sekitar Rp56 ribu.&lt;/li&gt;
  &lt;li&gt;FuelEconomy.gov menyebut efisiensi pengisian baterai sering berada di 84% sampai 93% (&lt;a href=&quot;https://www.fueleconomy.gov/feg/evtech.shtml&quot;&gt;FuelEconomy.gov&lt;/a&gt;). Dengan rugi itu, listrik yang ditarik dari dinding menjadi sekitar 41,8 sampai 46,3 kWh, sehingga biayanya sekitar Rp60 ribu sampai Rp67 ribu.&lt;/li&gt;
  &lt;li&gt;Dengan klaim jarak 380 km, itu berarti sekitar Rp160 sampai Rp176 per kilometer. Jarak nyata biasanya lebih pendek, jadi biaya per kilometer nyata lebih tinggi.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ini hitungan kasar. Tarif berubah per triwulan, dan rugi pengisian bergantung pada suhu, charger, dan kondisi baterai.&lt;/p&gt;

&lt;p&gt;Satu syarat praktis: mengisi di rumah butuh daya terpasang yang cukup dan titik colok yang aman. Tanyakan ke dealer atau PLN soal instalasinya sebelum memutuskan.&lt;/p&gt;

&lt;h3 id=&quot;di-spklu-umum&quot;&gt;Di SPKLU umum&lt;/h3&gt;

&lt;p&gt;SPKLU adalah singkatan stasiun pengisian kendaraan listrik umum. Kontan melaporkan PLN bersama mitra mengoperasikan 4.655 unit SPKLU di 3.007 lokasi sepanjang 2025, naik sekitar 44% dari 3.223 unit pada 2024 (&lt;a href=&quot;https://industri.kontan.co.id/news/meningkat-44-pln-operasikan-4655-spklu-sepanjang-2025&quot;&gt;Kontan, 8 Februari 2026&lt;/a&gt;). Kenaikannya cepat, dan titik pengisian di rute antarkota tetap perlu kamu cek sebelum berangkat.&lt;/p&gt;

&lt;p&gt;Okezone menyebut tarif dasar di SPKLU berada di kisaran Rp1.650 sampai Rp2.475 per kWh menurut aturan terbaru yang berlaku, tanpa menyebut nomor aturannya, dan SPKLU di jalan tol umumnya memasang tarif sekitar Rp2.466 sampai Rp2.475 per kWh (&lt;a href=&quot;https://www.rctiplus.com/news/detail/okezone/5343306/segini-tarif-cas-mobil-listrik-di-spklu-tol-untuk-mudik-lebaran-2026&quot;&gt;Okezone lewat RCTI+, 18 Maret 2026&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Pengisian cepat DC dikenai biaya tambahan per sesi: maksimal Rp25.000 untuk charger 25 sampai 50 kW, dan maksimal Rp57.000 untuk charger di atas 50 kW. Artikel itu merujuk Keputusan Menteri ESDM Nomor 182.K/TL.04/MEM.S/2023 untuk batas biaya tambahan tersebut.&lt;/p&gt;

&lt;p&gt;Kembali ke contoh Atto 1 Premium: mengisi 38,88 kWh pada tarif Rp2.475 per kWh menghabiskan sekitar Rp96 ribu, belum termasuk rugi pengisian dan biaya tambahan sesi. Selisihnya terhadap pengisian rumah sekitar Rp29 ribu sampai Rp40 ribu per pengisian penuh. Karena itu pola yang paling hemat adalah rumah untuk pemakaian harian dan SPKLU untuk perjalanan jauh. Sebelum membeli, tanyakan juga ke dealer jenis konektor AC dan DC yang dipakai mobilnya, karena tidak semua mobil dan SPKLU memakai colokan yang sama.&lt;/p&gt;

&lt;h3 id=&quot;biaya-mengisi-penuh-untuk-tiap-model&quot;&gt;Biaya mengisi penuh untuk tiap model&lt;/h3&gt;

&lt;p&gt;Dengan kapasitas baterai tiap model dan dua tarif di atas, kita bisa menghitung biaya mengisi dari kosong sampai penuh. Tabel ini memakai tarif rumah Rp1.444,70 per kWh (R-1 1.300 VA) dan tarif SPKLU Rp2.475 per kWh, tanpa rugi pengisian dan tanpa biaya tambahan sesi.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Model&lt;/th&gt;
      &lt;th&gt;Baterai (kWh)&lt;/th&gt;
      &lt;th&gt;Isi penuh di rumah&lt;/th&gt;
      &lt;th&gt;Isi penuh di SPKLU&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;VinFast VF 3&lt;/td&gt;
      &lt;td&gt;18,64&lt;/td&gt;
      &lt;td&gt;sekitar Rp27 ribu&lt;/td&gt;
      &lt;td&gt;sekitar Rp46 ribu&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;BYD Atto 1 Dynamic&lt;/td&gt;
      &lt;td&gt;30,08&lt;/td&gt;
      &lt;td&gt;sekitar Rp43 ribu&lt;/td&gt;
      &lt;td&gt;sekitar Rp74 ribu&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;BYD Atto 1 Premium&lt;/td&gt;
      &lt;td&gt;38,88&lt;/td&gt;
      &lt;td&gt;sekitar Rp56 ribu&lt;/td&gt;
      &lt;td&gt;sekitar Rp96 ribu&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Geely EX2&lt;/td&gt;
      &lt;td&gt;40,8&lt;/td&gt;
      &lt;td&gt;sekitar Rp59 ribu&lt;/td&gt;
      &lt;td&gt;sekitar Rp101 ribu&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;BYD M6 Standard&lt;/td&gt;
      &lt;td&gt;58&lt;/td&gt;
      &lt;td&gt;sekitar Rp84 ribu&lt;/td&gt;
      &lt;td&gt;sekitar Rp144 ribu&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Geely EX5&lt;/td&gt;
      &lt;td&gt;60,22&lt;/td&gt;
      &lt;td&gt;sekitar Rp87 ribu&lt;/td&gt;
      &lt;td&gt;sekitar Rp149 ribu&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Jaecoo J5 EV&lt;/td&gt;
      &lt;td&gt;60,9&lt;/td&gt;
      &lt;td&gt;sekitar Rp88 ribu&lt;/td&gt;
      &lt;td&gt;sekitar Rp151 ribu&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;MG S5 EV Magnify Max&lt;/td&gt;
      &lt;td&gt;62&lt;/td&gt;
      &lt;td&gt;sekitar Rp90 ribu&lt;/td&gt;
      &lt;td&gt;sekitar Rp153 ribu&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Wuling Darion EV&lt;/td&gt;
      &lt;td&gt;69,2&lt;/td&gt;
      &lt;td&gt;sekitar Rp100 ribu&lt;/td&gt;
      &lt;td&gt;sekitar Rp171 ribu&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;BYD Sealion 7&lt;/td&gt;
      &lt;td&gt;sekitar 82,6&lt;/td&gt;
      &lt;td&gt;sekitar Rp119 ribu&lt;/td&gt;
      &lt;td&gt;sekitar Rp204 ribu&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Denza D9&lt;/td&gt;
      &lt;td&gt;103,36&lt;/td&gt;
      &lt;td&gt;sekitar Rp149 ribu&lt;/td&gt;
      &lt;td&gt;sekitar Rp256 ribu&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Kapasitas baterai tiap model berasal dari sumber di bagian masing-masing mobil di &lt;a href=&quot;/2026/11/04/mobil-listrik-10-model-terlaris-cara-memilih&quot;&gt;Bagian 3&lt;/a&gt;. Dua hal perlu dicatat. Pertama, kamu jarang perlu mengisi dari 0% sampai 100% setiap hari, jadi biaya per pengisian biasanya lebih kecil dari angka tabel.&lt;/p&gt;

&lt;p&gt;Kedua, biaya per kilometer lebih berguna dari biaya per pengisian. Dengan klaim jarak pabrikan, baterai penuh di rumah menghabiskan sekitar Rp145 sampai Rp150 per kilometer untuk BYD Atto 1 dan Geely EX2, sekitar Rp190 untuk Jaecoo J5 EV dan BYD M6 Standard, dan sekitar Rp250 untuk Denza D9.&lt;/p&gt;

&lt;p&gt;Di SPKLU, angkanya sekitar 1,7 kali lipat. Karena jarak nyata biasanya lebih pendek dari klaim, biaya nyata per kilometer lebih tinggi dari angka ini.&lt;/p&gt;

&lt;h2 id=&quot;berapa-harga-mobil-listrik-dan-kenapa-angkanya-berubah-ubah&quot;&gt;Berapa harga mobil listrik dan kenapa angkanya berubah-ubah&lt;/h2&gt;

&lt;p&gt;Harga mobil listrik di Indonesia berubah cepat, dan satu model bisa muncul dengan angka berbeda di dua artikel yang terbit pada bulan yang sama. Ada tiga penyebab.&lt;/p&gt;

&lt;p&gt;Pertama, insentif pajak. Insentif PPN ditanggung pemerintah (PPN DTP) untuk mobil listrik dan keringanan bea masuk untuk mobil impor utuh (CBU) tidak berlanjut pada 2026. Listrik Indonesia memperkirakan kenaikan harga sekitar 5% sampai 15% setelah insentif dicabut (&lt;a href=&quot;https://listrikindonesia.com/detail/19930/insentif-pajak-dihapus-kapan-waktu-yang-tepat-beli-mobil-listrik&quot;&gt;Listrik Indonesia, 1 Mei 2026&lt;/a&gt;). Perkiraan itu pendapat media, bukan angka resmi.&lt;/p&gt;

&lt;p&gt;Kedua, rencana pengganti yang berkali-kali tertunda. Pemerintah merencanakan PPN DTP dengan tarif 100% untuk mobil listrik berbaterai berbasis nikel (NMC) dan 40% untuk baterai non-nikel seperti LFP (&lt;a href=&quot;https://news.ddtc.co.id/berita/nasional/1820265/ppn-dtp-kendaraan-listrik-belum-dirilis-airlangga-masih-dikaji-ulang&quot;&gt;DDTCNews, 23 Juni 2026&lt;/a&gt;).&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Waktu&lt;/th&gt;
      &lt;th&gt;Peristiwa&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Rencana awal&lt;/td&gt;
      &lt;td&gt;Mulai pertengahan 2026&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;26 Mei 2026&lt;/td&gt;
      &lt;td&gt;Menteri Keuangan Purbaya menyatakan pelaksanaan ditunda untuk menunggu perhitungan&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;23 Juni 2026&lt;/td&gt;
      &lt;td&gt;Menko Perekonomian Airlangga Hartarto menyebut insentif masih dikaji&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Sumber kronologi: &lt;a href=&quot;https://news.ddtc.co.id/berita/nasional/1820265/ppn-dtp-kendaraan-listrik-belum-dirilis-airlangga-masih-dikaji-ulang&quot;&gt;DDTCNews, 23 Juni 2026&lt;/a&gt;. Status setelah tanggal itu perlu kamu cek sendiri ke Kementerian Keuangan atau dealer sebelum membeli.&lt;/p&gt;

&lt;p&gt;Ketiga, promo dan harga peluncuran. Beberapa model dijual dengan harga khusus untuk pembeli pertama, lalu naik:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Jaecoo J5 EV naik dari Rp249,9 juta menjadi Rp279,9 juta untuk varian terendahnya (&lt;a href=&quot;https://oto.detik.com/mobil/d-8682899/harga-jaecoo-j5-naik-tak-ada-lagi-yang-di-bawah-rp-250-juta&quot;&gt;detikOto, 28 September 2026&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;Wuling Darion EV dijual Rp356 juta (CE) untuk 1.500 pembeli pertama, lalu Rp399 juta pada September 2026 (&lt;a href=&quot;https://oto.detik.com/mobil-listrik/d-8197085/spesifikasi-wuling-darion-ada-varian-ev-dan-phev-harga-mulai-rp-356-juta&quot;&gt;detikOto&lt;/a&gt;; &lt;a href=&quot;https://otodriver.com/daftar-harga/2026/daftar-harga-wuling-terbaru-september-2026-dafefcff026&quot;&gt;Otodriver&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;Geely EX2 mulai dari Rp229,9 juta (Pro) pada masa peluncuran, lalu Rp239,9 juta (&lt;a href=&quot;https://www.carmudi.co.id/journal/harga-geely-ex2-setelah-resmi-meluncur-di-indonesia-mulai-segini/&quot;&gt;Carmudi&lt;/a&gt;; &lt;a href=&quot;https://moladin.com/news/harga-otr-geely-terbaru-september-2026/&quot;&gt;Moladin&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Karena itu, setiap harga di tulisan ini saya tandai dengan sumber dan tanggal. Sumbernya media dan agregator otomotif, bukan daftar harga resmi merek, jadi anggap semua harga sebagai acuan awal, bukan penawaran.&lt;/p&gt;</content><author><name>Mahyuddin Susanto</name></author><category term="Mobil" /><category term="Otomotif" /><category term="mobil listrik" /><category term="bev" /><category term="baterai" /><category term="spklu" /><category term="harga mobil listrik" /><summary type="html">Daftar isi bagian ini</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.udienz.web.id/img/mobil-listrik-pengertian-jenis-cara-kerja.jpg" /><media:content medium="image" url="https://www.udienz.web.id/img/mobil-listrik-pengertian-jenis-cara-kerja.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Mobil Listrik (3/3): 10 Model Terlaris dan Cara Memilih</title><link href="https://www.udienz.web.id/2026/11/04/mobil-listrik-10-model-terlaris-cara-memilih" rel="alternate" type="text/html" title="Mobil Listrik (3/3): 10 Model Terlaris dan Cara Memilih" /><published>2026-11-04T00:00:01+00:00</published><updated>2026-11-04T00:00:01+00:00</updated><id>https://www.udienz.web.id/2026/11/04/mobil-listrik-10-model-terlaris-cara-memilih</id><content type="html" xml:base="https://www.udienz.web.id/2026/11/04/mobil-listrik-10-model-terlaris-cara-memilih">&lt;details class=&quot;toc&quot;&gt;
  &lt;summary&gt;Daftar isi bagian ini&lt;/summary&gt;

&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#10-mobil-listrik-terlaris-di-indonesia&quot; id=&quot;markdown-toc-10-mobil-listrik-terlaris-di-indonesia&quot;&gt;10 mobil listrik terlaris di Indonesia&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#cara-saya-memilih-sepuluh-model-ini&quot; id=&quot;markdown-toc-cara-saya-memilih-sepuluh-model-ini&quot;&gt;Cara saya memilih sepuluh model ini&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#ringkasan-harga-baterai-dan-klaim-jarak&quot; id=&quot;markdown-toc-ringkasan-harga-baterai-dan-klaim-jarak&quot;&gt;Ringkasan: harga, baterai, dan klaim jarak&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#1-jaecoo-j5-ev&quot; id=&quot;markdown-toc-1-jaecoo-j5-ev&quot;&gt;1. Jaecoo J5 EV&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#2-byd-atto-1&quot; id=&quot;markdown-toc-2-byd-atto-1&quot;&gt;2. BYD Atto 1&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#3-geely-ex2&quot; id=&quot;markdown-toc-3-geely-ex2&quot;&gt;3. Geely EX2&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#4-byd-m6&quot; id=&quot;markdown-toc-4-byd-m6&quot;&gt;4. BYD M6&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#5-byd-sealion-7&quot; id=&quot;markdown-toc-5-byd-sealion-7&quot;&gt;5. BYD Sealion 7&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#6-wuling-darion-ev&quot; id=&quot;markdown-toc-6-wuling-darion-ev&quot;&gt;6. Wuling Darion EV&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#7-denza-d9&quot; id=&quot;markdown-toc-7-denza-d9&quot;&gt;7. Denza D9&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#8-mg-s5-ev&quot; id=&quot;markdown-toc-8-mg-s5-ev&quot;&gt;8. MG S5 EV&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#9-geely-ex5&quot; id=&quot;markdown-toc-9-geely-ex5&quot;&gt;9. Geely EX5&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#10-vinfast-vf-3&quot; id=&quot;markdown-toc-10-vinfast-vf-3&quot;&gt;10. VinFast VF 3&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#cara-memilih-mobil-listrik-yang-tepat&quot; id=&quot;markdown-toc-cara-memilih-mobil-listrik-yang-tepat&quot;&gt;Cara memilih mobil listrik yang tepat&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#berapa-jarak-harianmu&quot; id=&quot;markdown-toc-berapa-jarak-harianmu&quot;&gt;Berapa jarak harianmu?&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#bisakah-kamu-mengisi-di-rumah&quot; id=&quot;markdown-toc-bisakah-kamu-mengisi-di-rumah&quot;&gt;Bisakah kamu mengisi di rumah?&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#seberapa-jauh-kamu-percaya-angka-klaim&quot; id=&quot;markdown-toc-seberapa-jauh-kamu-percaya-angka-klaim&quot;&gt;Seberapa jauh kamu percaya angka klaim?&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#kapan-mobil-listrik-belum-cocok&quot; id=&quot;markdown-toc-kapan-mobil-listrik-belum-cocok&quot;&gt;Kapan mobil listrik belum cocok?&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#bagaimana-dengan-umur-baterai&quot; id=&quot;markdown-toc-bagaimana-dengan-umur-baterai&quot;&gt;Bagaimana dengan umur baterai?&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#pertanyaan-yang-sering-muncul&quot; id=&quot;markdown-toc-pertanyaan-yang-sering-muncul&quot;&gt;Pertanyaan yang sering muncul&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#berapa-lama-mengisi-mobil-listrik-sampai-penuh&quot; id=&quot;markdown-toc-berapa-lama-mengisi-mobil-listrik-sampai-penuh&quot;&gt;Berapa lama mengisi mobil listrik sampai penuh?&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#berapa-biaya-mengisi-mobil-listrik&quot; id=&quot;markdown-toc-berapa-biaya-mengisi-mobil-listrik&quot;&gt;Berapa biaya mengisi mobil listrik?&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#apakah-hybrid-termasuk-mobil-listrik&quot; id=&quot;markdown-toc-apakah-hybrid-termasuk-mobil-listrik&quot;&gt;Apakah hybrid termasuk mobil listrik?&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#apakah-insentif-pajak-mobil-listrik-masih-ada&quot; id=&quot;markdown-toc-apakah-insentif-pajak-mobil-listrik-masih-ada&quot;&gt;Apakah insentif pajak mobil listrik masih ada?&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#apakah-mobil-listrik-bisa-dipakai-mudik&quot; id=&quot;markdown-toc-apakah-mobil-listrik-bisa-dipakai-mudik&quot;&gt;Apakah mobil listrik bisa dipakai mudik?&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#penutup&quot; id=&quot;markdown-toc-penutup&quot;&gt;Penutup&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#tentang-tulisan-ini&quot; id=&quot;markdown-toc-tentang-tulisan-ini&quot;&gt;Tentang tulisan ini&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#sumber-utama&quot; id=&quot;markdown-toc-sumber-utama&quot;&gt;Sumber utama&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/details&gt;

&lt;h2 id=&quot;10-mobil-listrik-terlaris-di-indonesia&quot;&gt;10 mobil listrik terlaris di Indonesia&lt;/h2&gt;

&lt;h3 id=&quot;cara-saya-memilih-sepuluh-model-ini&quot;&gt;Cara saya memilih sepuluh model ini&lt;/h3&gt;

&lt;p&gt;“Populer” bisa diartikan banyak hal. Saya memakai ukuran yang bisa diperiksa: jumlah unit yang tercatat menurut Gaikindo pada periode Januari sampai September 2026, sebagaimana dilaporkan Kontan pada 12 Oktober 2026 (&lt;a href=&quot;https://industri.kontan.co.id/news/10-mobil-listrik-terlaris-di-indonesia-hingga-september-2026&quot;&gt;Kontan&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Angka Gaikindo adalah angka distribusi dari pabrik ke dealer (wholesales), bukan penjualan eceran ke konsumen akhir. GoodStats menjelaskan istilah itu sebagai “jumlah kendaraan yang dikirim dari pabrikan ke dealer” (&lt;a href=&quot;https://data.goodstats.id/statistic/10-mobil-listrik-terlaris-semester-i-2026-jaecoo-j5-di-puncak-dRODE&quot;&gt;GoodStats, 23 Juli 2026&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Jadi urutan di bawah mencerminkan pengiriman ke dealer, yang biasanya sejalan dengan pembelian tetapi tidak persis sama.&lt;/p&gt;

&lt;p&gt;Total sepuluh model ini 89.502 unit pada sembilan bulan pertama 2026. Grafik di bawah menunjukkan sebaran per model.&lt;/p&gt;

&lt;figure class=&quot;blog-chart&quot;&gt;
&lt;svg viewBox=&quot;0 0 400 396&quot; width=&quot;400&quot; height=&quot;396&quot; role=&quot;img&quot; aria-label=&quot;Diagram batang penjualan wholesales sepuluh mobil listrik terlaris di Indonesia, Januari sampai September 2026, data Gaikindo via Kontan. Jaecoo J5 EV 26.635 unit, BYD Atto 1 24.749 unit, Geely EX2 11.659 unit, BYD M6 7.043 unit, BYD Sealion 7 4.266 unit, Wuling Darion EV 4.020 unit, Denza D9 3.009 unit, MG S5 EV 2.914 unit, Geely EX5 2.760 unit, VinFast VF 3 2.447 unit.&quot;&gt;
&lt;text x=&quot;200&quot; y=&quot;24&quot; text-anchor=&quot;middle&quot; font-size=&quot;16&quot; fill=&quot;currentColor&quot;&gt;Penjualan 10 mobil listrik terlaris (unit)&lt;/text&gt;
&lt;text x=&quot;200&quot; y=&quot;45&quot; text-anchor=&quot;middle&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;Januari sampai September 2026, wholesales Gaikindo&lt;/text&gt;
&lt;line x1=&quot;130&quot; y1=&quot;58&quot; x2=&quot;130&quot; y2=&quot;378&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;122&quot; y=&quot;80&quot; text-anchor=&quot;end&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;Jaecoo J5 EV&lt;/text&gt;
&lt;rect x=&quot;130&quot; y=&quot;64&quot; width=&quot;190.0&quot; height=&quot;22&quot; rx=&quot;4&quot; fill=&quot;#f97316&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;326.0&quot; y=&quot;80&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;26.635&lt;/text&gt;
&lt;text x=&quot;122&quot; y=&quot;112&quot; text-anchor=&quot;end&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;BYD Atto 1&lt;/text&gt;
&lt;rect x=&quot;130&quot; y=&quot;96&quot; width=&quot;176.5&quot; height=&quot;22&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;312.5&quot; y=&quot;112&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;24.749&lt;/text&gt;
&lt;text x=&quot;122&quot; y=&quot;144&quot; text-anchor=&quot;end&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;Geely EX2&lt;/text&gt;
&lt;rect x=&quot;130&quot; y=&quot;128&quot; width=&quot;83.2&quot; height=&quot;22&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;219.2&quot; y=&quot;144&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;11.659&lt;/text&gt;
&lt;text x=&quot;122&quot; y=&quot;176&quot; text-anchor=&quot;end&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;BYD M6&lt;/text&gt;
&lt;rect x=&quot;130&quot; y=&quot;160&quot; width=&quot;50.2&quot; height=&quot;22&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;186.2&quot; y=&quot;176&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;7.043&lt;/text&gt;
&lt;text x=&quot;122&quot; y=&quot;208&quot; text-anchor=&quot;end&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;BYD Sealion 7&lt;/text&gt;
&lt;rect x=&quot;130&quot; y=&quot;192&quot; width=&quot;30.4&quot; height=&quot;22&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;166.4&quot; y=&quot;208&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;4.266&lt;/text&gt;
&lt;text x=&quot;122&quot; y=&quot;240&quot; text-anchor=&quot;end&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;Wuling Darion EV&lt;/text&gt;
&lt;rect x=&quot;130&quot; y=&quot;224&quot; width=&quot;28.7&quot; height=&quot;22&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;164.7&quot; y=&quot;240&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;4.020&lt;/text&gt;
&lt;text x=&quot;122&quot; y=&quot;272&quot; text-anchor=&quot;end&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;Denza D9&lt;/text&gt;
&lt;rect x=&quot;130&quot; y=&quot;256&quot; width=&quot;21.5&quot; height=&quot;22&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;157.5&quot; y=&quot;272&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;3.009&lt;/text&gt;
&lt;text x=&quot;122&quot; y=&quot;304&quot; text-anchor=&quot;end&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;MG S5 EV&lt;/text&gt;
&lt;rect x=&quot;130&quot; y=&quot;288&quot; width=&quot;20.8&quot; height=&quot;22&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;156.8&quot; y=&quot;304&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;2.914&lt;/text&gt;
&lt;text x=&quot;122&quot; y=&quot;336&quot; text-anchor=&quot;end&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;Geely EX5&lt;/text&gt;
&lt;rect x=&quot;130&quot; y=&quot;320&quot; width=&quot;19.7&quot; height=&quot;22&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;155.7&quot; y=&quot;336&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;2.760&lt;/text&gt;
&lt;text x=&quot;122&quot; y=&quot;368&quot; text-anchor=&quot;end&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;VinFast VF 3&lt;/text&gt;
&lt;rect x=&quot;130&quot; y=&quot;352&quot; width=&quot;17.5&quot; height=&quot;22&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;153.5&quot; y=&quot;368&quot; font-size=&quot;13&quot; fill=&quot;currentColor&quot;&gt;2.447&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption&gt;Sumber: &lt;a href=&quot;https://industri.kontan.co.id/news/10-mobil-listrik-terlaris-di-indonesia-hingga-september-2026&quot;&gt;Kontan&lt;/a&gt;, 12 Oktober 2026, mengutip data Gaikindo. Angka wholesales, yaitu pengiriman pabrikan ke dealer. Batang oranye: peringkat pertama.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Daftar ini bisa berubah menurut periode. Pada data semester I 2026 (Januari sampai Juni), GAC Aion V dan Wuling Eksion masuk sepuluh besar, sedangkan MG S5 EV dan VinFast VF 3 belum (&lt;a href=&quot;https://data.goodstats.id/statistic/10-mobil-listrik-terlaris-semester-i-2026-jaecoo-j5-di-puncak-dRODE&quot;&gt;GoodStats&lt;/a&gt;). Mobil di peringkat 1 sampai 7 sama di kedua periode (&lt;a href=&quot;https://data.goodstats.id/statistic/10-mobil-listrik-terlaris-semester-i-2026-jaecoo-j5-di-puncak-dRODE&quot;&gt;GoodStats&lt;/a&gt;; &lt;a href=&quot;https://industri.kontan.co.id/news/10-mobil-listrik-terlaris-di-indonesia-hingga-september-2026&quot;&gt;Kontan&lt;/a&gt;), dengan urutan yang konsisten.&lt;/p&gt;

&lt;h3 id=&quot;ringkasan-harga-baterai-dan-klaim-jarak&quot;&gt;Ringkasan: harga, baterai, dan klaim jarak&lt;/h3&gt;

&lt;p&gt;Harga di tabel berikut dalam rupiah, umumnya OTR Jakarta, dan sumber tiap angka ada di bagian masing-masing model. Klaim jarak tempuh berasal dari pabrikan berdasarkan siklus uji NEDC, kecuali ada keterangan lain.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;#&lt;/th&gt;
      &lt;th&gt;Model&lt;/th&gt;
      &lt;th&gt;Harga (jutaan Rp)&lt;/th&gt;
      &lt;th&gt;Baterai&lt;/th&gt;
      &lt;th&gt;Klaim jarak&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;/td&gt;
      &lt;td&gt;Jaecoo J5 EV&lt;/td&gt;
      &lt;td&gt;279,9 (Standard) sampai 324,9 (Premium)&lt;/td&gt;
      &lt;td&gt;60,9 kWh&lt;/td&gt;
      &lt;td&gt;461 km&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;/td&gt;
      &lt;td&gt;BYD Atto 1&lt;/td&gt;
      &lt;td&gt;199 sampai 245&lt;/td&gt;
      &lt;td&gt;30,08 sampai 38,88 kWh&lt;/td&gt;
      &lt;td&gt;300 sampai 380 km&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;/td&gt;
      &lt;td&gt;Geely EX2&lt;/td&gt;
      &lt;td&gt;239,9 (Pro) sampai 269,9 (Max)&lt;/td&gt;
      &lt;td&gt;40,8 kWh LFP&lt;/td&gt;
      &lt;td&gt;395 km&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;BYD M6&lt;/td&gt;
      &lt;td&gt;395 sampai 445&lt;/td&gt;
      &lt;td&gt;58 kWh (Standard)&lt;/td&gt;
      &lt;td&gt;hingga 450 km (Standard)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;/td&gt;
      &lt;td&gt;BYD Sealion 7&lt;/td&gt;
      &lt;td&gt;629 sampai 719 (harga tercantum, ketersediaan perlu dicek)&lt;/td&gt;
      &lt;td&gt;sekitar 82,6 kWh&lt;/td&gt;
      &lt;td&gt;542 sampai 567 km&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;6&lt;/td&gt;
      &lt;td&gt;Wuling Darion EV&lt;/td&gt;
      &lt;td&gt;399 (CE) sampai 459 (EX)&lt;/td&gt;
      &lt;td&gt;69,2 kWh LFP&lt;/td&gt;
      &lt;td&gt;540 km (CLTC)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;7&lt;/td&gt;
      &lt;td&gt;Denza D9&lt;/td&gt;
      &lt;td&gt;950&lt;/td&gt;
      &lt;td&gt;103,36 kWh&lt;/td&gt;
      &lt;td&gt;600 km&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;8&lt;/td&gt;
      &lt;td&gt;MG S5 EV&lt;/td&gt;
      &lt;td&gt;333,9 (harga khusus awal) sampai 410,9&lt;/td&gt;
      &lt;td&gt;62 kWh (Magnify Max)&lt;/td&gt;
      &lt;td&gt;410 sampai 545 km&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;9&lt;/td&gt;
      &lt;td&gt;Geely EX5&lt;/td&gt;
      &lt;td&gt;465 sampai 515&lt;/td&gt;
      &lt;td&gt;60,22 kWh&lt;/td&gt;
      &lt;td&gt;490 sampai 495 km&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;10&lt;/td&gt;
      &lt;td&gt;VinFast VF 3&lt;/td&gt;
      &lt;td&gt;152 (sewa baterai) sampai 215&lt;/td&gt;
      &lt;td&gt;18,64 kWh&lt;/td&gt;
      &lt;td&gt;210 km&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Berikut penjelasan tiap model.&lt;/p&gt;

&lt;h3 id=&quot;1-jaecoo-j5-ev&quot;&gt;1. Jaecoo J5 EV&lt;/h3&gt;

&lt;p&gt;Jaecoo J5 EV memimpin penjualan kumulatif dengan 26.635 unit pada Januari sampai September 2026, dan tercatat 3.276 unit pada September saja (&lt;a href=&quot;https://industri.kontan.co.id/news/10-mobil-listrik-terlaris-di-indonesia-hingga-september-2026&quot;&gt;Kontan&lt;/a&gt;; &lt;a href=&quot;https://www.gaikindo.or.id/20-model-mobil-terlaris-september-2026-atto-1-menempel-gran-max/&quot;&gt;Gaikindo&lt;/a&gt;). J5 EV unggul secara kumulatif, sedangkan pada September BYD Atto 1 tercatat lebih banyak dalam sebulan, yaitu 4.840 berbanding 3.276 unit.&lt;/p&gt;

&lt;p&gt;Harga per akhir September 2026 adalah Rp279,9 juta untuk Standard dan Rp324,9 juta untuk Premium, tercantum di situs resmi Jaecoo Indonesia (&lt;a href=&quot;https://oto.detik.com/mobil/d-8682899/harga-jaecoo-j5-naik-tak-ada-lagi-yang-di-bawah-rp-250-juta&quot;&gt;detikOto, 28 September 2026&lt;/a&gt;). Sebelumnya harganya Rp249,9 juta dan Rp299,9 juta. Menurut detikOto, per September 2026 tidak ada lagi J5 yang dijual di bawah Rp250 juta.&lt;/p&gt;

&lt;p&gt;Spesifikasinya: baterai 60,9 kWh, klaim 461 km (NEDC), motor 155 kW, dan pengisian DC sampai 130 kW dengan 30% ke 80% dalam 28 menit (&lt;a href=&quot;https://oto.detik.com/mobil-listrik/d-8182231/harga-resmi-jaecoo-j5-ev-diumumkan-3-november-ini-bocoran-spesifikasinya&quot;&gt;detikOto, 28 Oktober 2025&lt;/a&gt;). Standard dan Premium memakai motor dan baterai yang sama, dan selisihnya ada di fitur (&lt;a href=&quot;https://listrikindonesia.com/detail/17505/membedah-perbedaan-fitur-jaecoo-j5-ev-standard-vs-premium&quot;&gt;Listrik Indonesia, 10 Agustus 2025&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Dari tiga model terlaris, J5 EV punya klaim jarak terpanjang, dengan harga yang juga paling tinggi.&lt;/p&gt;

&lt;h3 id=&quot;2-byd-atto-1&quot;&gt;2. BYD Atto 1&lt;/h3&gt;

&lt;p&gt;BYD Atto 1 mencatat 24.749 unit pada sembilan bulan pertama 2026 dan 4.840 unit pada September, angka bulanan tertinggi di antara semua mobil listrik pada bulan itu.&lt;/p&gt;

&lt;p&gt;Daftar harga BYD edisi September 2026 mencantumkan tiga varian: Standard Rp199 juta, Dynamic Rp210 juta, dan Premium Rp245 juta (&lt;a href=&quot;https://otodriver.com/daftar-harga/2026/daftar-harga-byd-terbaru-september-2026-dafefdaa026&quot;&gt;Otodriver, 15 September 2026&lt;/a&gt;). Moladin pada 8 September 2026 mencatat angka yang sama (&lt;a href=&quot;https://moladin.com/news/daftar-mobil-listrik-termurah-september-2026/?show_all=1&quot;&gt;Moladin&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Varian Dynamic memakai baterai 30,08 kWh dengan klaim 300 km (NEDC), dan Premium memakai 38,88 kWh dengan klaim 380 km (&lt;a href=&quot;https://listrikindonesia.com/detail/17430/mengupas-kapasitas-baterai-dan-jarak-tempuh-byd-atto-1&quot;&gt;Listrik Indonesia, 2 Agustus 2025&lt;/a&gt;). Selisih harga Dynamic ke Premium Rp35 juta membeli baterai lebih besar dan fitur tambahan.&lt;/p&gt;

&lt;h3 id=&quot;3-geely-ex2&quot;&gt;3. Geely EX2&lt;/h3&gt;

&lt;p&gt;Geely EX2 tercatat 11.659 unit pada Januari sampai September 2026 dan 1.890 unit pada September, peringkat ke-15 dalam daftar semua model Gaikindo bulan itu (&lt;a href=&quot;https://www.gaikindo.or.id/20-model-mobil-terlaris-september-2026-atto-1-menempel-gran-max/&quot;&gt;Gaikindo&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Menurut Moladin edisi 2 September 2026, EX2 Pro Rp239,9 juta dan EX2 Max Rp269,9 juta OTR Jakarta (&lt;a href=&quot;https://moladin.com/news/harga-otr-geely-terbaru-september-2026/&quot;&gt;Moladin&lt;/a&gt;). Pada masa peluncuran, Geely menawarkan harga khusus Rp229,9 juta untuk Pro dan Rp259,9 juta untuk Max bagi pemesan sampai 15 Februari 2026 atau 2.000 konsumen pertama, dengan harga normal Rp255 juta dan Rp285 juta OTR Jakarta (&lt;a href=&quot;https://www.carmudi.co.id/journal/harga-geely-ex2-setelah-resmi-meluncur-di-indonesia-mulai-segini/&quot;&gt;Carmudi&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Baterainya 40,8 kWh LFP, klaim 395 km (NEDC), dan motornya 85 kW (&lt;a href=&quot;https://www.carmudi.co.id/journal/harga-geely-ex2-setelah-resmi-meluncur-di-indonesia-mulai-segini/&quot;&gt;Carmudi, 21 Januari 2026&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Dalam uji Carmudi sejauh sekitar 100 km dari Jakarta ke kawasan Cibodas dan Puncak, konsumsinya rata-rata 18,1 kWh per 100 km dengan mode Sport dan Comfort, dan baterai berkurang 49% (&lt;a href=&quot;https://www.carmudi.co.id/journal/test-drive-jakarta-cianjur-berapa-konsumsi-listrik-dan-daya-geely-ex2/&quot;&gt;Carmudi, 3 Februari 2026&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Baterai yang berkurang 49% untuk sekitar 100 km setara jarak sekitar 205 km per pengisian penuh, dan konsumsi 18,1 kWh per 100 km dengan baterai 40,8 kWh setara sekitar 225 km, jadi hasilnya sekitar 205 sampai 225 km. Ini hitungan saya dari satu uji jalan, bukan angka resmi, tetapi memberi gambaran bahwa jarak nyata di rute itu jauh dari klaim 395 km. Untuk mobil kota yang jarang melewati rute seperti itu, selisihnya lebih kecil.&lt;/p&gt;

&lt;h3 id=&quot;4-byd-m6&quot;&gt;4. BYD M6&lt;/h3&gt;

&lt;p&gt;BYD M6 adalah MPV listrik BYD dan tercatat 7.043 unit pada Januari sampai September 2026.&lt;/p&gt;

&lt;p&gt;Daftar harga BYD September 2026: Standard Rp395 juta, Superior Rp435 juta, dan Superior Captain Seat Rp445 juta (&lt;a href=&quot;https://otodriver.com/daftar-harga/2026/daftar-harga-byd-terbaru-september-2026-dafefdaa026&quot;&gt;Otodriver, 15 September 2026&lt;/a&gt;). Varian Standard pada 2026 mendapat baterai Blade 58 kWh dengan klaim sampai 450 km, dan tersedia dengan susunan enam atau tujuh kursi (&lt;a href=&quot;https://www.carmudi.co.id/journal/harga-rp395-juta-ini-pembaruan-byd-m6-ev-2026-varian-standard-di-giias-2026/&quot;&gt;Carmudi, 31 Juli 2026&lt;/a&gt;).&lt;/p&gt;

&lt;h3 id=&quot;5-byd-sealion-7&quot;&gt;5. BYD Sealion 7&lt;/h3&gt;

&lt;p&gt;BYD Sealion 7 tercatat 4.266 unit pada Januari sampai September 2026. Harga yang tercantum untuk Sealion 7 adalah Rp629 juta untuk Premium dan Rp719 juta untuk Performance (&lt;a href=&quot;https://www.zigwheels.co.id/en/mobil-baru/byd/sealion-7/harga/&quot;&gt;Zigwheels, dibuka 4 November 2026&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Ada catatan penting soal ketersediaan. Otodriver pada September 2026 mencatat bahwa Sealion 7 tidak lagi tampil di situs resmi BYD Indonesia (&lt;a href=&quot;https://otodriver.com/daftar-harga/2026/daftar-harga-byd-terbaru-september-2026-dafefdaa026&quot;&gt;Otodriver, 15 September 2026&lt;/a&gt;). Per 4 November 2026, halaman model BYD Indonesia memang hanya menampilkan Seal, Atto 3, M6 DM, M6, dan Atto 1 (&lt;a href=&quot;https://www.byd.com/id&quot;&gt;BYD Indonesia&lt;/a&gt;). Alasannya tidak dijelaskan di sumber mana pun yang dikutip di sini. Kalau kamu mengincar Sealion 7, tanyakan stok dan harga terkini langsung ke dealer.&lt;/p&gt;

&lt;p&gt;Spesifikasinya: baterai Blade sekitar 82,6 kWh, klaim 567 km untuk Premium dan 542 km untuk Performance (NEDC), dan Performance berpenggerak semua roda dengan tenaga 523 hp (&lt;a href=&quot;https://www.carmudi.co.id/journal/spesifikasi-byd-sealion-7-sanggup-tempuh-567-km-sekali-cas/&quot;&gt;Carmudi, 16 Februari 2025&lt;/a&gt;).&lt;/p&gt;

&lt;h3 id=&quot;6-wuling-darion-ev&quot;&gt;6. Wuling Darion EV&lt;/h3&gt;

&lt;p&gt;Wuling Darion EV tercatat 4.020 unit pada sembilan bulan pertama 2026. Daftar harga Wuling edisi September 2026 mencantumkan CE Rp399 juta dan EX Rp459 juta OTR Jakarta (&lt;a href=&quot;https://otodriver.com/daftar-harga/2026/daftar-harga-wuling-terbaru-september-2026-dafefcff026&quot;&gt;Otodriver&lt;/a&gt;). Harga peluncurannya Rp356 juta untuk CE dan Rp416 juta untuk EX bagi 1.500 pembeli pertama.&lt;/p&gt;

&lt;p&gt;Baterainya LFP 69,2 kWh, klaim 540 km berdasarkan siklus CLTC, motor 150 kW penggerak roda depan, dan susunan tujuh kursi (&lt;a href=&quot;https://oto.detik.com/mobil-listrik/d-8197085/spesifikasi-wuling-darion-ada-varian-ev-dan-phev-harga-mulai-rp-356-juta&quot;&gt;detikOto, 6 November 2025&lt;/a&gt;). CLTC dan NEDC memakai pola uji yang berbeda, jadi jangan bandingkan 540 km ini langsung dengan angka NEDC mobil lain di daftar.&lt;/p&gt;

&lt;h3 id=&quot;7-denza-d9&quot;&gt;7. Denza D9&lt;/h3&gt;

&lt;p&gt;Denza D9 tercatat 3.009 unit pada Januari sampai September 2026, dan merupakan satu-satunya model berharga di atas Rp900 juta di daftar ini. Harganya Rp950 juta untuk varian FWD (&lt;a href=&quot;https://otodriver.com/daftar-harga/2026/daftar-harga-byd-terbaru-september-2026-dafefdaa026&quot;&gt;Otodriver, 15 September 2026&lt;/a&gt;), sama dengan harga peluncurannya, Rp950 juta OTR Jakarta (&lt;a href=&quot;https://listrikindonesia.com/detail/15468/harganya-bikin-alphard-ketar-ketir-ini-spesifikasi-byd-denza-d9&quot;&gt;Listrik Indonesia, 24 Januari 2025&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Baterainya 103,36 kWh dengan klaim 600 km dan motor tunggal 308 dk, dalam susunan kursi 2+2+3 atau 2+3+3, menurut artikel peluncuran Listrik Indonesia yang sama. Artikel itu menyebut siklus ujinya “NDC”, jadi bandingkan klaim ini dengan hati-hati. Media otomotif sering menempatkannya sebagai alternatif listrik untuk MPV mewah seperti Toyota Alphard.&lt;/p&gt;

&lt;h3 id=&quot;8-mg-s5-ev&quot;&gt;8. MG S5 EV&lt;/h3&gt;

&lt;p&gt;MG S5 EV tercatat 2.914 unit pada sembilan bulan pertama 2026. Harganya berubah beberapa kali sepanjang tahun, jadi saya susun jejaknya dalam satu tabel (OTR Jakarta).&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Waktu&lt;/th&gt;
      &lt;th&gt;Ignite&lt;/th&gt;
      &lt;th&gt;Magnify&lt;/th&gt;
      &lt;th&gt;Magnify Max&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Peluncuran, Februari 2026&lt;/td&gt;
      &lt;td&gt;Rp357,9 juta&lt;/td&gt;
      &lt;td&gt;Rp374,9 juta&lt;/td&gt;
      &lt;td&gt;Rp455,9 juta&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Harga khusus 1.500 pembeli pertama&lt;/td&gt;
      &lt;td&gt;Rp333,9 juta&lt;/td&gt;
      &lt;td&gt;Rp355,9 juta&lt;/td&gt;
      &lt;td&gt;tidak disebut&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Juli 2026&lt;/td&gt;
      &lt;td&gt;Rp333,9 juta&lt;/td&gt;
      &lt;td&gt;Rp355,9 juta&lt;/td&gt;
      &lt;td&gt;Rp399,9 juta sampai akhir September 2026, dari Rp410,9 juta&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Sumber: &lt;a href=&quot;https://www.kabarbursa.com/otomotif/mg-s5-ev-resmi-meluncur-di-iims-2026-harga-mulai-rp3339-juta.md&quot;&gt;Kabarbursa, 6 Februari 2026&lt;/a&gt; dan &lt;a href=&quot;https://www.kabarbursa.com/otomotif/mg-potong-harga-s5-ev-jadi-rp3999-juta-sekaligus-pamer-suv-hybrid-baru.md&quot;&gt;Kabarbursa, 17 Juli 2026&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Promo Magnify Max sudah berakhir pada akhir September, jadi Rp410,9 juta lebih aman dipakai. Angka itu lebih rendah dari Rp455,9 juta saat peluncuran, dan artikelnya tidak menjelaskan alasannya. Ignite dan Magnify masih tertulis Rp333,9 juta dan Rp355,9 juta pada Juli, padahal itu harga khusus 1.500 pembeli pertama, jadi tanyakan apakah harga itu masih berlaku.&lt;/p&gt;

&lt;p&gt;Klaim jarak Ignite sampai 415 km dan Magnify sampai 410 km. Magnify Max memakai baterai 62 kWh dengan motor 201,2 HP dan klaim 545 km (NEDC), menurut artikel Juli yang sama. Artikel peluncuran mencatat garansi baterai 8 tahun atau 160.000 km.&lt;/p&gt;

&lt;h3 id=&quot;9-geely-ex5&quot;&gt;9. Geely EX5&lt;/h3&gt;

&lt;p&gt;Geely EX5 tercatat 2.760 unit pada Januari sampai September 2026. Harga OTR Jakarta menurut Moladin edisi 2 September 2026: Pro Rp465 juta sampai Rp475 juta dan Max Rp505 juta sampai Rp515 juta, tergantung apakah harga khusus masih berlaku (&lt;a href=&quot;https://moladin.com/news/harga-otr-geely-terbaru-september-2026/&quot;&gt;Moladin&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Baterainya 60,22 kWh (short blade), klaim 495 km untuk Pro dan 490 km untuk Max (NEDC), dengan pengisian cepat 30% ke 80% dalam 20 menit dan daya tahan lebih dari 3.500 siklus pengisian menurut klaim (&lt;a href=&quot;https://www.idxchannel.com/technology/hadir-kembali-di-pasar-otomotif-ri-geely-hadirkan-mobil-listrik-dengan-segudang-teknologi&quot;&gt;IDX Channel, 22 Februari 2025&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Uji jalan Carmudi pada Mei 2025 dari Jakarta ke Bandung sejauh sekitar 154 km dengan tiga penumpang dan bagasi, kecepatan rata-rata sekitar 80 km/jam di tol, menghasilkan konsumsi 19,4 kWh per 100 km (&lt;a href=&quot;https://www.carmudi.co.id/journal/test-drive-jakarta-bandung-segini-konsumsi-daya-geely-ex5/&quot;&gt;Carmudi, 20 Mei 2025&lt;/a&gt;). Dengan baterai 60,22 kWh, itu setara sekitar 310 km per pengisian penuh, jauh di bawah klaim 490 sampai 495 km. Hitungan itu dari saya dan hanya berlaku untuk kondisi uji tersebut.&lt;/p&gt;

&lt;h3 id=&quot;10-vinfast-vf-3&quot;&gt;10. VinFast VF 3&lt;/h3&gt;

&lt;p&gt;VinFast VF 3 tercatat 2.447 unit pada Januari sampai September 2026. Moladin pada 8 September 2026 mencatat dua harga: Rp152 juta dengan skema sewa baterai dan Rp215 juta di luar skema sewa (&lt;a href=&quot;https://moladin.com/news/daftar-mobil-listrik-termurah-september-2026/?show_all=1&quot;&gt;Moladin&lt;/a&gt;). Halaman yang sama menampilkan kisaran Rp156 juta sampai Rp230,1 juta pada widget harga, jadi cek ulang angkanya ke dealer.&lt;/p&gt;

&lt;p&gt;Dengan sewa baterai, kamu membayar harga mobil yang lebih rendah, tetapi ada biaya sewa baterai berkala dan baterai tidak otomatis menjadi milikmu. Hitung total biaya selama tiga sampai lima tahun sebelum memilih skema.&lt;/p&gt;

&lt;p&gt;Spesifikasinya: baterai 18,64 kWh, klaim 210 km (NEDC), dan motor 32 kW (&lt;a href=&quot;https://listrikindonesia.com/detail/15531/siap-ramaikan-pasar-ev-indonesia-ini-spesifikasi-vf-3&quot;&gt;Listrik Indonesia, 31 Januari 2025&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id=&quot;cara-memilih-mobil-listrik-yang-tepat&quot;&gt;Cara memilih mobil listrik yang tepat&lt;/h2&gt;

&lt;p&gt;Daftar di atas mengurutkan model berdasarkan penjualan, bukan kecocokan. Tabel berikut mengelompokkannya menurut kebutuhan, memakai harga dan klaim yang sudah dibahas di atas. Angkanya tetap angka klaim dan harga September 2026, jadi cek ulang sebelum memutuskan.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Kebutuhan&lt;/th&gt;
      &lt;th&gt;Model yang layak dilihat&lt;/th&gt;
      &lt;th&gt;Dasar pertimbangan&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Harga masuk termurah&lt;/td&gt;
      &lt;td&gt;VinFast VF 3, BYD Atto 1&lt;/td&gt;
      &lt;td&gt;VF 3 mulai Rp152 juta dengan sewa baterai (klaim 210 km); Atto 1 Dynamic Rp210 juta (klaim 300 km)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Mobil kota dengan jarak menengah&lt;/td&gt;
      &lt;td&gt;Geely EX2, BYD Atto 1 Premium&lt;/td&gt;
      &lt;td&gt;EX2 Pro Rp239,9 juta (klaim 395 km); Atto 1 Premium Rp245 juta (klaim 380 km)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Klaim jarak terpanjang di bawah Rp350 juta&lt;/td&gt;
      &lt;td&gt;Jaecoo J5 EV&lt;/td&gt;
      &lt;td&gt;Standard Rp279,9 juta dengan klaim 461 km; MG S5 EV Ignite Rp333,9 juta (harga khusus awal, cek) dengan klaim 415 km&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Keluarga enam atau tujuh kursi&lt;/td&gt;
      &lt;td&gt;BYD M6, Wuling Darion EV&lt;/td&gt;
      &lt;td&gt;M6 Standard Rp395 juta (klaim 450 km); Darion EV CE Rp399 juta (klaim 540 km, siklus CLTC)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Pengisian cepat yang diklaim singkat&lt;/td&gt;
      &lt;td&gt;Geely EX5, Jaecoo J5 EV&lt;/td&gt;
      &lt;td&gt;EX5 mengklaim 20 menit untuk 30% ke 80%, J5 EV 28 menit&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Segmen premium&lt;/td&gt;
      &lt;td&gt;BYD Sealion 7, Denza D9&lt;/td&gt;
      &lt;td&gt;Sealion 7 Rp629 juta sampai Rp719 juta (ketersediaan perlu dicek); D9 Rp950 juta dengan klaim 600 km&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Lima pertanyaan berikut lebih menentukan daripada peringkat penjualan.&lt;/p&gt;

&lt;h3 id=&quot;berapa-jarak-harianmu&quot;&gt;Berapa jarak harianmu?&lt;/h3&gt;

&lt;p&gt;Hitung dulu jarak rata-rata hariannya. Kalau kamu menempuh sekitar 50 km pulang pergi, klaim 300 km BYD Atto 1 Dynamic sudah jauh di atas kebutuhan, dan kamu tidak perlu membayar mahal untuk baterai yang jauh lebih besar. Kalau kamu sering ke luar kota, jarak tempuh nyata dan kecepatan pengisian cepat jadi lebih penting dari harga.&lt;/p&gt;

&lt;h3 id=&quot;bisakah-kamu-mengisi-di-rumah&quot;&gt;Bisakah kamu mengisi di rumah?&lt;/h3&gt;

&lt;p&gt;Ini pertanyaan yang paling menentukan. Mengisi di rumah semalaman membuat jarak tempuh hampir tidak jadi masalah untuk pemakaian harian. Tanpa titik pengisian di rumah atau kantor, kamu bergantung penuh pada SPKLU, dan tarifnya lebih tinggi seperti dihitung di atas.&lt;/p&gt;

&lt;h3 id=&quot;seberapa-jauh-kamu-percaya-angka-klaim&quot;&gt;Seberapa jauh kamu percaya angka klaim?&lt;/h3&gt;

&lt;p&gt;Klaim jarak tempuh pabrikan adalah angka uji di bawah kondisi standar. Dua uji jalan di atas, yaitu Geely EX2 dan Geely EX5, menghasilkan jarak hitungan sekitar 205 sampai 225 km dan 310 km, atau sekitar 52% sampai 57% dan 63% dari klaim 395 km dan 490 sampai 495 km. Dua contoh itu bukan bukti untuk semua mobil. Konsumsi dipengaruhi kecepatan, medan, jumlah penumpang, penyejuk udara, dan mode berkendara. Perlakukan klaim sebagai batas atas, lalu sesuaikan perencanaanmu setelah tahu konsumsi nyata mobilmu.&lt;/p&gt;

&lt;h3 id=&quot;kapan-mobil-listrik-belum-cocok&quot;&gt;Kapan mobil listrik belum cocok?&lt;/h3&gt;

&lt;p&gt;Ada situasi yang membuat mobil listrik kurang praktis, dan lebih jujur membahasnya sebelum membeli.&lt;/p&gt;

&lt;p&gt;Kalau kamu tinggal di apartemen atau rumah tanpa titik pengisian dan tempat parkirmu tidak punya colokan, kamu bergantung pada SPKLU. Hitungan biaya di &lt;a href=&quot;/2026/11/04/mobil-listrik-cara-kerja-pengisian-harga#biaya-mengisi-penuh-untuk-tiap-model&quot;&gt;Bagian 2&lt;/a&gt; menunjukkan SPKLU sekitar 1,7 kali lebih mahal dari rumah dan butuh waktu khusus untuk singgah. PLN dan mitranya mengoperasikan 3.007 lokasi SPKLU pada 2025.&lt;/p&gt;

&lt;p&gt;Rute yang panjang tanpa cadangan menambah risiko: misalnya sering melewati daerah tanpa SPKLU, klaim jarak yang tampak cukup di brosur bisa menjadi tipis. Dua uji jalan Geely di atas menunjukkan jarak hitungan 52% sampai 63% dari klaim. Pada rute seperti itu, PHEV atau hybrid bisa lebih masuk akal, karena mesin bensin menutup kekurangan jarak.&lt;/p&gt;

&lt;p&gt;Untuk anggaran yang ketat dan nilai jual kembali, ingat bahwa harga mobil listrik di Indonesia berubah cepat, seperti yang terlihat dari kenaikan harga Jaecoo J5 EV dan perubahan harga Wuling Darion EV dalam beberapa bulan.&lt;/p&gt;

&lt;p&gt;Mobil listrik paling masuk akal ketika kamu bisa mengisi di rumah, rutemu rata-rata pendek, dan kamu menghitung biaya per tahun termasuk listrik, tidak berhenti di harga beli.&lt;/p&gt;

&lt;h3 id=&quot;bagaimana-dengan-umur-baterai&quot;&gt;Bagaimana dengan umur baterai?&lt;/h3&gt;

&lt;p&gt;Studi Departemen Energi AS menyebut baterai bisa bertahan 12 sampai 15 tahun di iklim sedang dan 8 sampai 12 tahun di iklim berat, dan penggantiannya bisa mahal kalau baterai rusak (&lt;a href=&quot;https://www.fueleconomy.gov/feg/evtech.shtml&quot;&gt;FuelEconomy.gov&lt;/a&gt;). Sumber itu tidak merinci iklim tropis, jadi pakai rentang bawah sebagai acuan hati-hati. Cek masa garansi baterai: MG, misalnya, menyebut 8 tahun atau 160.000 km untuk S5 EV.&lt;/p&gt;

&lt;h2 id=&quot;pertanyaan-yang-sering-muncul&quot;&gt;Pertanyaan yang sering muncul&lt;/h2&gt;

&lt;h3 id=&quot;berapa-lama-mengisi-mobil-listrik-sampai-penuh&quot;&gt;Berapa lama mengisi mobil listrik sampai penuh?&lt;/h3&gt;

&lt;p&gt;Pengisian penuh lewat AC bisa memakan 3 sampai 12 jam, tergantung kapasitas baterai dan daya charger. Pengisian cepat DC sampai 80% biasanya sekitar 20 sampai 30 menit untuk mobil yang mendukungnya.&lt;/p&gt;

&lt;h3 id=&quot;berapa-biaya-mengisi-mobil-listrik&quot;&gt;Berapa biaya mengisi mobil listrik?&lt;/h3&gt;

&lt;p&gt;Untuk BYD Atto 1 Premium dengan baterai 38,88 kWh, mengisi penuh di rumah dengan tarif Rp1.444,70 per kWh menghabiskan sekitar Rp60 ribu sampai Rp67 ribu setelah memperhitungkan rugi pengisian. Di SPKLU dengan tarif Rp2.475 per kWh, biayanya sekitar Rp96 ribu atau lebih.&lt;/p&gt;

&lt;h3 id=&quot;apakah-hybrid-termasuk-mobil-listrik&quot;&gt;Apakah hybrid termasuk mobil listrik?&lt;/h3&gt;

&lt;p&gt;Tidak, kalau yang dimaksud mobil listrik murni. HEV dan PHEV masih memakai mesin bensin. PHEV bisa dicolok dan menempuh sekitar 32 sampai 64 km dengan listrik saja, sedangkan HEV tidak bisa dicolok sama sekali.&lt;/p&gt;

&lt;h3 id=&quot;apakah-insentif-pajak-mobil-listrik-masih-ada&quot;&gt;Apakah insentif pajak mobil listrik masih ada?&lt;/h3&gt;

&lt;p&gt;Insentif lama berakhir. Rencana PPN DTP baru (100% untuk baterai nikel, 40% untuk non-nikel) masih dikaji pada 23 Juni 2026. Cek status terbarunya ke Kementerian Keuangan atau dealer.&lt;/p&gt;

&lt;h3 id=&quot;apakah-mobil-listrik-bisa-dipakai-mudik&quot;&gt;Apakah mobil listrik bisa dipakai mudik?&lt;/h3&gt;

&lt;p&gt;Bisa, dengan perencanaan. Pastikan baterai penuh sebelum berangkat, rencanakan titik SPKLU di sepanjang rute, dan jangan mengandalkan klaim jarak penuh. Pengisian cepat 30% ke 80% yang diklaim 20 sampai 28 menit pada Geely EX5 dan Jaecoo J5 EV membuat singgah di SPKLU relatif singkat, tetapi antrean dan SPKLU yang sedang rusak tetap mungkin terjadi.&lt;/p&gt;

&lt;h2 id=&quot;penutup&quot;&gt;Penutup&lt;/h2&gt;

&lt;p&gt;Mobil listrik sudah masuk jajaran model terlaris di Indonesia pada 2026, tetapi memilihnya tidak cukup dengan membandingkan harga. Untuk pemakaian dalam kota dengan titik pengisian di rumah, BYD Atto 1, Geely EX2, dan Jaecoo J5 EV memberi jarak tempuh klaim yang cukup di kisaran Rp200 jutaan sampai Rp300 jutaan. Untuk keluarga besar, BYD M6 dan Wuling Darion EV menawarkan kursi lebih banyak. Untuk perjalanan antarkota, kecepatan pengisian cepat dan ketersediaan SPKLU lebih menentukan daripada angka kapasitas baterai.&lt;/p&gt;

&lt;p&gt;Sebelum membeli, tanyakan tiga hal ke dealer: harga OTR terbaru dengan semua biaya, konektor pengisian yang dipakai mobilnya, dan masa garansi baterai. Ketiganya menentukan biaya sebenarnya, dan tidak bisa dibaca dari brosur saja.&lt;/p&gt;

&lt;h2 id=&quot;tentang-tulisan-ini&quot;&gt;Tentang tulisan ini&lt;/h2&gt;

&lt;p&gt;Saya Mahyuddin Susanto, penulis blog ini. Latar belakang saya di jaringan dan infrastruktur TI, bukan otomotif (profil lengkap ada di halaman &lt;a href=&quot;/about&quot;&gt;About&lt;/a&gt;), jadi artikel ini adalah rangkuman dari sumber publik yang dikutip di dalam teks, ditambah hitungan dari data sumber itu. Saya tidak menguji mobilnya sendiri. Kalau kamu menemukan angka yang sudah berubah atau keliru, kirim lewat halaman &lt;a href=&quot;/contact&quot;&gt;Contact&lt;/a&gt;. Angka yang terbukti berubah akan saya perbarui di artikel ini dan tanggalnya saya catat.&lt;/p&gt;

&lt;h2 id=&quot;sumber-utama&quot;&gt;Sumber utama&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Gaikindo, &lt;a href=&quot;https://www.gaikindo.or.id/20-model-mobil-terlaris-september-2026-atto-1-menempel-gran-max/&quot;&gt;20 model mobil terlaris September 2026&lt;/a&gt;, 25 Oktober 2026&lt;/li&gt;
  &lt;li&gt;Kontan, &lt;a href=&quot;https://industri.kontan.co.id/news/10-mobil-listrik-terlaris-di-indonesia-hingga-september-2026&quot;&gt;10 mobil listrik terlaris hingga September 2026&lt;/a&gt;, 12 Oktober 2026&lt;/li&gt;
  &lt;li&gt;GoodStats Data, &lt;a href=&quot;https://data.goodstats.id/statistic/10-mobil-listrik-terlaris-semester-i-2026-jaecoo-j5-di-puncak-dRODE&quot;&gt;10 mobil listrik terlaris semester I 2026&lt;/a&gt;, 23 Juli 2026&lt;/li&gt;
  &lt;li&gt;U.S. Department of Energy, &lt;a href=&quot;https://afdc.energy.gov/vehicles/electric&quot;&gt;Alternative Fuels Data Center&lt;/a&gt; dan &lt;a href=&quot;https://www.fueleconomy.gov/feg/evtech.shtml&quot;&gt;FuelEconomy.gov&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Metro TV, &lt;a href=&quot;https://www.metrotvnews.com/read/NA0CzpEz-daftar-lengkap-tarif-listrik-pln-akhir-oktober-2026-per-kwh&quot;&gt;tarif listrik PLN akhir Oktober 2026&lt;/a&gt;, 29 Oktober 2026&lt;/li&gt;
  &lt;li&gt;Okezone, &lt;a href=&quot;https://www.rctiplus.com/news/detail/okezone/5343306/segini-tarif-cas-mobil-listrik-di-spklu-tol-untuk-mudik-lebaran-2026&quot;&gt;tarif cas mobil listrik di SPKLU tol&lt;/a&gt;, 18 Maret 2026&lt;/li&gt;
  &lt;li&gt;Kontan, &lt;a href=&quot;https://industri.kontan.co.id/news/meningkat-44-pln-operasikan-4655-spklu-sepanjang-2025&quot;&gt;PLN operasikan 4.655 SPKLU sepanjang 2025&lt;/a&gt;, 8 Februari 2026&lt;/li&gt;
  &lt;li&gt;DDTCNews, &lt;a href=&quot;https://news.ddtc.co.id/berita/nasional/1820265/ppn-dtp-kendaraan-listrik-belum-dirilis-airlangga-masih-dikaji-ulang&quot;&gt;PPN DTP kendaraan listrik belum dirilis&lt;/a&gt;, 23 Juni 2026&lt;/li&gt;
  &lt;li&gt;Otodriver, daftar harga &lt;a href=&quot;https://otodriver.com/daftar-harga/2026/daftar-harga-byd-terbaru-september-2026-dafefdaa026&quot;&gt;BYD&lt;/a&gt; dan &lt;a href=&quot;https://otodriver.com/daftar-harga/2026/daftar-harga-wuling-terbaru-september-2026-dafefcff026&quot;&gt;Wuling&lt;/a&gt;, September 2026&lt;/li&gt;
  &lt;li&gt;Moladin, &lt;a href=&quot;https://moladin.com/news/harga-otr-geely-terbaru-september-2026/&quot;&gt;harga OTR Geely&lt;/a&gt; dan &lt;a href=&quot;https://moladin.com/news/daftar-mobil-listrik-termurah-september-2026/?show_all=1&quot;&gt;mobil listrik termurah&lt;/a&gt;, September 2026&lt;/li&gt;
  &lt;li&gt;Kabarbursa, &lt;a href=&quot;https://www.kabarbursa.com/otomotif/mg-s5-ev-resmi-meluncur-di-iims-2026-harga-mulai-rp3339-juta.md&quot;&gt;MG S5 EV&lt;/a&gt;, 6 Februari dan 17 Juli 2026&lt;/li&gt;
  &lt;li&gt;detikOto, &lt;a href=&quot;https://oto.detik.com/mobil/d-8682899/harga-jaecoo-j5-naik-tak-ada-lagi-yang-di-bawah-rp-250-juta&quot;&gt;harga Jaecoo J5 naik&lt;/a&gt;, 28 September 2026, &lt;a href=&quot;https://oto.detik.com/mobil-listrik/d-8182231/harga-resmi-jaecoo-j5-ev-diumumkan-3-november-ini-bocoran-spesifikasinya&quot;&gt;spesifikasi J5 EV&lt;/a&gt;, 28 Oktober 2025, dan &lt;a href=&quot;https://oto.detik.com/mobil-listrik/d-8197085/spesifikasi-wuling-darion-ada-varian-ev-dan-phev-harga-mulai-rp-356-juta&quot;&gt;spesifikasi Wuling Darion&lt;/a&gt;, 6 November 2025&lt;/li&gt;
  &lt;li&gt;Listrik Indonesia, &lt;a href=&quot;https://listrikindonesia.com/detail/17430/mengupas-kapasitas-baterai-dan-jarak-tempuh-byd-atto-1&quot;&gt;Atto 1&lt;/a&gt; (2 Agustus 2025), &lt;a href=&quot;https://listrikindonesia.com/detail/17505/membedah-perbedaan-fitur-jaecoo-j5-ev-standard-vs-premium&quot;&gt;Jaecoo J5 EV&lt;/a&gt; (10 Agustus 2025), &lt;a href=&quot;https://listrikindonesia.com/detail/15468/harganya-bikin-alphard-ketar-ketir-ini-spesifikasi-byd-denza-d9&quot;&gt;Denza D9&lt;/a&gt; (24 Januari 2025), &lt;a href=&quot;https://listrikindonesia.com/detail/15531/siap-ramaikan-pasar-ev-indonesia-ini-spesifikasi-vf-3&quot;&gt;VinFast VF 3&lt;/a&gt; (31 Januari 2025), dan &lt;a href=&quot;https://listrikindonesia.com/detail/19930/insentif-pajak-dihapus-kapan-waktu-yang-tepat-beli-mobil-listrik&quot;&gt;insentif pajak&lt;/a&gt; (1 Mei 2026)&lt;/li&gt;
  &lt;li&gt;Carmudi, &lt;a href=&quot;https://www.carmudi.co.id/journal/harga-geely-ex2-setelah-resmi-meluncur-di-indonesia-mulai-segini/&quot;&gt;Geely EX2&lt;/a&gt; (21 Januari 2026), &lt;a href=&quot;https://www.carmudi.co.id/journal/test-drive-jakarta-cianjur-berapa-konsumsi-listrik-dan-daya-geely-ex2/&quot;&gt;uji EX2&lt;/a&gt; (3 Februari 2026), &lt;a href=&quot;https://www.carmudi.co.id/journal/test-drive-jakarta-bandung-segini-konsumsi-daya-geely-ex5/&quot;&gt;uji EX5&lt;/a&gt; (20 Mei 2025), &lt;a href=&quot;https://www.carmudi.co.id/journal/harga-rp395-juta-ini-pembaruan-byd-m6-ev-2026-varian-standard-di-giias-2026/&quot;&gt;BYD M6&lt;/a&gt; (31 Juli 2026), dan &lt;a href=&quot;https://www.carmudi.co.id/journal/spesifikasi-byd-sealion-7-sanggup-tempuh-567-km-sekali-cas/&quot;&gt;BYD Sealion 7&lt;/a&gt; (16 Februari 2025)&lt;/li&gt;
  &lt;li&gt;IDX Channel, &lt;a href=&quot;https://www.idxchannel.com/technology/hadir-kembali-di-pasar-otomotif-ri-geely-hadirkan-mobil-listrik-dengan-segudang-teknologi&quot;&gt;spesifikasi Geely EX5&lt;/a&gt;, 22 Februari 2025&lt;/li&gt;
  &lt;li&gt;Foto hero: &lt;a href=&quot;https://unsplash.com/photos/a-white-car-plugged-in-to-a-charging-station-JkTjKEVcckg&quot;&gt;JUICE&lt;/a&gt; di &lt;a href=&quot;https://unsplash.com&quot;&gt;Unsplash&lt;/a&gt;, dipotong ke 1200 x 630&lt;/li&gt;
  &lt;li&gt;IEA, &lt;a href=&quot;https://www.iea.org/reports/global-ev-outlook-2026&quot;&gt;Global EV Outlook 2026&lt;/a&gt;; BPK, &lt;a href=&quot;https://peraturan.bpk.go.id/Details/116973/perpres-no-55&quot;&gt;Perpres 55/2019&lt;/a&gt; dan &lt;a href=&quot;https://peraturan.bpk.go.id/Details/273447&quot;&gt;Perpres 79/2023&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Zigwheels, &lt;a href=&quot;https://www.zigwheels.co.id/en/mobil-baru/byd/sealion-7/harga/&quot;&gt;harga BYD Sealion 7&lt;/a&gt;, dan &lt;a href=&quot;https://www.byd.com/id&quot;&gt;BYD Indonesia&lt;/a&gt;, keduanya dibuka 4 November 2026&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Mahyuddin Susanto</name></author><category term="Mobil" /><category term="Otomotif" /><category term="mobil listrik" /><category term="bev" /><category term="baterai" /><category term="spklu" /><category term="harga mobil listrik" /><summary type="html">Daftar isi bagian ini</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.udienz.web.id/img/mobil-listrik-pengertian-jenis-cara-kerja.jpg" /><media:content medium="image" url="https://www.udienz.web.id/img/mobil-listrik-pengertian-jenis-cara-kerja.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Jenis Konektor Fiber Optic: SC, LC, FC, ST, MPO, VSFF</title><link href="https://www.udienz.web.id/2026/11/03/jenis-jenis-konektor-fiber-optic" rel="alternate" type="text/html" title="Jenis Konektor Fiber Optic: SC, LC, FC, ST, MPO, VSFF" /><published>2026-11-03T00:00:00+00:00</published><updated>2026-11-03T00:00:00+00:00</updated><id>https://www.udienz.web.id/2026/11/03/jenis-jenis-konektor-fiber-optic</id><content type="html" xml:base="https://www.udienz.web.id/2026/11/03/jenis-jenis-konektor-fiber-optic">&lt;p&gt;Pegang patch cord fiber dari laci, lalu lihat ujungnya. Bentuknya bisa persegi, bisa kecil berpasangan, bisa bulat berulir. Semuanya tugasnya sama: mempertemukan dua inti serat sehingga cahaya lewat dengan rugi sekecil mungkin. Yang beda adalah ukuran, cara kopling, dan tempat konektor itu cocok dipakai.&lt;/p&gt;

&lt;p&gt;Tulisan ini merangkum jenis konektor fiber optic yang paling sering ketemu di lapangan, mulai dari SC dan LC sampai konektor VSFF untuk transceiver 400G/800G. Saya juga bahas perbedaan UPC dan APC yang sering bikin salah beli, arti kode warna, dan angka insertion loss yang boleh dijadikan pegangan.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/jenis-konektor-fiber-optic-ferrule.png&quot; alt=&quot;Diagram perbandingan ferrule konektor fiber optic: 2,5 mm untuk SC, FC, ST dan 1,25 mm untuk LC, MU&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;Dua hal yang membedakan konektor: ukuran ferrule (2,5 mm untuk SC, FC, ST; 1,25 mm untuk LC dan MU) dan cara koplingnya.&lt;/li&gt;
    &lt;li&gt;UPC (biru) dan APC (hijau) tidak boleh dikawinkan langsung. Kalau polish-nya harus ganti, pakai patch cord hibrida.&lt;/li&gt;
    &lt;li&gt;Warna konektor membantu, tapi tanda cetak di kabel lebih bisa dipercaya.&lt;/li&gt;
    &lt;li&gt;Untuk densitas tinggi, LC adalah titik awal. MPO/MTP dan VSFF (SN, MDC) masuk saat port-nya sudah 400G/800G.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;apa-yang-membedakan-satu-konektor-dari-yang-lain&quot;&gt;Apa yang membedakan satu konektor dari yang lain?&lt;/h2&gt;

&lt;p&gt;Sebuah konektor fiber memegang serat di dalam ferrule, yaitu tabung kecil dengan lubang tepat di tengah. Dua ferrule dipertemukan di dalam adapter, dan kualitas pertemuan itulah yang menentukan loss. Ada tiga hal yang membedakan konektor.&lt;/p&gt;

&lt;p&gt;Pertama, diameter ferrule. SC, FC, dan ST memakai ferrule 2,5 mm, sedangkan LC dan MU memakai 1,25 mm sehingga bodinya bisa jauh lebih kecil (&lt;a href=&quot;https://thefoa.org/tech/connID.htm&quot;&gt;FOA, Connector Identifier&lt;/a&gt;). Kedua, mekanisme kopling: snap-in (SC), bayonet (ST), ulir (FC), atau push-on dengan pin pemandu (MPO). Ketiga, polish ujung ferrule, rata (PC/UPC) atau miring 8 derajat (APC), yang saya bahas tersendiri di bawah.&lt;/p&gt;

&lt;h2 id=&quot;konektor-satu-ukuran-25-mm-sc-fc-st&quot;&gt;Konektor satu ukuran 2,5 mm: SC, FC, ST&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SC&lt;/strong&gt; dipakai luas dan tersedia dalam bentuk duplex. Koplingnya snap-in dengan gerakan push-pull, dan menurut &lt;a href=&quot;https://thefoa.org/tech/connID.htm&quot;&gt;FOA&lt;/a&gt; konektor ini distandardisasi di TIA-568-A, edisi lama (nilai loss di bawah merujuk TIA-568.3-E).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FC&lt;/strong&gt; memakai ulir. Dulu populer untuk singlemode, sekarang sebagian besar sudah digantikan SC dan LC. Kalau kamu ketemu FC, kemungkinan besar itu instalasi lama.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ST&lt;/strong&gt; memakai kopling bayonet dengan ferrule 2,5 mm, biasanya keramik. FOA mencatat ST sebagai konektor multimode paling populer sampai sekitar tahun 2005. Nama ST juga merek dagang AT&amp;amp;T.&lt;/p&gt;
&lt;h2 id=&quot;konektor-kecil-125-mm-lc-dan-mu&quot;&gt;Konektor kecil 1,25 mm: LC dan MU&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;LC&lt;/strong&gt; (FOA menyebutnya “Lucent LC”) memakai ferrule 1,25 mm, sehingga bisa dipasang jauh lebih rapat daripada SC. FOA mencatat konektor small form factor mulai naik pada akhir 1990-an, dan LC kini jadi pilihan utama untuk singlemode di telco serta LAN/SAN berkecepatan tinggi.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MU&lt;/strong&gt; juga berferrule 1,25 mm, bentuknya mirip SC versi mini. Konektor ini populer di Jepang dan Asia Timur, jadi di Indonesia jarang ketemu.&lt;/p&gt;

&lt;h2 id=&quot;mpomtp-banyak-serat-dalam-satu-konektor&quot;&gt;MPO/MTP: banyak serat dalam satu konektor&lt;/h2&gt;

&lt;p&gt;MPO memuat 12 atau 16 serat dalam satu ferrule plastik yang berbentuk baris. Kopling-nya push-on, dan keselarasan dijaga oleh pin di salah satu ferrule yang masuk ke lubang di ferrule lawannya (&lt;a href=&quot;https://thefoa.org/tech/connID.htm&quot;&gt;FOA&lt;/a&gt;). “MTP” adalah nama komersial untuk konektor jenis ini.&lt;/p&gt;

&lt;p&gt;Konektor ini biasa dijual dalam bentuk kabel preterminated, dan dipakai untuk paralel optik seperti multimode 40G/100G.&lt;/p&gt;

&lt;p&gt;Yang sering bikin bingung ada tiga. Pertama, gender: male punya dua pin pemandu dan female punya lubang untuk pin itu. Menurut &lt;a href=&quot;https://www.ampcom.com/blogs/tech-lab/mpo-mtp-polarization-types-explained-type-a-b-c&quot;&gt;AMPCOM&lt;/a&gt;, male ke male bisa merusak kedua ferrule, jadi satu sisi harus male dan sisi lain female.&lt;/p&gt;

&lt;p&gt;Kedua, polaritas. Ada tipe A (lurus, posisi 1 ke 1), tipe B (terbalik penuh, 1 ke 12), dan tipe C (pair-flipped). Ringkasan ini dari &lt;a href=&quot;https://www.ampcom.com/blogs/tech-lab/mpo-mtp-polarization-types-explained-type-a-b-c&quot;&gt;AMPCOM Tech Lab&lt;/a&gt;, blog vendor, jadi anggap sebagai gambaran awal. Untuk desain sungguhan, rujuk TIA-568.3 atau panduan vendor kabel yang kamu pakai.&lt;/p&gt;

&lt;p&gt;Ketiga, hubungan pin dan key. Sumber yang saya baca tidak sepakat soal aturannya, jadi cek dokumentasi produk yang kamu beli dan jangan menghafal satu aturan umum.&lt;/p&gt;

&lt;h2 id=&quot;konektor-vsff-untuk-400g-dan-800g-sn-dan-mdc&quot;&gt;Konektor VSFF untuk 400G dan 800G: SN dan MDC&lt;/h2&gt;

&lt;p&gt;Panel 19 inci makin padat, jadi muncul keluarga &lt;em&gt;very small form factor&lt;/em&gt; (VSFF). Dua yang terdokumentasi paling jelas adalah SN dan MDC. Keduanya berisi dua ferrule keramik berpegas 1,25 mm berbasis teknologi LC. Menurut Rosenberger OSI, SN adalah Senko Nano dari SENKO, sedangkan MDC (Miniature Duplex Connector) dari US Conec.&lt;/p&gt;

&lt;p&gt;Menurut &lt;a href=&quot;https://osi.rosenberger.com/us/news-media/blog-vlog/vsff-connector-in-400-and-800-gigabit-applications/&quot;&gt;Rosenberger OSI&lt;/a&gt;, konektor VSFF muat hingga 128 port per rack unit di panel 19 inci, dibanding maksimum 96 port untuk LC duplex. Versi SN Quad dan MDC Quad dipakai untuk 400G DR4 dan 800G DR4 sampai sekitar 500 m.&lt;/p&gt;

&lt;p&gt;Satu peringatan praktis: ferrule 1,25 mm yang sama bukan berarti housing dan adapternya cocok. Jangan asumsikan konektor VSFF yang berbeda bisa saling dikawinkan.&lt;/p&gt;

&lt;h2 id=&quot;upc-vs-apc-jangan-dicampur&quot;&gt;UPC vs APC: jangan dicampur&lt;/h2&gt;

&lt;p&gt;Polish ujung ferrule menentukan seberapa banyak cahaya yang memantul balik ke sumber. Menurut &lt;a href=&quot;https://www.l-com.com/resources/blog/apc-vs-upc-fiber-connectors&quot;&gt;L-com&lt;/a&gt; (28 Oktober 2026):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;UPC punya return loss sekitar 50 dB atau lebih baik. Polish PC yang lebih lama sekitar 40 dB.&lt;/li&gt;
  &lt;li&gt;APC dipoles dengan sudut 8 derajat, sehingga cahaya pantul diarahkan ke cladding dan tidak balik ke laser. Return loss-nya sekitar 60 dB atau lebih baik.&lt;/li&gt;
  &lt;li&gt;Pada singlemode, UPC berwarna biru dan APC berwarna hijau.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Menurut L-com juga, APC jadi standar untuk PON/FTTx, terutama bila ada overlay video RF 1550 nm (biasanya SC APC), plus RF over fiber, CATV, dan DAS.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jangan pernah mengawinkan UPC dengan APC.&lt;/strong&gt; Menurut L-com, sudut ferrule-nya tidak pas, sehingga ada celah udara yang menambah beberapa dB loss, dan ferrule bisa rusak. Untuk berpindah antar-polish, pakai patch cord hibrida APC-ke-UPC. Adapter tidak menyelesaikan masalah ini.&lt;/p&gt;

&lt;h2 id=&quot;kode-warna-bantu-tapi-jangan-dijadikan-satu-satunya-pegangan&quot;&gt;Kode warna: bantu, tapi jangan dijadikan satu-satunya pegangan&lt;/h2&gt;

&lt;p&gt;Berdasarkan &lt;a href=&quot;https://www.thefoa.org/tech/ColCodes.htm&quot;&gt;FOA, Fiber Optic Cable And Connector Color&lt;/a&gt;:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Jenis serat&lt;/th&gt;
      &lt;th&gt;Warna&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Singlemode PC/UPC&lt;/td&gt;
      &lt;td&gt;Biru&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Singlemode APC&lt;/td&gt;
      &lt;td&gt;Hijau&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Multimode OM1 (62,5/125)&lt;/td&gt;
      &lt;td&gt;Beige&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Multimode OM2 (50/125)&lt;/td&gt;
      &lt;td&gt;Konektor hitam, jaket oranye&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Multimode OM3/OM4&lt;/td&gt;
      &lt;td&gt;Aqua&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Multimode OM5&lt;/td&gt;
      &lt;td&gt;Lime&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Warna lime untuk jaket kabel OM5 diresmikan lewat ANSI/TIA-598-D-2 pada Januari 2018 (&lt;a href=&quot;https://www.commscope.com/Blog/Call-me-a-limey&quot;&gt;CommScope&lt;/a&gt;). Hati-hati: L-com mencatat lime OM5 bisa terlihat seperti hijau APC di cahaya redup. Warna violet untuk OM4 yang kadang ditemui adalah konvensi pabrikan, bukan warna standar TIA-598.&lt;/p&gt;

&lt;p&gt;FOA sendiri mengingatkan bahwa pewarnaan konektor tidak seragam antarpabrikan. Cek tanda cetak di jaket kabel sebelum menyimpulkan jenis serat dari warna konektornya.&lt;/p&gt;

&lt;h2 id=&quot;berapa-loss-yang-wajar&quot;&gt;Berapa loss yang wajar?&lt;/h2&gt;

&lt;p&gt;Fluke Networks menulis bahwa TIA menetapkan 0,75 dB sebagai batas maksimum worst-case untuk satu pasangan konektor, dan menyebut angka itu “cukup tinggi dan kurang realistis” (&lt;a href=&quot;https://de.flukenetworks.com/blog/cabling-chronicles/cable-testing-101-standard-says-075-db&quot;&gt;Fluke, 18 April 2018&lt;/a&gt;). Nilai tipikal yang disebut Fluke di artikel yang sama jauh lebih rendah:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Kelas konektor&lt;/th&gt;
      &lt;th&gt;Insertion loss tipikal&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Standar&lt;/td&gt;
      &lt;td&gt;0,3 sampai 0,5 dB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Low loss&lt;/td&gt;
      &lt;td&gt;0,15 sampai 0,2 dB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Untuk pengukuran dengan kabel referensi, &lt;a href=&quot;https://www.flukenetworks.com/knowledge-base/certifiber-pro/new-loss-budget-values-reference-grade-connectors-ansitia-5683-d&quot;&gt;Fluke KB&lt;/a&gt; mencatat nilai yang selaras TIA-568.3-E untuk sambungan reference ke standard: singlemode 0,50 dB. Nilai multimode (0,30 dB dan 0,50 dB) tergantung versi dan konfigurasi pengukuran, jadi baca artikel Fluke-nya sebelum memakainya. Untuk pasangan konektor reference-grade, Fluke menyebut maksimum 0,10 dB untuk multimode dan 0,20 dB untuk singlemode.&lt;/p&gt;

&lt;p&gt;Satu peringatan: jangan memetakan 0,75 dB TIA ke “Grade B” atau “Grade C” di IEC 61753-1. Grade IEC adalah statistik untuk sambungan acak, bukan batas lulus-gagal seperti TIA.&lt;/p&gt;

&lt;h2 id=&quot;kebersihan-ujung-konektor&quot;&gt;Kebersihan ujung konektor&lt;/h2&gt;

&lt;p&gt;Loss atau return loss yang jelek tidak selalu salah jenis konektor. Bisa juga debu. Partikel di permukaan ferrule menghalangi cahaya atau menimbulkan pantulan.&lt;/p&gt;

&lt;p&gt;Langkahnya sederhana: inspeksi dulu dengan scope sebelum mengawinkan konektor, bersihkan kalau kotor, dan pasang tutup debu saat konektor tidak dipakai.&lt;/p&gt;
&lt;h2 id=&quot;cara-memilih&quot;&gt;Cara memilih&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Kebutuhan&lt;/th&gt;
      &lt;th&gt;Konektor yang biasanya cocok&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Jaringan akses FTTH/PON&lt;/td&gt;
      &lt;td&gt;SC APC (hijau) atau LC APC&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Patch panel dan transceiver dengan port duplex kecil&lt;/td&gt;
      &lt;td&gt;LC duplex&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Instalasi lama&lt;/td&gt;
      &lt;td&gt;FC atau ST&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Backbone paralel optik 40G/100G&lt;/td&gt;
      &lt;td&gt;MPO/MTP&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Port 400G/800G berdensitas tinggi&lt;/td&gt;
      &lt;td&gt;SN atau MDC (VSFF), sesuai transceiver&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Aturan praktisnya: pilih konektor mengikuti port perangkat, lalu pilih polish mengikuti jenis layanan, dan terakhir cocokkan warna dengan jenis serat. Kalau ragu, baca datasheet transceiver atau ODF yang akan dipakai sebelum memesan patch cord.&lt;/p&gt;

&lt;p&gt;Konektor APC dipakai di PON/FTTx (lihat bagian UPC vs APC di atas). Untuk melihat posisinya dalam arsitektur jaringan PON, baca &lt;a href=&quot;/2026/11/03/mengenal-gpon-fungsi-manfaat-arsitektur&quot;&gt;Mengenal GPON&lt;/a&gt;. Kondisi internet rumah berbasis fiber di Indonesia saya bahas di &lt;a href=&quot;/2026/11/03/target-100-mbps-fixed-broadband-indonesia&quot;&gt;target 100 Mbps fixed broadband&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;sumber&quot;&gt;Sumber&lt;/h2&gt;

&lt;p&gt;Hampir semua sumber di bawah adalah dokumentasi vendor atau asosiasi industri (FOA). Standar TIA dan IEC berbayar, jadi saya merujuknya lewat sumber-sumber ini dan bukan membaca dokumennya langsung. Untuk desain atau pengadaan, cek ke dokumen standar dan datasheet produknya.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://thefoa.org/tech/connID.htm&quot;&gt;FOA, Connector Identifier&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.thefoa.org/tech/ColCodes.htm&quot;&gt;FOA, Fiber Optic Cable And Connector Color&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.l-com.com/resources/blog/apc-vs-upc-fiber-connectors&quot;&gt;L-com, APC vs UPC Fiber Connectors&lt;/a&gt; (28 Oktober 2026)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://de.flukenetworks.com/blog/cabling-chronicles/cable-testing-101-standard-says-075-db&quot;&gt;Fluke Networks, Cable Testing 101: But the Standard Says 0.75 dB!&lt;/a&gt; (18 April 2018)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.flukenetworks.com/knowledge-base/certifiber-pro/new-loss-budget-values-reference-grade-connectors-ansitia-5683-d&quot;&gt;Fluke Networks, New Loss Budget Values for Reference Grade Connectors&lt;/a&gt; (20 Februari 2019)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.commscope.com/Blog/Call-me-a-limey&quot;&gt;CommScope, Call me a limey&lt;/a&gt; (9 Maret 2018)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://osi.rosenberger.com/us/news-media/blog-vlog/vsff-connector-in-400-and-800-gigabit-applications/&quot;&gt;Rosenberger OSI, VSFF connector in 400 and 800 Gigabit applications&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.ampcom.com/blogs/tech-lab/mpo-mtp-polarization-types-explained-type-a-b-c&quot;&gt;AMPCOM Tech Lab, MPO/MTP Polarization Types Explained&lt;/a&gt; (10 Juli 2026, blog vendor)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Penulis: &lt;a href=&quot;/about&quot;&gt;Mahyuddin Susanto&lt;/a&gt;. Koreksi atau tambahan bisa dikirim lewat &lt;a href=&quot;/contact&quot;&gt;halaman kontak&lt;/a&gt;.&lt;/p&gt;</content><author><name>Mahyuddin Susanto</name></author><category term="Komputer" /><category term="fiber optic" /><category term="konektor" /><category term="networking" /><category term="ftth" /><category term="datacenter" /><summary type="html">Pegang patch cord fiber dari laci, lalu lihat ujungnya. Bentuknya bisa persegi, bisa kecil berpasangan, bisa bulat berulir. Semuanya tugasnya sama: mempertemukan dua inti serat sehingga cahaya lewat dengan rugi sekecil mungkin. Yang beda adalah ukuran, cara kopling, dan tempat konektor itu cocok dipakai.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.udienz.web.id/img/jenis-konektor-fiber-optic-ferrule.png" /><media:content medium="image" url="https://www.udienz.web.id/img/jenis-konektor-fiber-optic-ferrule.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Mengenal GPON: Fungsi, Manfaat, dan Arsitekturnya</title><link href="https://www.udienz.web.id/2026/11/03/mengenal-gpon-fungsi-manfaat-arsitektur" rel="alternate" type="text/html" title="Mengenal GPON: Fungsi, Manfaat, dan Arsitekturnya" /><published>2026-11-03T00:00:00+00:00</published><updated>2026-11-03T00:00:00+00:00</updated><id>https://www.udienz.web.id/2026/11/03/mengenal-gpon-fungsi-manfaat-arsitektur</id><content type="html" xml:base="https://www.udienz.web.id/2026/11/03/mengenal-gpon-fungsi-manfaat-arsitektur">&lt;p&gt;Kalau kamu pernah melihat kotak kecil berlampu di rumah pelanggan fiber, itu ujung dari sebuah jaringan GPON. Di seberangnya, entah beberapa kilometer jauhnya, ada satu perangkat yang melayani puluhan kotak seperti itu lewat satu serat. Di antaranya hanya ada kaca dan splitter, tanpa listrik.&lt;/p&gt;

&lt;p&gt;Tulisan ini membahas apa itu GPON, standar yang mendasarinya, arsitektur dan cara kerjanya, serta apa gunanya dibanding jaringan fiber biasa. Untuk bagian konektor, saya tautkan ke &lt;a href=&quot;/2026/11/03/jenis-jenis-konektor-fiber-optic&quot;&gt;pembahasan jenis konektor fiber optic&lt;/a&gt; yang terbit sebelumnya.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/mengenal-gpon-arsitektur.png&quot; alt=&quot;Diagram arsitektur GPON: satu OLT terhubung lewat serat dan splitter pasif ke banyak ONT&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ilustrasi. Jumlah ONT dan split ratio di gambar bukan nilai nyata.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;GPON (Gigabit-capable Passive Optical Network) adalah teknologi akses fiber point-to-multipoint yang distandardisasi ITU-T lewat seri G.984.&lt;/li&gt;
    &lt;li&gt;Satu OLT (Optical Line Terminal) melayani banyak ONT (Optical Network Terminal) lewat serat bersama dan splitter pasif. Downstream 2,48832 Gbit/s, upstream 1,24416 Gbit/s (ITU juga mencantumkan varian upstream 2,48832 Gbit/s).&lt;/li&gt;
    &lt;li&gt;Satu serat membawa dua arah di panjang gelombang berbeda: sekitar 1490 nm ke bawah, sekitar 1310 nm ke atas.&lt;/li&gt;
    &lt;li&gt;Jangkauan fisik hingga 20 km, dan umumnya dipakai split 1:32. Batas sebenarnya ditentukan budget loss.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;apa-itu-gpon&quot;&gt;Apa itu GPON?&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;GPON&lt;/strong&gt; (Gigabit-capable Passive Optical Network) adalah jaringan akses fiber yang membagi satu jalur optik ke banyak pelanggan memakai komponen pasif, yaitu komponen pembagi yang tidak butuh catu daya. Arsitektur seperti ini disebut point-to-multipoint. GPON termasuk keluarga PON, yang kini juga mencakup standar yang lebih cepat.&lt;/p&gt;

&lt;p&gt;GPON sendiri adalah keluarga standar ITU-T G.984. Cisco menjelaskan perangkat sisi operator (OLT) mengumpulkan sinyal dari banyak ONT dalam satu aliran terpadu, lalu memformatnya menjadi Ethernet (&lt;a href=&quot;https://cisco.com/c/en/us/support/docs/switches/catalyst-pon-series/216230-understand-gpon-technology.html&quot;&gt;Cisco, Understand GPON Technology&lt;/a&gt;, Rev 3.0, 6 Desember 2023).&lt;/p&gt;

&lt;h2 id=&quot;keluarga-standar-itu-t-g984&quot;&gt;Keluarga standar ITU-T G.984&lt;/h2&gt;

&lt;p&gt;G.984 bukan satu dokumen, melainkan beberapa rekomendasi yang membagi tugas per lapisan. Tanggal berikut diambil dari halaman ITU untuk masing-masing rekomendasi:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Standar&lt;/th&gt;
      &lt;th&gt;Cakupan&lt;/th&gt;
      &lt;th&gt;Edisi yang berlaku&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;G.984.1&lt;/td&gt;
      &lt;td&gt;Karakteristik umum&lt;/td&gt;
      &lt;td&gt;03/2008&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;G.984.2&lt;/td&gt;
      &lt;td&gt;Lapisan fisik (PMD, Physical Media Dependent)&lt;/td&gt;
      &lt;td&gt;08/2019&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;G.984.3&lt;/td&gt;
      &lt;td&gt;Lapisan transmission convergence (TC)&lt;/td&gt;
      &lt;td&gt;01/2014, dengan amendemen sampai 2025&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;G.984.4&lt;/td&gt;
      &lt;td&gt;Antarmuka manajemen ONT (OMCI)&lt;/td&gt;
      &lt;td&gt;02/2008&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;G.984.5&lt;/td&gt;
      &lt;td&gt;Enhancement band&lt;/td&gt;
      &lt;td&gt;02/2022&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;G.984.6&lt;/td&gt;
      &lt;td&gt;Reach extension&lt;/td&gt;
      &lt;td&gt;03/2008, dengan amendemen&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;G.984.3 mencakup framing GTC (GPON Transmission Convergence), TDMA (time-division multiple access) upstream, DBA, aktivasi ONU, FEC (forward error correction), dan keamanan. G.984.5 menyediakan rentang panjang gelombang tambahan untuk layanan lain lewat WDM (wavelength-division multiplexing) overlay. G.984.6 mengatur perangkat penyambung (regenerator atau penguat) yang memperpanjang jangkauan sampai 60 km.&lt;/p&gt;

&lt;p&gt;Satu catatan jujur: teks lengkap G.984.1 dan G.984.2 tidak bisa saya baca langsung karena berbayar atau tidak tersedia terbuka. Angka detail di bawah saya ambil dari dokumentasi Cisco dan Omada yang terbuka, bukan dari teks standarnya.&lt;/p&gt;

&lt;h2 id=&quot;arsitektur-olt-odn-dan-ont&quot;&gt;Arsitektur: OLT, ODN, dan ONT&lt;/h2&gt;

&lt;p&gt;Menurut Cisco, jaringan GPON terdiri dari tiga bagian.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Komponen&lt;/th&gt;
      &lt;th&gt;Peran&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;OLT&lt;/td&gt;
      &lt;td&gt;Perangkat di sisi operator. Menggabungkan sinyal dari banyak ONT dan memformatnya jadi Ethernet.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ODN&lt;/td&gt;
      &lt;td&gt;Optical Distribution Network, yaitu jaringan distribusi optik: serat dan komponen pasif, termasuk splitter.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ONT/ONU&lt;/td&gt;
      &lt;td&gt;Optical Network Terminal/Unit. Perangkat di sisi pelanggan. Mengubah sinyal optik jadi listrik untuk perangkat pelanggan.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Alurnya: dari OLT, satu serat feeder menuju splitter, lalu serat distribusi dan drop menuju tiap ONT. Cisco memakai “ONT/ONU” sebagai satu istilah, jadi di artikel ini ONT dan ONU saya pakai bergantian.&lt;/p&gt;

&lt;h2 id=&quot;kecepatan-dan-panjang-gelombang&quot;&gt;Kecepatan dan panjang gelombang&lt;/h2&gt;

&lt;p&gt;GPON bersifat asimetris. Menurut Cisco, downstream berjalan di 2,48832 Gbit/s dan upstream di 1,24416 Gbit/s. Halaman G.984.3 di ITU mencatat bahwa edisi 2008 menyebut angka yang sama, dengan upstream 1,24416 atau 2,48832 Gbit/s.&lt;/p&gt;

&lt;p&gt;Dua arah itu berbagi satu serat dengan panjang gelombang berbeda (WDM dua arah). Menurut Cisco, rentangnya:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Arah&lt;/th&gt;
      &lt;th&gt;Rentang&lt;/th&gt;
      &lt;th&gt;Nominal&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Downstream&lt;/td&gt;
      &lt;td&gt;1480 sampai 1500 nm&lt;/td&gt;
      &lt;td&gt;1490 nm&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Upstream&lt;/td&gt;
      &lt;td&gt;1290 sampai 1330 nm&lt;/td&gt;
      &lt;td&gt;1310 nm&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Cisco juga mencatat redaman serat sekitar 0,35 dB/km pada 1310 dan 1490 nm.&lt;/p&gt;

&lt;p&gt;Ada panjang gelombang ketiga yang sering disebut, yaitu sekitar 1550 nm untuk overlay video RF. Standar G.984.5 memang menyediakan enhancement band untuk WDM overlay, tetapi nilai nanometernya tidak terlihat di ringkasan ITU yang bisa saya buka. Spesifikasi vendor menyebut sekitar 1550 nm, jadi anggap ini praktik umum, bukan angka dari standar yang saya verifikasi.&lt;/p&gt;

&lt;h2 id=&quot;jarak-split-ratio-dan-budget-loss&quot;&gt;Jarak, split ratio, dan budget loss&lt;/h2&gt;

&lt;p&gt;Menurut Cisco, GPON mendukung 16, 32, atau 64 cabang per port PON, dibatasi oleh path loss, dan 1:32 adalah yang umum. Menurut Cisco, batas jaraknya:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Parameter&lt;/th&gt;
      &lt;th&gt;Nilai&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Jarak serat maksimum&lt;/td&gt;
      &lt;td&gt;20 km&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Differential distance maksimum&lt;/td&gt;
      &lt;td&gt;20 km&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Logical reach maksimum&lt;/td&gt;
      &lt;td&gt;60 km&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Ringkasan ITU G.984.6 menyebut perangkat penyambung (regenerator atau penguat) untuk jangkauan sampai 60 km. Dari dua sumber itu saya menyimpulkan bahwa jangkauan di atas 20 km butuh perangkat tambahan.&lt;/p&gt;

&lt;p&gt;Yang menentukan sebenarnya adalah budget loss. Omada mencatat kelas optik B+ dengan anggaran maksimum 28 dB dan kelas C+ dengan 32 dB. Sensitivitas penerimanya masing-masing -28 dBm dan -32 dBm, dan itu nilai terpisah dari anggaran. Semakin besar split ratio, semakin besar redaman splitter, dan semakin sedikit sisa anggaran untuk panjang serat dan konektor. Artinya 1:64 pada 20 km tidak otomatis bisa jalan. Hitung budget lossnya.&lt;/p&gt;

&lt;h2 id=&quot;cara-kerja-downstream-upstream-dan-ranging&quot;&gt;Cara kerja: downstream, upstream, dan ranging&lt;/h2&gt;

&lt;p&gt;Karena splitter pasif membagi cahaya yang sama ke semua cabang, tiap ONT menerima aliran downstream yang sama. Cisco mencatat downstream dienkripsi dengan AES-128 tanpa tambahan overhead bandwidth. Enkripsi ini relevan karena aliran downstream yang sama sampai ke semua ONT (ini penalaran saya, bukan kutipan Cisco).&lt;/p&gt;

&lt;p&gt;Upstream lebih rumit, karena banyak ONT berbagi satu serat. Menurut Cisco (dan G.984.3 untuk cakupan TDMA dan DBA), solusinya TDMA: tiap ONT mengirim dalam burst pada slot yang ditentukan OLT. Rinciannya, menurut Cisco:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;OLT memantau kongesti dan membagi slot upstream lewat DBA (dynamic bandwidth assignment). Informasi slot dikirim lewat BWmap di tiap frame downstream. Alokasi statis juga bisa.&lt;/li&gt;
  &lt;li&gt;Ranging: OLT mengukur round-trip delay tiap ONU dan menetapkan equalization delay, supaya frame upstream dari ONT yang dekat dan jauh tidak bertabrakan.&lt;/li&gt;
  &lt;li&gt;Data pengguna dibungkus dalam GEM (GPON Encapsulation Method), yaitu bingkai berorientasi koneksi yang bisa difragmentasi. Di upstream, GEM port dipetakan ke T-CONT, wadah antrean yang dilayani sesuai DBA.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Frame downstream berdurasi 125 mikrodetik, menurut Cisco.&lt;/p&gt;

&lt;h2 id=&quot;fungsi-dan-manfaat&quot;&gt;Fungsi dan manfaat&lt;/h2&gt;

&lt;p&gt;Fungsi utama GPON adalah menghantarkan broadband lewat fiber sampai ke pelanggan (FTTH). Satu port OLT melayani banyak ONT, jadi satu jaringan distribusi dipakai bersama. Seberapa cepat internet rumah di Indonesia saat ini dibanding target pemerintah saya bahas di &lt;a href=&quot;/2026/11/03/target-100-mbps-fixed-broadband-indonesia&quot;&gt;target 100 Mbps fixed broadband&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;gpon-dibanding-satu-serat-per-pelanggan&quot;&gt;GPON dibanding satu serat per pelanggan&lt;/h3&gt;

&lt;p&gt;Perbandingan ini penalaran teknis dari arsitektur di atas, bukan data biaya. Saya tidak menemukan sumber yang memberi angka penghematan, jadi tidak ada persentase di sini.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Aspek&lt;/th&gt;
      &lt;th&gt;Satu serat per pelanggan (point-to-point)&lt;/th&gt;
      &lt;th&gt;GPON (point-to-multipoint)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Serat dari pusat&lt;/td&gt;
      &lt;td&gt;Satu serat per pelanggan&lt;/td&gt;
      &lt;td&gt;Satu serat feeder dibagi lewat splitter&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Port di sisi operator&lt;/td&gt;
      &lt;td&gt;Satu port per pelanggan&lt;/td&gt;
      &lt;td&gt;Satu port OLT untuk banyak ONT&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Jalur distribusi&lt;/td&gt;
      &lt;td&gt;Tanpa splitter&lt;/td&gt;
      &lt;td&gt;Splitter pasif, tanpa catu daya&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Kapasitas link&lt;/td&gt;
      &lt;td&gt;Khusus per pelanggan&lt;/td&gt;
      &lt;td&gt;Dibagi antar-ONT di satu port&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Dari tabel itu, manfaatnya (sebagai penalaran): serat feeder dari pusat lebih sedikit, port OLT yang terpakai lebih sedikit, dan jalur distribusi pasif tidak butuh catu daya aktif di lapangan. Upstream dibagi antar-ONT lewat TDMA dan DBA, sedangkan downstream berupa satu aliran bersama, jadi kapasitas tidak dikunci per pelanggan.&lt;/p&gt;

&lt;p&gt;Harga dari pembagian itu adalah kapasitas bersama. Sebagai gambaran kasar: satu port PON dengan 32 ONT yang semuanya aktif bersamaan dan dibagi rata memberi sekitar 77,76 Mbit/s downstream per ONT (2,48832 Gbit/s dibagi 32) dan sekitar 38,88 Mbit/s upstream (1,24416 Gbit/s dibagi 32). Angka itu belum dikurangi overhead. Di lapangan tidak semua ONT aktif bersamaan dan DBA membagi slot sesuai kebutuhan, jadi anggap ini hanya perkiraan kasus ramai.&lt;/p&gt;

&lt;h2 id=&quot;konektor-dan-pengukuran-di-lapangan&quot;&gt;Konektor dan pengukuran di lapangan&lt;/h2&gt;

&lt;p&gt;Konektor di jaringan PON umumnya memakai polish APC (hijau). Alasannya dibahas di artikel konektor: &lt;a href=&quot;/2026/11/03/jenis-jenis-konektor-fiber-optic&quot;&gt;pembahasan UPC vs APC&lt;/a&gt; menjelaskan return loss APC sekitar 60 dB atau lebih dan kenapa APC lazim di PON/FTTx dengan overlay video. Tapi saya tidak menemukan standar yang mewajibkan APC, jadi ini praktik industri.&lt;/p&gt;

&lt;p&gt;Untuk pengukuran, ada power meter khusus PON yang memeriksa panjang gelombang 1310, 1490, dan 1550 nm secara in-service. Saya hanya menemukan spesifikasi produk vendor untuk ini, jadi cek datasheet alat yang kamu pakai.&lt;/p&gt;

&lt;p&gt;Untuk OTDR, menguji lewat splitter memerlukan perhatian khusus. Sebuah artikel Yokogawa tentang OTDR untuk PON (dimuat di EPDT, 13 Oktober 2009) menyebut pengujian in-service memakai panjang gelombang 1625 nm dengan filter.&lt;/p&gt;

&lt;h2 id=&quot;gpon-dan-penerusnya&quot;&gt;GPON dan penerusnya&lt;/h2&gt;

&lt;p&gt;GPON bukan ujung jalan. ITU-T punya standar penerus yang memakai prinsip PON yang sama:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Standar&lt;/th&gt;
      &lt;th&gt;Nama&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;G.987.1&lt;/td&gt;
      &lt;td&gt;XG-PON&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;G.9807.1&lt;/td&gt;
      &lt;td&gt;10-Gigabit-capable symmetric passive optical network (XGS-PON)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;G.989.1&lt;/td&gt;
      &lt;td&gt;40-Gigabit-capable passive optical networks (NG-PON2)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Untuk teknisi yang baru mulai, pahami dulu GPON. Prinsip PON yang sama (OLT, ODN, ONT, splitter pasif) dipakai oleh standar penerusnya, jadi pemahaman ini berguna lebih jauh.&lt;/p&gt;

&lt;h2 id=&quot;sumber&quot;&gt;Sumber&lt;/h2&gt;

&lt;p&gt;Banyak angka detail di atas berasal dari dokumentasi vendor (Cisco, Omada) karena teks lengkap G.984.1 dan G.984.2 tidak bisa saya baca. Untuk desain atau pengadaan, cek ke rekomendasi ITU-T dan datasheet perangkat.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://cisco.com/c/en/us/support/docs/switches/catalyst-pon-series/216230-understand-gpon-technology.html&quot;&gt;Cisco, Understand GPON Technology&lt;/a&gt; (Rev 3.0, 6 Desember 2023)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://support.omadanetworks.com/baltic/document/112365/&quot;&gt;Omada, dokumentasi optical class PON&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.itu.int/rec/T-REC-G.984.1-200803-I/en&quot;&gt;ITU-T G.984.1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.itu.int/rec/T-REC-G.984.2-201908-I/en&quot;&gt;ITU-T G.984.2&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.itu.int/rec/T-REC-G.984.3-201401-I/en&quot;&gt;ITU-T G.984.3&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.itu.int/rec/T-REC-G.984.4&quot;&gt;ITU-T G.984.4&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.itu.int/rec/T-REC-G.984.5-202202-I/en&quot;&gt;ITU-T G.984.5&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.itu.int/dms_pubrec/itu-t/rec/g/T-REC-G.984.6-200803-I!!SUM-HTM-E.htm&quot;&gt;ITU-T G.984.6&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.itu.int/rec/T-REC-G.987.1&quot;&gt;ITU-T G.987.1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.itu.int/rec/T-REC-G.9807.1&quot;&gt;ITU-T G.9807.1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.itu.int/rec/T-REC-G.989.1&quot;&gt;ITU-T G.989.1&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.epdtonthenet.net/article/28695/OTDR-for-PON-testing.aspx&quot;&gt;Yokogawa, OTDR for PON testing&lt;/a&gt; (dimuat di EPDT, 13 Oktober 2009)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Penulis: &lt;a href=&quot;/about&quot;&gt;Mahyuddin Susanto&lt;/a&gt;. Koreksi atau tambahan bisa dikirim lewat &lt;a href=&quot;/contact&quot;&gt;halaman kontak&lt;/a&gt;.&lt;/p&gt;</content><author><name>Mahyuddin Susanto</name></author><category term="Komputer" /><category term="gpon" /><category term="ftth" /><category term="fiber optic" /><category term="networking" /><category term="pon" /><summary type="html">Kalau kamu pernah melihat kotak kecil berlampu di rumah pelanggan fiber, itu ujung dari sebuah jaringan GPON. Di seberangnya, entah beberapa kilometer jauhnya, ada satu perangkat yang melayani puluhan kotak seperti itu lewat satu serat. Di antaranya hanya ada kaca dan splitter, tanpa listrik.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.udienz.web.id/img/mengenal-gpon-arsitektur.png" /><media:content medium="image" url="https://www.udienz.web.id/img/mengenal-gpon-arsitektur.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Target 100 Mbps Fixed Broadband: Kenapa Masih Jauh</title><link href="https://www.udienz.web.id/2026/11/03/target-100-mbps-fixed-broadband-indonesia" rel="alternate" type="text/html" title="Target 100 Mbps Fixed Broadband: Kenapa Masih Jauh" /><published>2026-11-03T00:00:00+00:00</published><updated>2026-11-03T00:00:00+00:00</updated><id>https://www.udienz.web.id/2026/11/03/target-100-mbps-fixed-broadband-indonesia</id><content type="html" xml:base="https://www.udienz.web.id/2026/11/03/target-100-mbps-fixed-broadband-indonesia">&lt;p&gt;Target 100 Mbps untuk fixed broadband bisa terbaca seolah itu kecepatan yang dijanjikan ke setiap rumah. Faktanya itu target rata-rata nasional dengan tenggat 2028 atau 2029, jadi belum ada yang gagal. Jaraknya ke 100 Mbps memang masih lebar: median fixed broadband Indonesia pada Agustus 2026 ada di 51,4 Mbps menurut Ookla, peringkat ke-113 dunia dan ke-9 dari 10 negara ASEAN.&lt;/p&gt;

&lt;p&gt;Tulisan ini menjelaskan apa yang sebenarnya ditargetkan, apa yang menghambatnya, dan apa artinya untuk paket internet di rumahmu. Fixed broadband di sini berarti internet rumah berkabel (di berita sering ditulis “internet tetap” atau “pita lebar tetap”). Beberapa angka dari berita saling bertentangan, jadi tiap angka saya sebut lengkap dengan sumbernya, apakah dokumen resmi atau pemberitaan.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/target-100-mbps-fixed-broadband.png&quot; alt=&quot;Dua batang perbandingan: median fixed broadband Indonesia 51,4 Mbps dan target Komdigi 100 Mbps&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Median Ookla Agustus 2026 dan target rata-rata Komdigi tidak diukur dengan metode yang sama.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;Key Takeaways&lt;/strong&gt;&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;100 Mbps adalah target rata-rata nasional di akhir periode Renstra Komdigi. Sebagian sumber menyebut tahun 2029, Wakil Menteri Komdigi menyebut 2028.&lt;/li&gt;
    &lt;li&gt;Median Ookla (51,4 Mbps, Agustus 2026) dan hasil ukur Komdigi (51,84 Mbps di 20 kota, 2025) memakai metode berbeda. Jangan dibandingkan langsung.&lt;/li&gt;
    &lt;li&gt;Hambatan yang disebut pelaku industri dan laporan Komdigi: jangkauan fiber yang belum merata, aturan dan retribusi daerah, harga bahan kabel yang naik, dan harga langganan yang masih tinggi untuk banyak rumah tangga.&lt;/li&gt;
    &lt;li&gt;Dua paket 100 Mbps berbayar penuh yang dibandingkan Bisnis.com berharga Rp233 ribu dan Rp279 ribu per bulan sebelum pajak pertambahan nilai (PPN), per Januari 2026.&lt;/li&gt;
    &lt;li&gt;Kecepatan di perangkatmu tetap ditentukan ONT (perangkat fiber di rumah), WiFi, dan kabel.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;apa-sebenarnya-yang-ditargetkan&quot;&gt;Apa sebenarnya yang ditargetkan?&lt;/h2&gt;

&lt;p&gt;Target kecepatan ada di Rencana Strategis (Renstra) Kementerian Komunikasi dan Digital 2025–2029. Laporan Kinerja Komdigi 2025 memuat indikator “Kecepatan Internet Jaringan Pita Lebar Tetap (Fixed Broadband)” dengan target 2025 sebesar 37 Mbps (&lt;a href=&quot;https://eppid.komdigi.go.id/attachments/cb1d2d05a0d09902a340a09882b2eae56e6462ed88f3e3f688372c5053ed086a/fa1898f3b7f2672c03afd8682a6187d1ece86d3114c6a1a52d8a51fe86a81ae0.pdf&quot;&gt;Kementerian Komdigi, Laporan Kinerja 2025&lt;/a&gt;, tabel indikator program, hlm. 90). Target tahun-tahun berikutnya tidak terbaca jelas di dokumen itu, jadi untuk 2026 sampai 2029 rujukannya pemberitaan, dan dua media menulis jalur yang berbeda:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Tahun&lt;/th&gt;
      &lt;th&gt;detikInet (7 Jan 2026)&lt;/th&gt;
      &lt;th&gt;Bisnis.com (5 Jan 2026)&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2026&lt;/td&gt;
      &lt;td&gt;45 Mbps&lt;/td&gt;
      &lt;td&gt;45 Mbps&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2027&lt;/td&gt;
      &lt;td&gt;64 Mbps&lt;/td&gt;
      &lt;td&gt;55 Mbps&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2028&lt;/td&gt;
      &lt;td&gt;83 Mbps&lt;/td&gt;
      &lt;td&gt;70 Mbps&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2029&lt;/td&gt;
      &lt;td&gt;100 Mbps&lt;/td&gt;
      &lt;td&gt;100 Mbps&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Sumber: &lt;a href=&quot;https://inet.detik.com/law-and-policy/d-8295938/prabowo-target-kecepatan-internet-mobile-60-mbps-dan-fixed-45-mbps&quot;&gt;detikInet&lt;/a&gt; dan &lt;a href=&quot;https://teknologi.bisnis.com/read/20260105/101/1941746/target-komdigi-2026-rerata-kecepatan-seluler-60-mbps-fixed-broadband-45-mbps&quot;&gt;Bisnis.com&lt;/a&gt;. Keduanya sepakat di 45 Mbps untuk 2026 dan 100 Mbps untuk 2029, tapi jalur di tengahnya berbeda.&lt;/p&gt;

&lt;p&gt;Tahun tercapainya 100 Mbps juga belum seragam. Sekretaris Jenderal Komdigi menyebut “secepatnya 2029” (&lt;a href=&quot;https://teknologi.bisnis.com/read/20251210/101/1935763/strategi-komdigi-kejar-target-rerata-kecepatan-internet-100-mbps-pada-2029&quot;&gt;Bisnis.com, 10 Desember 2025&lt;/a&gt;). Wakil Menteri Nezar Patria menyebut target nasional 100 Mbps dalam dua tahun, yaitu 2028, dalam berita Juli 2026 yang tidak membedakan fixed dan mobile (&lt;a href=&quot;https://teknologi.bisnis.com/read/20260705/101/1985643/komdigi-bidik-kecepatan-internet-nasional-100-mbps-pada-2028&quot;&gt;Bisnis.com, 5 Juli 2026&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Kalau kamu menemukan judul berita yang menulis “64 Mbps di 2026”, baca isinya dulu. Judul Selular.ID pada Maret 2026 menulis 64 Mbps, sementara isi artikelnya menyebut minimum 60 Mbps (&lt;a href=&quot;https://selular.id/2026/03/komdigi-targetkan-kecepatan-internet-fixed-broadband-64-mbps-2026-isp-katakan-ini/&quot;&gt;Selular.ID&lt;/a&gt;).&lt;/p&gt;

&lt;h2 id=&quot;seberapa-jauh-jaraknya-sekarang&quot;&gt;Seberapa jauh jaraknya sekarang?&lt;/h2&gt;

&lt;p&gt;Ookla Speedtest Global Index mencatat median download fixed broadband Indonesia 51,40 Mbps pada Agustus 2026, peringkat 113 dunia dan ke-9 dari 10 negara ASEAN (&lt;a href=&quot;https://teknologi.bisnis.com/read/20261014/101/2012346/peringkat-kecepatan-internet-ri-merangkak-di-global-agustus-2026-berkat-5g&quot;&gt;Bisnis.com, 14 Oktober 2026&lt;/a&gt;, mengutip Ookla).&lt;/p&gt;

&lt;p&gt;Komdigi punya angka sendiri. Laporan Kinerja 2025 menulis rata-rata kecepatan unduh fixed broadband nasional 51,84 Mbps, diukur di 20 kota, dan menyatakan angka itu melampaui target 2025 sebesar 37 Mbps (hlm. 106). Di bagian latar belakang laporan yang sama, rata-rata fixed broadband tertulis 28,37 Mbps dengan merujuk ke Renstra (&lt;a href=&quot;https://eppid.komdigi.go.id/attachments/cb1d2d05a0d09902a340a09882b2eae56e6462ed88f3e3f688372c5053ed086a/fa1898f3b7f2672c03afd8682a6187d1ece86d3114c6a1a52d8a51fe86a81ae0.pdf&quot;&gt;Laporan Kinerja Komdigi 2025&lt;/a&gt;, hlm. 20).&lt;/p&gt;

&lt;p&gt;Angka-angka itu kelihatannya sama padahal berbeda:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Median Ookla&lt;/strong&gt;: dari tes yang dijalankan pengguna aplikasi Speedtest.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Rata-rata Komdigi&lt;/strong&gt;: hasil pengukuran di 20 kota, tidak mencakup wilayah di luar kota-kota itu.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Rata-rata di Renstra&lt;/strong&gt;: angka latar belakang yang metodenya tidak dijelaskan di laporan.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dengan 100 Mbps sebagai garis akhir, selisihnya tetap besar, tapi seberapa besar tergantung angka mana yang dipakai. Median Ookla Agustus 2026 (51,4 Mbps) memang sudah di atas target rata-rata 2026 sebesar 45 Mbps, tapi keduanya mengukur hal berbeda, jadi saya tidak menyimpulkan target 2026 sudah terlampaui. Karena itu saya menahan diri untuk menulis satu angka “kecepatan internet Indonesia”.&lt;/p&gt;

&lt;p&gt;Untuk gambaran regional, data Februari 2026 yang dikutip &lt;a href=&quot;https://seasia.co/2026/04/20/asean-internet-speeds-index-february-2026-big-condolences-to-indonesian-users&quot;&gt;Seasia.co&lt;/a&gt; dari Ookla menaruh Indonesia di posisi terakhir dari sembilan negara ASEAN yang datanya tersedia (Myanmar tidak termasuk), dengan 45,4 Mbps. Singapura ada di puncak dengan 420,92 Mbps.&lt;/p&gt;

&lt;figure class=&quot;blog-chart&quot;&gt;
&lt;svg viewBox=&quot;0 0 400 350&quot; style=&quot;width: 100%; max-width: 560px; height: auto;&quot; role=&quot;img&quot; aria-label=&quot;Diagram batang median kecepatan unduh fixed broadband ASEAN, Februari 2026, menurut Ookla via Seasia.co. Singapura 420,92 Mbps, Vietnam 288,76, Thailand 273,78, Malaysia 166,23, Filipina 106,5, Brunei 86,46, Laos 54,78, Kamboja 51,86, Indonesia 45,4. Myanmar tidak termasuk.&quot;&gt;
  &lt;text x=&quot;200&quot; y=&quot;24&quot; text-anchor=&quot;middle&quot; font-size=&quot;16&quot; fill=&quot;currentColor&quot;&gt;Median fixed broadband ASEAN (Mbps)&lt;/text&gt;
  &lt;text x=&quot;200&quot; y=&quot;44&quot; text-anchor=&quot;middle&quot; font-size=&quot;12&quot; fill=&quot;currentColor&quot;&gt;Februari 2026, data Ookla Speedtest Global Index&lt;/text&gt;
  &lt;line x1=&quot;96&quot; y1=&quot;60&quot; x2=&quot;96&quot; y2=&quot;330&quot; stroke=&quot;#9ca3af&quot;&gt;&lt;/line&gt;
&lt;text x=&quot;88&quot; y=&quot;81&quot; text-anchor=&quot;end&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Singapura&lt;/text&gt;
&lt;rect x=&quot;96&quot; y=&quot;66&quot; width=&quot;200.0&quot; height=&quot;20&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;302.0&quot; y=&quot;81&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;420,92&lt;/text&gt;
&lt;text x=&quot;88&quot; y=&quot;111&quot; text-anchor=&quot;end&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Vietnam&lt;/text&gt;
&lt;rect x=&quot;96&quot; y=&quot;96&quot; width=&quot;137.2&quot; height=&quot;20&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;239.2&quot; y=&quot;111&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;288,76&lt;/text&gt;
&lt;text x=&quot;88&quot; y=&quot;141&quot; text-anchor=&quot;end&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Thailand&lt;/text&gt;
&lt;rect x=&quot;96&quot; y=&quot;126&quot; width=&quot;130.1&quot; height=&quot;20&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;232.1&quot; y=&quot;141&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;273,78&lt;/text&gt;
&lt;text x=&quot;88&quot; y=&quot;171&quot; text-anchor=&quot;end&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Malaysia&lt;/text&gt;
&lt;rect x=&quot;96&quot; y=&quot;156&quot; width=&quot;79.0&quot; height=&quot;20&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;181.0&quot; y=&quot;171&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;166,23&lt;/text&gt;
&lt;text x=&quot;88&quot; y=&quot;201&quot; text-anchor=&quot;end&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Filipina&lt;/text&gt;
&lt;rect x=&quot;96&quot; y=&quot;186&quot; width=&quot;50.6&quot; height=&quot;20&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;152.6&quot; y=&quot;201&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;106,5&lt;/text&gt;
&lt;text x=&quot;88&quot; y=&quot;231&quot; text-anchor=&quot;end&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Brunei&lt;/text&gt;
&lt;rect x=&quot;96&quot; y=&quot;216&quot; width=&quot;41.1&quot; height=&quot;20&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;143.1&quot; y=&quot;231&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;86,46&lt;/text&gt;
&lt;text x=&quot;88&quot; y=&quot;261&quot; text-anchor=&quot;end&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Laos&lt;/text&gt;
&lt;rect x=&quot;96&quot; y=&quot;246&quot; width=&quot;26.0&quot; height=&quot;20&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;128.0&quot; y=&quot;261&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;54,78&lt;/text&gt;
&lt;text x=&quot;88&quot; y=&quot;291&quot; text-anchor=&quot;end&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Kamboja&lt;/text&gt;
&lt;rect x=&quot;96&quot; y=&quot;276&quot; width=&quot;24.6&quot; height=&quot;20&quot; rx=&quot;4&quot; fill=&quot;#38bdf8&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;126.6&quot; y=&quot;291&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;51,86&lt;/text&gt;
&lt;text x=&quot;88&quot; y=&quot;321&quot; text-anchor=&quot;end&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;Indonesia&lt;/text&gt;
&lt;rect x=&quot;96&quot; y=&quot;306&quot; width=&quot;21.6&quot; height=&quot;20&quot; rx=&quot;4&quot; fill=&quot;#f97316&quot; stroke=&quot;currentColor&quot;&gt;&lt;/rect&gt;
&lt;text x=&quot;123.6&quot; y=&quot;321&quot; font-size=&quot;14&quot; fill=&quot;currentColor&quot;&gt;45,4&lt;/text&gt;
&lt;/svg&gt;
&lt;figcaption&gt;Sumber: &lt;a href=&quot;https://seasia.co/2026/04/20/asean-internet-speeds-index-february-2026-big-condolences-to-indonesian-users&quot;&gt;Seasia.co, mengutip Ookla&lt;/a&gt;, 20 April 2026. Batang oranye: Indonesia.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Grafik ini memakai median, bukan rata-rata. Seasia.co mengutip Ookla, jadi anggap ini gambaran kasar. Angka Indonesia di sini (Februari) berbeda dari 51,4 Mbps karena periodenya.&lt;/p&gt;

&lt;h2 id=&quot;apa-yang-menghambat&quot;&gt;Apa yang menghambat?&lt;/h2&gt;

&lt;p&gt;Tidak ada satu penyebab tunggal. Hambatannya berlapis.&lt;/p&gt;

&lt;h3 id=&quot;banyak-rumah-belum-terjangkau-dan-banyak-yang-terjangkau-belum-berlangganan&quot;&gt;Banyak rumah belum terjangkau, dan banyak yang terjangkau belum berlangganan&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://eppid.komdigi.go.id/attachments/cb1d2d05a0d09902a340a09882b2eae56e6462ed88f3e3f688372c5053ed086a/fa1898f3b7f2672c03afd8682a6187d1ece86d3114c6a1a52d8a51fe86a81ae0.pdf&quot;&gt;Laporan Kinerja Komdigi 2025&lt;/a&gt; mengutip data Bank Dunia 2024 (hlm. 19–20) tentang 75 juta rumah di Indonesia:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;38 juta rumah sudah dilewati jaringan fiber optik.&lt;/li&gt;
  &lt;li&gt;Dari jumlah itu, 24,5 juta belum terhubung ke layanan fixed broadband.&lt;/li&gt;
  &lt;li&gt;Sisanya, 37 juta rumah, belum terjangkau fiber sama sekali.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dengan hitungan sederhana, yang sudah terhubung sekitar 13,5 juta rumah. Angka itu tidak sebanding dengan 21% rumah tangga di bawah, karena tahun dan basis hitungnya berbeda.&lt;/p&gt;

&lt;p&gt;Di tingkat kecamatan, jangkauan fiber mencapai 72,12% pada 2025 menurut laporan (5.253 dari 7.285 kecamatan, hlm. 106; hasil bagi langsungnya 72,11%), naik dari 70,88% di baseline Renstra (hlm. 19).&lt;/p&gt;

&lt;p&gt;Targetnya 90% kecamatan (&lt;a href=&quot;https://teknologi.bisnis.com/read/20251001/101/1916328/komdigi-targetkan-penetrasi-fixed-broadband-naik-dari-21-menjadi-50-pada-2029&quot;&gt;Bisnis.com, 1 Oktober 2025&lt;/a&gt;). Dari angka itu saya menyimpulkan tidak semua kecamatan ditargetkan terlayani fiber.&lt;/p&gt;

&lt;p&gt;Sekjen Komdigi menilai membangun fiber sampai ke semua kecamatan tidak efisien dan menyebut seluler dan satelit sebagai alternatif di wilayah yang sulit (&lt;a href=&quot;https://teknologi.bisnis.com/read/20251210/101/1935763/strategi-komdigi-kejar-target-rerata-kecepatan-internet-100-mbps-pada-2029&quot;&gt;Bisnis.com, 10 Desember 2025&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Soal berlangganan, Menteri Komdigi menyebut baru 21% rumah tangga yang punya akses broadband tetap, dengan target 50% pada 2029 (&lt;a href=&quot;https://teknologi.bisnis.com/read/20251001/101/1916328/komdigi-targetkan-penetrasi-fixed-broadband-naik-dari-21-menjadi-50-pada-2029&quot;&gt;Bisnis.com, 1 Oktober 2025&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Survei Asosiasi Penyelenggara Jasa Internet Indonesia (APJII) 2026 menghitung sekitar 99,51 juta orang berlangganan internet tetap, atau 42,3% dari pengguna internet (&lt;a href=&quot;https://teknologi.bisnis.com/read/20260617/101/1981302/penetrasi-internet-tetap-di-ri-baru-423-ruang-pertumbuhan-masih-lebar&quot;&gt;Bisnis.com, 17 Juni 2026&lt;/a&gt;). Angka 21% dan 42,3% tidak bisa dipertukarkan karena basis hitungnya beda: rumah tangga di satu sisi, pengguna internet di sisi lain.&lt;/p&gt;

&lt;h3 id=&quot;biaya-bangun-dan-aturan-di-daerah&quot;&gt;Biaya bangun dan aturan di daerah&lt;/h3&gt;

&lt;p&gt;Asosiasi Penyelenggara Jaringan Telekomunikasi Indonesia (APJATEL) menyoroti aturan yang tumpang tindih. Menurut Wakil Ketua APJATEL Fariz Azhar Harahap, tiap kota atau kabupaten punya dasar hukum sendiri. Pelaku usaha menanggung beberapa pungutan:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;BHP Pita dan BHP USO di tingkat pusat (pungutan atas pita frekuensi dan kontribusi pelayanan universal).&lt;/li&gt;
  &lt;li&gt;Sewa aset negara atau daerah (BMN/BMD).&lt;/li&gt;
  &lt;li&gt;Retribusi penempatan kabel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Di sejumlah kota, sewa lahan bahkan disamakan dengan ruang komersial. Artikelnya tidak menyebut nominal rupiah (&lt;a href=&quot;https://investortrust.id/business/94447/internet-lambat-dan-mahal-apjatel-soroti-tumpang-tindih-aturan-fiber-optik&quot;&gt;investortrust.id, 13 Februari 2026&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Bahan baku ikut menekan. Menurut &lt;a href=&quot;https://teknologi.bisnis.com/read/20260415/101/1966687/harga-kabel-serat-optik-melesat-ekspansi-internet-nasional-berisiko-melambat&quot;&gt;Bisnis.com&lt;/a&gt;, Ketua Umum APJATEL Jerry Mangasas Swandy menyebut harga HDPE, material pelindung kabel, naik 15–17%. Ketua Umum APJII Muhammad Arif menyebut kenaikan harga paling terasa di fiber core, tanpa angka persen. Artikel itu menjelaskan sebabnya sebagai pasokan serat optik global yang dialihkan ke industri militer, termasuk drone, ditambah keterbatasan produksi di China.&lt;/p&gt;

&lt;p&gt;Artikel yang sama mengutip contoh sebuah perusahaan yang tadinya membangun 50 km per tahun dan kini mungkin hanya sekitar 10 km dengan anggaran yang sama. Perusahaannya tidak disebut dan hitungannya tidak dijelaskan, jadi anggap itu ilustrasi kasar (&lt;a href=&quot;https://teknologi.bisnis.com/read/20260415/101/1966687/harga-kabel-serat-optik-melesat-ekspansi-internet-nasional-berisiko-melambat&quot;&gt;Bisnis.com, 15 April 2026&lt;/a&gt;). Pengamat ICT Institute menambahkan hak jalan dan relokasi kabel ke bawah tanah sebagai beban yang menggerus margin operator (&lt;a href=&quot;https://teknologi.bisnis.com/read/20260826/101/1999077/tantangan-bisnis-serat-optik-pengamat-utilisasi-aset-hingga-beban-relokasi&quot;&gt;Bisnis.com, 26 Agustus 2026&lt;/a&gt;).&lt;/p&gt;

&lt;h3 id=&quot;harga-langganan-dan-permintaan&quot;&gt;Harga langganan dan permintaan&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://eppid.komdigi.go.id/attachments/cb1d2d05a0d09902a340a09882b2eae56e6462ed88f3e3f688372c5053ed086a/fa1898f3b7f2672c03afd8682a6187d1ece86d3114c6a1a52d8a51fe86a81ae0.pdf&quot;&gt;Laporan Kinerja Komdigi&lt;/a&gt; mencatat harga layanan fixed broadband di Indonesia sekitar 4,86% dari pendapatan nasional bruto per kapita (hlm. 20). Rekomendasi ITU (badan telekomunikasi PBB) yang dikutip laporan itu adalah tidak lebih dari 2%. Untuk mobile broadband angkanya sekitar 0,24%. Laporan itu sendiri menyimpulkan itulah salah satu alasan penetrasi seluler jauh lebih tinggi.&lt;/p&gt;

&lt;p&gt;Alasan dari sisi calon pelanggan sejalan. Dalam survei APJII 2026, 47,2% yang tidak berlangganan internet tetap merasa kualitas internet seluler sudah cukup, dan 32,9% menyebut harga terlalu mahal (&lt;a href=&quot;https://teknologi.bisnis.com/read/20260617/101/1981302/penetrasi-internet-tetap-di-ri-baru-423-ruang-pertumbuhan-masih-lebar&quot;&gt;Bisnis.com, 17 Juni 2026&lt;/a&gt;). Saya menduga, kalau permintaan akan paket kencang rendah, operator punya alasan lebih kecil untuk membangun cepat. Ini dugaan saya, tidak ada sumber di atas yang menyatakannya langsung.&lt;/p&gt;

&lt;h3 id=&quot;standar-minimum-100-mbps-yang-pernah-disiapkan&quot;&gt;Standar minimum 100 Mbps yang pernah disiapkan&lt;/h3&gt;

&lt;p&gt;Pada Januari 2024, Kementerian Kominfo (sekarang Komdigi) pernah menyiapkan standar minimum 100 Mbps untuk fixed broadband. Direktur Jenderal Informasi dan Komunikasi Publik saat itu menyatakan penerapannya sangat tergantung kesiapan industri dan tidak akan dipaksakan kalau industri belum siap (&lt;a href=&quot;https://teknologi.bisnis.com/read/20240125/101/1735592/internet-fixed-broadband-100-mbps-kemenkominfo-tergantung-kesiapan-industri&quot;&gt;Bisnis.com, 25 Januari 2024&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Ada satu kewajiban yang mendekati, tapi bukan standar minimum untuk paket rumahan. Pada lelang pita frekuensi 1,4 GHz, Komdigi menyebut pemenang harus menyediakan akses pita lebar nirkabel dengan kecepatan “sampai dengan” 100 Mbps, dengan harga paling tinggi 10% di atas rata-rata konsumsi rumah tangga (&lt;a href=&quot;https://teknologi.bisnis.com/read/20250803/101/1898837/komdigi-ungkap-sederet-kewajiban-pemenang-lelang-14-ghz&quot;&gt;Bisnis.com, 3 Agustus 2025&lt;/a&gt;). Kewajiban itu berlaku selama masa izin pita frekuensi dan mengikat pemenang lelang, bukan semua penyedia internet.&lt;/p&gt;

&lt;h2 id=&quot;apa-artinya-buat-kamu-di-rumah&quot;&gt;Apa artinya buat kamu di rumah?&lt;/h2&gt;

&lt;p&gt;Pertama, target rata-rata tidak menjamin apa pun untuk satu rumah. Kamu bisa berada di atas atau di bawah angkanya, tergantung jangkauan ISP di lokasimu, jenis paketnya, dan kondisi jaringan di dalam rumah.&lt;/p&gt;

&lt;p&gt;Kedua, paket 100 Mbps sudah ada, dan harganya tidak seragam. Berikut perbandingan dari Bisnis.com per Januari 2026, yang diambil dari situs masing-masing penyedia:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Paket&lt;/th&gt;
      &lt;th&gt;Kecepatan&lt;/th&gt;
      &lt;th&gt;Harga per bulan&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Internet Rakyat&lt;/td&gt;
      &lt;td&gt;hingga 100 Mbps&lt;/td&gt;
      &lt;td&gt;Rp100.000 (bulan pertama gratis)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;MyRepublic Neo&lt;/td&gt;
      &lt;td&gt;100 Mbps&lt;/td&gt;
      &lt;td&gt;Rp233.100 (belum PPN)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;IndiHome&lt;/td&gt;
      &lt;td&gt;75 Mbps&lt;/td&gt;
      &lt;td&gt;Rp270.000&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;XL Satu&lt;/td&gt;
      &lt;td&gt;100 Mbps&lt;/td&gt;
      &lt;td&gt;Rp279.000 (belum PPN)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Sumber: &lt;a href=&quot;https://teknologi.bisnis.com/read/20260129/101/1948332/harga-internet-rumah-2026-internet-rakyat-vs-myrepublic-vs-indihome-vs-xlsatu&quot;&gt;Bisnis.com, 29 Januari 2026&lt;/a&gt;. Dua paket tercatat belum termasuk PPN, sedangkan basis harga dua lainnya tidak disebut, jadi jangan membandingkan angkanya mentah-mentah. IndiHome di tabel ini 75 Mbps. Internet Rakyat memakai kata “hingga”, yaitu batas atas dan bukan kecepatan yang dijamin, makanya saya tidak memasukkannya ke kisaran Rp233 ribu dan Rp279 ribu yang saya sebut di Key Takeaways. Harga dan promo berubah cepat, jadi cek ulang di situs penyedia sebelum memutuskan.&lt;/p&gt;

&lt;p&gt;Ketiga, kalau kamu sudah berlangganan 100 Mbps tapi hasilnya jauh lebih rendah, periksa dulu sisi rumah sebelum menyalahkan penyedia internet (ISP):&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Tes dengan kabel.&lt;/strong&gt; Colok laptop langsung ke port LAN ONT (perangkat fiber di rumahmu) atau router dan jalankan tes kecepatan. Kalau angkanya jauh lebih tinggi daripada lewat WiFi, masalahnya ada di WiFi.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Cek port.&lt;/strong&gt; Port Fast Ethernet (100 Mbps) di salah satu perangkat pada jalur itu menjadi batas atas, dan hasil nyatanya biasanya di bawah 100 Mbps. Cari port Gigabit.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Tes di jam berbeda.&lt;/strong&gt; Kalau angkanya turun terus di jam padat, catat waktunya sebagai bahan laporan.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Lihat redaman optik&lt;/strong&gt; di ONT bila kamu bisa mengaksesnya. Konsep dasarnya ada di tulisan saya tentang &lt;a href=&quot;/2026/11/03/mengenal-gpon-fungsi-manfaat-arsitektur&quot;&gt;arsitektur GPON&lt;/a&gt;, dan soal konektor ada di &lt;a href=&quot;/2026/11/03/jenis-jenis-konektor-fiber-optic&quot;&gt;jenis konektor fiber optic&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Keempat, tidak semua rumah perlu 100 Mbps. Hampir separuh yang tidak berlangganan merasa seluler sudah cukup, dan itu masuk akal untuk penggunaan ringan. Paket yang lebih kencang baru terasa kalau ada beberapa perangkat yang dipakai bersamaan untuk streaming, unggah berkas besar, atau kerja jarak jauh.&lt;/p&gt;

&lt;h2 id=&quot;yang-belum-bisa-saya-pastikan&quot;&gt;Yang belum bisa saya pastikan&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Jalur target 2026 sampai 2029 per tahun. Dokumen Renstra lengkapnya belum saya baca, jadi saya hanya tahu dua versi dari berita.&lt;/li&gt;
  &lt;li&gt;Apakah 100 Mbps dicapai pada 2028 atau 2029.&lt;/li&gt;
  &lt;li&gt;Angka Ookla langsung dari halaman resminya.&lt;/li&gt;
  &lt;li&gt;Data resmi kecepatan nyata dibanding kecepatan di kontrak, yang memuat paket “hingga”. Data terbarunya belum ada di sumber yang dipakai tulisan ini.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kalau kamu punya dokumen atau data yang menutup salah satu celah itu, kirim lewat &lt;a href=&quot;/contact&quot;&gt;halaman kontak&lt;/a&gt; dan tulisan ini saya perbarui.&lt;/p&gt;

&lt;p&gt;Saya &lt;a href=&quot;/about&quot;&gt;Mahyuddin Susanto&lt;/a&gt;, insinyur jaringan dan infrastruktur dengan pengalaman lebih dari 15 tahun di lingkungan jaringan skala besar dan sistem Linux. Tulisan ini merangkum dokumen dan berita yang disebut di atas, tanpa pengukuran saya sendiri. Kalau ada yang keliru, kabari lewat halaman kontak, dan koreksinya saya cantumkan di tulisan ini lengkap dengan tanggalnya.&lt;/p&gt;

&lt;h2 id=&quot;sumber&quot;&gt;Sumber&lt;/h2&gt;

&lt;p&gt;Semua tautan diakses 3 November 2026.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Kementerian Komdigi, &lt;a href=&quot;https://eppid.komdigi.go.id/attachments/cb1d2d05a0d09902a340a09882b2eae56e6462ed88f3e3f688372c5053ed086a/fa1898f3b7f2672c03afd8682a6187d1ece86d3114c6a1a52d8a51fe86a81ae0.pdf&quot;&gt;Laporan Kinerja 2025&lt;/a&gt; (dokumen primer).&lt;/li&gt;
  &lt;li&gt;detikInet, &lt;a href=&quot;https://inet.detik.com/law-and-policy/d-8295938/prabowo-target-kecepatan-internet-mobile-60-mbps-dan-fixed-45-mbps&quot;&gt;Prabowo Target Kecepatan Internet Mobile 60 Mbps dan Fixed 45 Mbps&lt;/a&gt;, 7 Januari 2026.&lt;/li&gt;
  &lt;li&gt;Bisnis.com, &lt;a href=&quot;https://teknologi.bisnis.com/read/20260105/101/1941746/target-komdigi-2026-rerata-kecepatan-seluler-60-mbps-fixed-broadband-45-mbps&quot;&gt;Target Komdigi 2026&lt;/a&gt;, 5 Januari 2026.&lt;/li&gt;
  &lt;li&gt;Bisnis.com, &lt;a href=&quot;https://teknologi.bisnis.com/read/20251210/101/1935763/strategi-komdigi-kejar-target-rerata-kecepatan-internet-100-mbps-pada-2029&quot;&gt;Strategi Komdigi Kejar Target 100 Mbps pada 2029&lt;/a&gt;, 10 Desember 2025.&lt;/li&gt;
  &lt;li&gt;Bisnis.com, &lt;a href=&quot;https://teknologi.bisnis.com/read/20260705/101/1985643/komdigi-bidik-kecepatan-internet-nasional-100-mbps-pada-2028&quot;&gt;Komdigi Bidik Kecepatan Internet Nasional 100 Mbps pada 2028&lt;/a&gt;, 5 Juli 2026.&lt;/li&gt;
  &lt;li&gt;Bisnis.com, &lt;a href=&quot;https://teknologi.bisnis.com/read/20261014/101/2012346/peringkat-kecepatan-internet-ri-merangkak-di-global-agustus-2026-berkat-5g&quot;&gt;Peringkat Kecepatan Internet RI Agustus 2026&lt;/a&gt;, 14 Oktober 2026.&lt;/li&gt;
  &lt;li&gt;Bisnis.com, &lt;a href=&quot;https://teknologi.bisnis.com/read/20251001/101/1916328/komdigi-targetkan-penetrasi-fixed-broadband-naik-dari-21-menjadi-50-pada-2029&quot;&gt;Penetrasi Fixed Broadband 21% menjadi 50% pada 2029&lt;/a&gt;, 1 Oktober 2025.&lt;/li&gt;
  &lt;li&gt;Bisnis.com, &lt;a href=&quot;https://teknologi.bisnis.com/read/20260617/101/1981302/penetrasi-internet-tetap-di-ri-baru-423-ruang-pertumbuhan-masih-lebar&quot;&gt;Penetrasi Internet Tetap di RI Baru 42,3%&lt;/a&gt;, 17 Juni 2026.&lt;/li&gt;
  &lt;li&gt;investortrust.id, &lt;a href=&quot;https://investortrust.id/business/94447/internet-lambat-dan-mahal-apjatel-soroti-tumpang-tindih-aturan-fiber-optik&quot;&gt;APJATEL Soroti Tumpang Tindih Aturan Fiber Optik&lt;/a&gt;, 13 Februari 2026.&lt;/li&gt;
  &lt;li&gt;Bisnis.com, &lt;a href=&quot;https://teknologi.bisnis.com/read/20260415/101/1966687/harga-kabel-serat-optik-melesat-ekspansi-internet-nasional-berisiko-melambat&quot;&gt;Harga Kabel Serat Optik Melesat&lt;/a&gt;, 15 April 2026.&lt;/li&gt;
  &lt;li&gt;Bisnis.com, &lt;a href=&quot;https://teknologi.bisnis.com/read/20260826/101/1999077/tantangan-bisnis-serat-optik-pengamat-utilisasi-aset-hingga-beban-relokasi&quot;&gt;Tantangan Bisnis Serat Optik&lt;/a&gt;, 26 Agustus 2026.&lt;/li&gt;
  &lt;li&gt;Bisnis.com, &lt;a href=&quot;https://teknologi.bisnis.com/read/20260129/101/1948332/harga-internet-rumah-2026-internet-rakyat-vs-myrepublic-vs-indihome-vs-xlsatu&quot;&gt;Harga Internet Rumah 2026&lt;/a&gt;, 29 Januari 2026.&lt;/li&gt;
  &lt;li&gt;Bisnis.com, &lt;a href=&quot;https://teknologi.bisnis.com/read/20240125/101/1735592/internet-fixed-broadband-100-mbps-kemenkominfo-tergantung-kesiapan-industri&quot;&gt;Internet Fixed Broadband 100 Mbps, Kemenkominfo: Tergantung Kesiapan Industri&lt;/a&gt;, 25 Januari 2024.&lt;/li&gt;
  &lt;li&gt;Selular.ID, &lt;a href=&quot;https://selular.id/2026/03/komdigi-targetkan-kecepatan-internet-fixed-broadband-64-mbps-2026-isp-katakan-ini/&quot;&gt;Komdigi Targetkan Kecepatan Internet Fixed Broadband 64 Mbps 2026&lt;/a&gt;, 6 Maret 2026.&lt;/li&gt;
  &lt;li&gt;Seasia.co, &lt;a href=&quot;https://seasia.co/2026/04/20/asean-internet-speeds-index-february-2026-big-condolences-to-indonesian-users&quot;&gt;ASEAN Internet Speeds Index February 2026&lt;/a&gt;, 20 April 2026 (mengutip Ookla).&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Mahyuddin Susanto</name></author><category term="Komputer" /><category term="fixed broadband" /><category term="komdigi" /><category term="internet rumah" /><category term="ftth" /><category term="ookla" /><summary type="html">Target 100 Mbps untuk fixed broadband bisa terbaca seolah itu kecepatan yang dijanjikan ke setiap rumah. Faktanya itu target rata-rata nasional dengan tenggat 2028 atau 2029, jadi belum ada yang gagal. Jaraknya ke 100 Mbps memang masih lebar: median fixed broadband Indonesia pada Agustus 2026 ada di 51,4 Mbps menurut Ookla, peringkat ke-113 dunia dan ke-9 dari 10 negara ASEAN.</summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://www.udienz.web.id/img/target-100-mbps-fixed-broadband.png" /><media:content medium="image" url="https://www.udienz.web.id/img/target-100-mbps-fixed-broadband.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>