Caddy DNS #

Secara bawaan, server web Caddy menggunakan metode HTTP-01 challenge untuk mengajukan dan memperbarui sertifikat SSL/TLS gratis dari Let’s Encrypt atau ZeroSSL. Metode ini sangat praktis karena bekerja secara otomatis tanpa memerlukan konfigurasi tambahan, namun memiliki batasan operasional yang signifikan: server kita wajib terhubung langsung ke internet publik dan membuka port HTTP 80 agar dapat dihubungi balik oleh server otoritas sertifikat (CA) untuk memverifikasi kepemilikan domain. Masalah serius muncul ketika kita ingin memasang sertifikat SSL pada server internal intranet yang berada di balik firewall perusahaan, server lokal di jaringan rumah (di belakang NAT provider), atau ketika kita membutuhkan satu sertifikat tunggal untuk melindungi seluruh subdomain secara dinamis (wildcard certificate seperti *.example.com). Untuk mengatasi skenario-skenario tersebut, Caddy menyediakan plugin caddy-dns yang membolehkan kita beralih menggunakan metode DNS-01 challenge. Melalui metode ini, proses pembuktian kepemilikan domain dilakukan sepenuhnya dengan memodifikasi TXT record pada server nama domain (DNS Provider) kita secara programatis melalui API. Kita akan membahas secara tuntas keunggulan metode DNS-01 challenge, memetakan provider DNS yang didukung, mempraktikkan setup kredensial API secara aman untuk Cloudflare dan AWS Route53, menyusun strategi redundansi issuer, mengimplementasikan teknik delegasi DNS kustom (DNS delegation), serta melakukan investigasi pemecahan masalah kegagalan propagasi rekaman DNS.

Mengapa Memilih DNS-01 Challenge? #

Untuk menentukan strategi pengamanan TLS yang tepat, kita harus memahami perbedaan mendasar dan trade-off operasional antara metode verifikasi HTTP-01 challenge dengan DNS-01 challenge.

1. HTTP-01 Challenge (Pendekatan Klasik) #

  • Cara Kerja: CA mengirimkan token acak ke Caddy. Caddy meletakkan token tersebut di path khusus / .well-known/acme-challenge/ pada web server. CA kemudian mengakses URL tersebut via port 80 untuk memverifikasi.
  • Kelebihan: Sangat mudah, bekerja seketika tanpa memerlukan konfigurasi token API eksternal.
  • Kekurangan: Menuntut port 80 terbuka penuh ke internet. Tidak mendukung pembuatan sertifikat wildcard (*.example.com), dan mustahil digunakan di server terisolasi (misalnya server database internal).

2. DNS-01 Challenge (Pendekatan Berbasis API DNS) #

  • Cara Kerja: CA mengirimkan token acak ke Caddy. Caddy masuk ke akun DNS kita via API, lalu menulis TXT record baru bernama _acme-challenge.example.com yang berisi token tersebut. CA membaca record DNS tersebut dari internet, memverifikasi kecocokan data, lalu menerbitkan sertifikat. Setelah sukses, Caddy menghapus kembali record TXT tersebut.
  • Kelebihan: Mendukung penerbitan sertifikat wildcard, tidak membutuhkan port masuk (inbound port 80/443) terbuka ke internet publik, dan sangat aman untuk mengamankan server internal.
  • Kekurangan: Mengharuskan kita mengelola kredensial token API DNS provider di dalam server, dan proses penerbitan memakan waktu sedikit lebih lama karena harus menunggu waktu propagasi DNS (propagation delay).

Berikut adalah perbandingan ringkas kecocokan penggunaan metode ini berdasarkan skenario deployment:

Skenario InfrastrukturRekomendasi Tantangan ACMEAlasan Utama
Server Web Publik Single DomainHTTP-01 ChallengeSederhana, tanpa konfigurasi API
Situs Multi-Subdomain DinamisDNS-01 ChallengeWajib untuk menerbitkan sertifikat wildcard
Server Database/API Internal LANDNS-01 ChallengeServer tidak memiliki alamat IP publik
Server di Balik IP Dinamis (NAT)DNS-01 ChallengeMenghindari keharusan membuka port router

