/.well-known/acme-challenge/.
Kalau DNS-nya sendiri yang masih kamu curigai, bahasannya ada di Kenapa AutoSSL Gagal Diperbarui Padahal Domain Sudah Mengarah ke Server. Di sini kita fokus ke apa yang terjadi di dalam web server saat validator datang, dan cara membuktikannya dengan curl.
Apa yang sebenarnya dicek validator
/.well-known/acme-challenge/ pada docroot domain. Setelah itu validator milik CA mengirim request GET biasa ke http://domainkamu/.well-known/acme-challenge/<token> lewat port 80.
Validator hanya peduli dua hal: request-nya berhasil, dan body respons berisi string yang persis sama dengan yang diharapkan. Status 200 saja tidak cukup. Kalau yang kembali adalah halaman beranda WordPress dengan status 200, validasi tetap gagal karena isinya HTML, bukan token.
Soal redirect, Let's Encrypt mengikuti redirect dengan batas tertentu, hanya ke skema http atau https, dan hanya ke port 80 atau 443. Jadi redirect ke HTTPS di domain yang sama biasanya aman, selama tujuan akhirnya masih menyajikan file token yang sama. Masalah muncul saat rantai redirect berakhir di tempat yang tidak punya file itu.
Perlu diingat juga, nama token ACME berisi karakter base64url (huruf, angka, -, dan _) tanpa ekstensi. Detail ini penting saat kita membuat file uji nanti.
Urutan kerja .htaccess yang bikin token tidak pernah dibaca
- Request masuk ke virtual host yang cocok dengan header Host.
- URL dipetakan ke path file di docroot, misalnya
/home/user/public_html/.well-known/acme-challenge/<token>. - Server menelusuri direktori dari docroot ke bawah, membaca setiap .htaccess yang ditemui, lalu menggabungkan isinya.
- Rule mod_rewrite dari .htaccess dijalankan berurutan dari atas ke bawah.
- Baru setelah semua itu lolos, file disajikan.
RewriteRule dengan flag R yang cocok, server langsung mengirim respons 301 atau 302 beserta header Location. File token yang sudah ada di disk tidak pernah disentuh. Ada atau tidaknya file tidak berpengaruh sama sekali.
Ini sebabnya banyak orang bingung. Blok bawaan WordPress sebenarnya sudah punya RewriteCond %{REQUEST_FILENAME} !-f, yang artinya file yang benar-benar ada dibiarkan lewat. Tapi rule paksa HTTPS atau paksa www biasanya ditaruh di atas blok WordPress, jadi redirect sudah terjadi sebelum pengecekan !-f sempat berjalan.
Satu detail mekanis lagi: di konteks .htaccess, pola RewriteRule dicocokkan dengan path relatif terhadap direktori tempat .htaccess berada, tanpa garis miring di depan. Sementara %{REQUEST_URI} di RewriteCond selalu diawali garis miring. Salah satu dari dua hal ini sering menjadi alasan pengecualian yang sudah ditulis ternyata tidak pernah cocok.
Dari pola yang sering muncul, rantai redirect yang bermasalah biasanya salah satu dari ini:
- Redirect ke domain lain (domain utama baru, landing page) yang tidak menyimpan token.
- Redirect yang membuang path, misalnya semua request diarahkan ke
https://example.com/tanpa%{REQUEST_URI}. - Redirect ke HTTPS di host yang port 443-nya dilayani server lain, misalnya proxy atau CDN yang tidak meneruskan path ini ke origin.
- Redirect ke www padahal record www belum mengarah ke server yang sama.
- Redirect loop, yang membuat validator berhenti sebelum sampai ke file.
Menguji path validasi dengan curl
test.txt bisa lolos atau gagal dengan cara yang berbeda dari token sungguhan.
BASH
# Buat file uji tanpa ekstensi (sesuaikan path docroot dengan domainnya)
mkdir -p ~/public_html/.well-known/acme-challenge
echo 'tes-validasi' > ~/public_html/.well-known/acme-challenge/cektoken123
# 1. Lihat hop pertama saja, tanpa mengikuti redirect
curl -sI 'http://example.com/.well-known/acme-challenge/cektoken123'
# 2. Ikuti seluruh rantai dan tampilkan status serta Location tiap hop
curl -sIL --max-redirs 10 'http://example.com/.well-known/acme-challenge/cektoken123' | grep -iE '^(HTTP|location)'
# 3. Pastikan isi akhirnya benar-benar token, bukan halaman HTML
curl -sL 'http://example.com/.well-known/acme-challenge/cektoken123'
# 4. Paksa ke IP server ini, melewati DNS lokal atau CDN
curl -sI --resolve 'example.com:80:203.0.113.10' 'http://example.com/.well-known/acme-challenge/cektoken123'example.com dengan domainmu dan 203.0.113.10 dengan IP server. Ulangi untuk setiap nama yang tercantum di sertifikat, minimal domain utama dan varian www, karena AutoSSL memvalidasi keduanya secara terpisah.
Berikut contoh format output dari perintah nomor 2, bukan hasil dari server sungguhan:
TEXT
HTTP/1.1 301 Moved Permanently
Location: https://www.example.com/.well-known/acme-challenge/cektoken123
HTTP/1.1 301 Moved Permanently
Location: https://example.com/
HTTP/1.1 200 OKtes-validasi. Perintah nomor 3 akan langsung memperlihatkan ini.
Kalau hasil dari perintah nomor 4 (langsung ke IP) benar tapi perintah nomor 2 (lewat DNS publik) salah, masalahnya kemungkinan ada di luar .htaccess: CDN, proxy, atau DNS yang masih mengarah ke tempat lain.
Setelah selesai, hapus file cektoken123. File itu tidak berbahaya, tapi tidak perlu dibiarkan.
Menambahkan pengecualian yang aman
APACHE
RewriteEngine On
# Biarkan request validasi ACME lewat tanpa redirect apa pun
RewriteRule ^\.well-known/acme-challenge/ - [L]
# Baru setelah itu rule redirect biasa
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]- artinya URL tidak diubah, dan flag L menghentikan pemrosesan rule berikutnya di putaran itu. Hasilnya, request ke path validasi diteruskan ke file di disk, sedangkan request lain tetap kena redirect seperti biasa.
Kenapa tidak cukup menambah RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/ di atas rule HTTPS? Bisa, dan itu valid. Tapi RewriteCond hanya berlaku untuk satu RewriteRule tepat di bawahnya. Kalau ada rule paksa www, rule pindah domain, atau rule dari plugin di bawahnya, masing-masing perlu kondisi yang sama. Satu rule pass-through di atas menutup semuanya sekaligus.
Beberapa hal yang sering terlewat:
- Taruh rule ini di luar blok
# BEGIN WordPressdan# END WordPress, karena WordPress bisa menulis ulang isi blok itu. - Direktif
RedirectdanRedirectMatchmilik mod_alias tidak terpengaruh oleh rule mod_rewrite. Kalau kamu menemukanRedirect 301 / https://domain-lain.com/, pengecualian di atas tidak menolong. Lebih aman ganti redirect itu denganRewriteRulesupaya bisa dikecualikan. - Rule keamanan yang memblokir semua path diawali titik (biasanya dimaksudkan untuk menyembunyikan
.gitatau.env) bisa ikut memblokir.well-knowndengan status 403. Cari pola seperti itu dan beri pengecualian yang sama. - Fitur Redirects di cPanel biasanya menambahkan kondisi pengecualian untuk path validasi secara otomatis. Rule yang ditulis manual atau dibuat plugin tidak mendapat perlakuan itu.
- Kalau ada Nginx di depan sebagai reverse proxy dan redirect HTTPS dilakukan di sana, .htaccess tidak pernah dibaca untuk request itu. Perbaikannya harus di konfigurasi server, seperti dibahas di Kenapa Redirect HTTPS Global Bikin Perpanjangan Otomatis ACME Gagal.