Daftar Provider DNS yang Didukung #

Modul caddy-dns tidak dikelola sebagai satu plugin tunggal yang besar. Caddy memisahkannya menjadi modul-modul independen per provider untuk menjaga agar ukuran berkas biner Caddy kita tetap efisien. Kita hanya perlu mengompilasi modul DNS provider yang kita gunakan menggunakan xcaddy.

Berikut adalah daftar modul repositori resmi untuk beberapa provider DNS terpopuler:

  • Cloudflaregithub.com/caddy-dns/cloudflare
  • AWS Route53github.com/caddy-dns/route53
  • Google Cloud DNSgithub.com/caddy-dns/googleclouddns
  • DigitalOceangithub.com/caddy-dns/digitalocean
  • Azure DNSgithub.com/caddy-dns/azure
  • DuckDNSgithub.com/caddy-dns/duckdns
  • Porkbungithub.com/caddy-dns/porkbun

Panduan Langkah Demi Langkah: Cloudflare DNS #

Cloudflare adalah salah satu penyedia DNS yang paling banyak digunakan karena kestabilan dan kecepatan propagasi rekaman DNS-nya.

Langkah 1: Kompilasi Caddy dengan Plugin Cloudflare #

Kita memulai dengan mengompilasi biner Caddy kustom yang telah menggabungkan plugin DNS Cloudflare:

xcaddy build --with github.com/caddy-dns/cloudflare

Langkah 2: Membuat API Token Terbatas di Cloudflare #

[!WARNING] JANGAN PERNAH menggunakan Global API Key akun Cloudflare kita. Menggunakan Global API Key memberikan hak akses penuh untuk menghapus seluruh domain, memodifikasi billing, dan merusak seluruh akun kita jika kunci tersebut bocor dari server. Selalu buat API Token terbatas dengan hak akses minimal yang hanya diizinkan untuk mengelola DNS domain tertentu saja.

Cara membuat API Token terbatas di Cloudflare Dashboard:

  1. Masuk ke Cloudflare Dashboard → klik ikon My Profile di kanan atas → pilih API Tokens.
  2. Klik Create Token → pilih template Edit zone DNS.
  3. Sesuaikan izin akses (Permissions):
    • Zone - DNS - Edit (Wajib untuk menulis TXT record).
    • Zone - Zone - Read (Wajib agar Caddy dapat mencari ID Zone domain kita).
  4. Tentukan cakupan sumber daya (Zone Resources):
    • Include - Specific zone - pilih domain target kita (misalnya example.com).
  5. Klik Continue to summary lalu Create Token. Salin token tersebut dan simpan dengan aman.

Langkah 3: Konfigurasi Variabel Lingkungan secara Aman #

Kita harus menyuntikkan token tersebut melalui variabel lingkungan sistem operasi agar tidak tertulis secara mentah (hardcoded) di berkas konfigurasi Caddyfile kita:

# Tambahkan ke variabel lingkungan shell server
export CLOUDFLARE_API_TOKEN="kunci_token_cloudflare_rahasia_kita"

Langkah 4: Penyusunan Caddyfile untuk Sertifikat Wildcard #

# Blok opsi global
{
    email [email protected]
}

# Blok penanganan wildcard (*.example.com) dan domain root (example.com)
*.example.com example.com {
    tls {
        # Instruksikan Caddy menggunakan DNS challenge Cloudflare
        # dengan mengambil nilai token dari variabel lingkungan
        dns cloudflare {env.CLOUDFLARE_API_TOKEN}
    }
    
    # Perutean subdomain kustom menggunakan named matchers
    @app host app.example.com
    @api host api.example.com
    
    handle @app {
        reverse_proxy localhost:3000
    }
    
    handle @api {
        reverse_proxy localhost:8080
    }
    
    # Penanganan halaman utama untuk domain root
    handle {
        root * /var/www/html
        file_server
    }
}

Konfigurasi untuk AWS Route53 #

Jika infrastruktur server kita berjalan di dalam ekosistem AWS (Amazon Web Services), AWS Route53 adalah pilihan DNS provider yang ideal.

1. Kompilasi Biner Kustom #

xcaddy build --with github.com/caddy-dns/route53

2. IAM Policy Minimum untuk Route53 #

Untuk alasan keamanan, kredensial AWS yang digunakan oleh Caddy hanya boleh memiliki akses untuk mengelola Hosted Zone terkait. Berikut adalah dokumen JSON IAM Policy dengan hak akses minimal (least privilege) yang wajib kita buat dan sematkan pada pengguna IAM (IAM User) atau peran (IAM Role) Caddy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "route53:GetChange",
                "route53:ChangeResourceRecordSets",
                "route53:ListResourceRecordSets"
            ],
            "Resource": [
                "arn:aws:route53:::hostedzone/ID_HOSTED_ZONE_DOMAN_KITA",
                "arn:aws:route53:::change/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": "route53:ListHostedZonesByName",
            "Resource": "*"
        }
    ]
}

3. Konfigurasi Caddyfile AWS Route53 #

Caddy mendukung pemuatan kredensial AWS melalui beberapa metode. Jika Caddy dijalankan di dalam instansi AWS EC2, Caddy dapat memanfaatkan fitur IAM Instance Profile secara otomatis tanpa menulis kredensial apa pun di Caddyfile. Jika berjalan di luar AWS, kita memuat kredensial via variabel lingkungan:

# Konfigurasi Caddyfile dengan DNS Route53
*.example.com example.com {
    tls {
        dns route53 {
            # Opsi 1: Jika berjalan di EC2 dengan Instance Profile,
            # biarkan blok parameter ini kosong. Caddy otomatis mengambil role RAM.
            
            # Opsi 2: Tulis secara eksplisit menggunakan variabel lingkungan (untuk non-AWS host)
            access_key_id     {env.AWS_ACCESS_KEY_ID}
            secret_access_key {env.AWS_SECRET_ACCESS_KEY}
            region            {env.AWS_REGION}
        }
    }
    reverse_proxy localhost:3000
}

Menggunakan DNS Challenge pada Jaringan Internal (Intranet) #

Kasus penggunaan yang sangat populer dari DNS-01 challenge adalah memberikan enkripsi HTTPS resmi untuk server web internal yang terisolasi dari internet. Sebagai contoh, server visualisasi metrik internal kita yang berjalan pada subdomain monitor.company.com di dalam jaringan lokal kantor:

# Konfigurasi pengamanan server intranet privat
monitor.company.com {
    tls {
        # Mengajukan sertifikat Let's Encrypt resmi lewat DNS.
        # Let's Encrypt CA dapat memverifikasi kepemilikan domain kita lewat DNS publik,
        # meskipun server fisik monitor.company.com kita tidak memiliki IP publik
        # dan tidak dapat diakses dari luar kantor.
        dns cloudflare {env.CLOUDFLARE_API_TOKEN}
    }
    
    # Pengamanan lapis tambahan: Hanya izinkan akses fisik dari subnet LAN kantor
    @external not remote_ip 10.0.0.0/8 192.168.0.0/16
    respond @external "Akses Ditolak: Khusus Jaringan Internal" 403
    
    reverse_proxy localhost:9090
}

Dengan taktik ini, browser karyawan kita tidak akan lagi menampilkan peringatan merah “Self-Signed Certificate / Connection Not Private” yang mengganggu, sekaligus menjamin keamanan lalu lintas data lokal dari bahaya penyadapan jaringan.


Redundansi & Fallback Issuer (Let’s Encrypt + ZeroSSL) #

Otoritas sertifikat publik terkadang dapat mengalami masa pemeliharaan tidak terjadwal (downtime) atau mencapai batas limitasi pengajuan sertifikat (rate limit exceed). Untuk memastikan ketersediaan sertifikat yang andal, kita dapat mengonfigurasi Caddy untuk menggunakan dua issuer yang berbeda secara berurutan. Caddy akan mencoba mengontak issuer pertama (misalnya Let’s Encrypt), dan jika gagal, Caddy secara otomatis beralih menggunakan issuer kedua (ZeroSSL) sebagai cadangan:

# Contoh konfigurasi redundansi issuer TLS
*.example.com example.com {
    tls {
        # Issuer 1: Let's Encrypt (Default)
        issuer acme {
            ca https://acme-v02.api.letsencrypt.org/directory
            dns cloudflare {env.CLOUDFLARE_API_TOKEN}
        }
        
        # Issuer 2: ZeroSSL (Cadangan)
        issuer acme {
            ca https://acme.zerossl.com/v2/DV90
            eab_key_id  {env.ZEROSSL_KEY_ID} # Kredensial EAB untuk ZeroSSL
            eab_mac_key {env.ZEROSSL_MAC_KEY}
            dns cloudflare {env.CLOUDFLARE_API_TOKEN}
        }
    }
    reverse_proxy localhost:3000
}

DNS Challenge Delegation (CNAME Redirection) #

Pada arsitektur keamanan perusahaan (enterprise security), tim administrator DNS sering kali melarang keras penyematan token API DNS yang memiliki hak akses modifikasi pada server web edge publik. Domain utama company.com dinilai terlalu berharga untuk diletakkan token API-nya di mesin virtual produksi.

Untuk memecahkan kebuntuan ini, kita dapat menerapkan taktik DNS Challenge Delegation memanfaatkan rekaman CNAME. Kita mendelegasikan proses pembuktian token ACME dari domain utama ke domain cadangan yang kurang bernilai keamanan tinggi (misalnya company-dns.com yang didedikasikan khusus untuk validasi).

Alur Konfigurasi: #

  1. Di server DNS Domain Utama (company.com): Buat rekaman CNAME yang mengarahkan permintaan verifikasi ACME ke domain cadangan:

    _acme-challenge.app.company.com CNAME _acme-challenge.app.company-dns.com
    
  2. Di server DNS Domain Cadangan (company-dns.com): Gunakan API Token Cloudflare yang hanya diizinkan untuk mengelola zona company-dns.com.

  3. Di berkas Caddyfile Server Caddy kita: Kita mengonfigurasi Caddy untuk mengabaikan domain utama saat berinteraksi dengan API DNS provider, dan menginstruksikannya untuk memodifikasi DNS domain cadangan sebagai gantinya:

# Konfigurasi Delegasi Tantangan DNS CNAME
app.company.com {
    tls {
        # Menginstruksikan Caddy untuk menulis TXT record di company-dns.com
        # meskipun Caddy sedang meminta sertifikat untuk app.company.com
        dns cloudflare {env.CF_DELEGATE_API_TOKEN} {
            # Parameter override zone target
            # (Bergantung pada implementasi driver plugin provider kustom)
        }
    }
    reverse_proxy localhost:3000
}

(Catatan: Sebagian besar driver ACME client modern secara otomatis mengikuti rute CNAME secara transparan saat mencari titik akhir API untuk menulis TXT token).


Troubleshooting Masalah Validasi DNS #

DNS-01 challenge melibatkan lebih banyak pihak luar (DNS server, cache resolvers, jaringan internet global) dibandingkan HTTP-01. Hal ini terkadang memicu kegagalan operasional. Berikut adalah panduan pemecahan masalah kegagalan validasi DNS:

1. Masalah: Validasi Gagal Karena Hambatan Caching (Propagation Timeout) #

  • Gejala: Caddy menulis token ke Cloudflare secara sukses, namun Let’s Encrypt mengembalikan error “No TXT record found”.
  • Penyebab: Caddy atau server penguji Let’s Encrypt menanyakan status TXT record ke DNS server sebelum record tersebut benar-benar tersebar (propagated) ke seluruh server DNS replika global.
  • Solusi: Kita dapat memaksa Caddy untuk menggunakan DNS resolver publik eksternal yang cepat dan tidak menggunakan cache lokal untuk memverifikasi propagasi sebelum menyatakan siap diuji oleh Let’s Encrypt. Tambahkan parameter resolver di dalam blok tls:
*.example.com {
    tls {
        dns cloudflare {env.CLOUDFLARE_API_TOKEN}
        
        # Gunakan resolver DNS Google & Cloudflare untuk mengecek propagasi
        resolvers 1.1.1.1 8.8.8.8
    }
}

2. Menggunakan Perintah dig Untuk Debugging Manual #

Sebelum mengajukan sertifikat, kita dapat melihat apakah TXT record telah tertulis dengan benar pada server nama menggunakan perintah terminal:

# Menanyakan berkas TXT record ACME domain kita secara langsung ke resolver publik
dig TXT _acme-challenge.example.com @1.1.1.1

# Output yang benar harus menampilkan baris token acak:
# _acme-challenge.example.com. 120 IN TXT "h7y1K9lPqRstUvwXyz..."

Diagram Alur Otentikasi ACME DNS-01 Challenge #

Untuk memahami urutan interaksi jaringan yang teratur antara Caddy, penyedia DNS, dan Otoritas Sertifikat (CA) selama proses DNS-01 challenge, perhatikan visualisasi diagram alir (flowchart) berikut:

flowchart TD
    A["1. Caddy Meminta Sertifikat Baru\n(Mengirim Order ke CA Let's Encrypt)"] --> B["2. CA Mengirimkan Tantangan ACME\n(Token tantangan acak yang wajib ditulis)"]
    
    B --> C["3. Caddy Panggil Driver DNS API\n(Mengirim request penulisan record via API Provider)"]
    C --> D["4. DNS Provider Menulis TXT Record\n(Membuat record _acme-challenge.example.com)"]
    
    D --> E["5. Caddy Melakukan Polling Mandiri\n(Menguji status record via resolvers 1.1.1.1)"]
    
    E --> E1{"6. Apakah record terdeteksi?"}
    E1 -- "Tidak" --> E2["Tunggu (Propagation Delay)\ndan ulangi pengecekan"]
    E2 --> E
    E1 -- "Ya" --> F["7. Caddy Beri Tahu CA\n(Menyatakan bahwa record siap divalidasi)"]
    
    F --> G["8. CA Melakukan Validasi DNS\n(Membaca TXT record dari internet publik)"]
    
    G --> G1{"9. Apakah token valid?"}
    G1 -- "Tidak" --> G2["Proses Gagal\n(Catat error ke log & coba lagi)"]
    G1 -- "Ya" --> H["10. CA Menerbitkan Sertifikat SSL\n(Sertifikat dikirim kembali ke Caddy)"]
    
    H --> I["11. Caddy Bersihkan DNS Record\n(Panggil API DNS untuk menghapus TXT token)"]
    I --> J["12. Sertifikat Disimpan di Storage\n(HTTPS aktif di server Caddy)"]

Ringkasan #

  • Solusi Wildcard: DNS-01 challenge merupakan satu-satunya metode ACME resmi untuk menerbitkan sertifikat wildcard gratis dari Let’s Encrypt.
  • Isolasi Jaringan: Metode ini membolehkan server internal yang berada di balik firewall atau NAT privat memperoleh sertifikat SSL publik tanpa membuka port 80 ke internet.
  • Prinsip Hak Akses Minimal: Selalu gunakan API Token Cloudflare terbatas yang dikunci khusus untuk domain tertentu, bukan Global API Key akun kita.
  • Pengamanan Token: Amankan token API DNS di berkas variabel lingkungan (EnvironmentFile dengan hak akses 600), jangan pernah menulisnya langsung di Caddyfile.
  • Bypass IAM AWS: Manfaatkan IAM Instance Profile pada instansi EC2 agar Caddy dapat mengakses Route53 tanpa memerlukan konfigurasi kredensial fisik.
  • Verifikasi Cepat: Gunakan parameter resolvers 1.1.1.1 8.8.8.8 untuk menghindari kegagalan proses validasi akibat lambatnya propagasi DNS lokal.
  • Delegasi CNAME: Terapkan teknik DNS Challenge Delegation CNAME jika kebijakan keamanan internal melarang peletakan token API pada server edge publik.

← Sebelumnya: Plugin Populer   Berikutnya: Buat Plugin →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact