Basic Auth #
HTTP Basic Authentication adalah mekanisme autentikasi paling sederhana dalam ekosistem HTTP — browser menampilkan dialog login bawaan, user memasukkan username dan password, dan browser mengirimkan credentials dalam setiap request sebagai header Authorization: Basic base64(username:password).
Meski sederhana, basicauth sangat berguna untuk melindungi area tertentu dari aplikasi yang tidak memerlukan user management yang kompleks: admin panel internal, staging environment, directory listing, atau API yang hanya diakses oleh beberapa orang.
Cara Kerja HTTP Basic Auth #
1. Browser request ke URL yang dilindungi basicauth
GET /admin/ HTTP/1.1
Host: example.com
2. Caddy merespons dengan 401 Unauthorized
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Restricted Area"
3. Browser menampilkan dialog login
┌─────────────────────────────┐
│ Sign in │
│ example.com │
│ Username: [ ] │
│ Password: [ ] │
│ [Cancel] [Sign in] │
└─────────────────────────────┘
4. User masukkan username "alice" dan password "secret123"
Browser encode: base64("alice:secret123") = "YWxpY2U6c2VjcmV0MTIz"
GET /admin/ HTTP/1.1
Authorization: Basic YWxpY2U6c2VjcmV0MTIz
5. Caddy decode header, verifikasi username dan bcrypt hash password
→ Cocok → Request diteruskan
→ Tidak cocok → 401 Unauthorized lagi
Membuat Password Hash #
Caddy menggunakan bcrypt untuk menyimpan password hash — jauh lebih aman dari plaintext atau MD5. Kamu tidak pernah menyimpan password asli di Caddyfile, hanya hash-nya.
# Generate bcrypt hash untuk password
caddy hash-password --plaintext "password-kamu"
# Output contoh:
# $2a$14$8lGvWLMR9jGg2.bSZlAHOeYuI1FjTPExECWQpkLPMH1y0LkJnbEKy
# Dengan cost factor berbeda (default 14, range 4-31)
# Cost lebih tinggi = lebih aman tapi lebih lambat
caddy hash-password --plaintext "password-kamu" --cost 12
# Interaktif (tidak menampilkan password di terminal/history)
caddy hash-password
# Enter password: [ketik tanpa echo]
# Confirm password: [ketik lagi]
# Output: $2a$14$...
Bcrypt dengan cost 14 membutuhkan sekitar 1-2 detik per hash verification di hardware modern. Ini disengaja — membuat brute force attack jauh lebih lambat. Jangan khawatir tentang “overhead” ini untuk normal login, tapi perhatikan jika endpoint basicauth mendapat traffic sangat tinggi.
Konfigurasi Dasar #
example.com {
basicauth {
# Format: username bcrypt_hash
alice $2a$14$8lGvWLMR9jGg2.bSZlAHOeYuI1FjTPExECWQpkLPMH1y0LkJnbEKy
bob $2a$14$7kFuXLMR9jGg2.bSZlAHOeYuI1FjTPExECWQpkLPMH1y0LkJnbEKy
}
root * /var/www/protected
file_server
}
Proteksi Hanya Sebagian Path #
example.com {
# Hanya proteksi path /admin/*
basicauth /admin/* {
admin $2a$14$adminHashHere
devops $2a$14$devopsHashHere
}
# Path lain bisa diakses tanpa auth
root * /var/www/html
file_server
}
Menggunakan Matcher #
example.com {
@protected {
path /admin/*
path /internal/*
path /metrics
}
basicauth @protected {
alice $2a$14$aliceHashHere
bob $2a$14$bobHashHere
}
root * /var/www/html
file_server
}
Custom Realm #
Realm adalah teks yang muncul di dialog login browser:
example.com {
basicauth * {
# Ubah teks yang muncul di dialog login browser
realm "Portal Admin Example.com"
alice $2a$14$aliceHashHere
bob $2a$14$bobHashHere
}
reverse_proxy localhost:3000
}
Bypass Auth untuk IP Internal #
Skenario umum: basicauth untuk akses dari internet, tapi IP internal tidak perlu auth:
example.com {
@internal remote_ip 10.0.0.0/8 192.168.0.0/16 172.16.0.0/12
@external not remote_ip 10.0.0.0/8 192.168.0.0/16 172.16.0.0/12
# Hanya request dari luar yang perlu auth
basicauth @external {
alice $2a$14$aliceHashHere
}
root * /var/www/html
file_server
}
Basicauth + Reverse Proxy #
Ketika Caddy digunakan sebagai reverse proxy dengan basicauth, backend menerima informasi user via header:
admin.example.com {
basicauth {
alice $2a$14$aliceHashHere
bob $2a$14$bobHashHere
}
reverse_proxy localhost:9000 {
# Teruskan username ke backend
# Setelah basicauth berhasil, {http.auth.user.id} berisi username
header_up X-Authenticated-User {http.auth.user.id}
# Hapus Authorization header dari backend
# (backend tidak perlu validasi lagi)
header_up -Authorization
}
}
// Di backend Node.js — ambil username dari header
app.get('/admin/dashboard', (req, res) => {
const user = req.headers['x-authenticated-user'];
console.log(`User ${user} accessed dashboard`);
res.json({ user, data: getDashboardData(user) });
});
Menyimpan Hash dengan Aman — Environment Variables #
Menaruh password hash langsung di Caddyfile yang masuk ke version control tidak ideal meski hash aman:
{
# Konfigurasi dari environment variable
}
example.com {
basicauth {
# Hash bisa di-load dari environment variable
alice {env.ALICE_PASSWORD_HASH}
bob {env.BOB_PASSWORD_HASH}
}
reverse_proxy localhost:3000
}
# Set env vars sebelum jalankan Caddy
export ALICE_PASSWORD_HASH='$2a$14$aliceHashHere'
export BOB_PASSWORD_HASH='$2a$14$bobHashHere'
# Atau di systemd override
sudo systemctl edit caddy
# [Service]
# EnvironmentFile=/etc/caddy/caddy.env
# /etc/caddy/caddy.env (mode 600)
# ALICE_PASSWORD_HASH=$2a$14$...
# BOB_PASSWORD_HASH=$2a$14$...
Mengelola Banyak User #
Untuk banyak user, gunakan script untuk generate Caddyfile snippet:
#!/bin/bash
# generate-basicauth.sh
# Usage: ./generate-basicauth.sh users.txt > basicauth-snippet.txt
# users.txt format: username:password (satu per baris)
while IFS=':' read -r username password; do
hash=$(caddy hash-password --plaintext "$password")
echo " $username $hash"
done < "$1"
# users.txt
alice:secret123
bob:another-password
charlie:yet-another
# Generate snippet
./generate-basicauth.sh users.txt > /etc/caddy/basicauth-users.txt
# Lihat hasilnya
cat /etc/caddy/basicauth-users.txt
# alice $2a$14$...
# bob $2a$14$...
# charlie $2a$14$...
# Import ke Caddyfile dengan import directive
# basicauth {
# import /etc/caddy/basicauth-users.txt
# }
Keterbatasan Basic Auth dan Alternatifnya #
Basic Auth cocok untuk:
✓ Melindungi area internal dari akses tidak sah
✓ Staging environment (agar tidak terindeks Google)
✓ Admin panel dengan pengguna terbatas
✓ File server yang perlu proteksi sederhana
✓ Quick protection sementara
Basic Auth TIDAK cocok untuk:
✗ Aplikasi consumer (user experience buruk)
✗ Butuh logout yang proper (browser cache credentials)
✗ Remember me / session management
✗ OAuth, SSO, LDAP integration
✗ Audit log yang detail
✗ Password reset self-service
✗ Multi-factor authentication
Alternatif yang lebih lengkap:
→ caddy-security plugin (LDAP, OAuth, JWT)
→ Authelia (self-hosted, bisa dikombinasikan dengan Caddy)
→ Authentik (self-hosted identity provider)
→ Cloudflare Access (jika pakai Cloudflare)
Security Considerations #
# Basic Auth WAJIB digunakan dengan HTTPS
# HTTP Basic Auth mengirim credentials dalam Base64 — mudah didecode!
# Selalu pastikan HTTPS aktif (Caddy otomatis melakukan ini)
# Cek apakah HTTPS aktif
curl -I https://example.com/admin/
# Harus HTTPS, bukan HTTP
# Rate limiting untuk mencegah brute force
# (Caddy sendiri tidak punya rate limiting bawaan untuk basicauth)
# Gunakan fail2ban atau rate limit plugin untuk produksi yang kritis
Melindungi Staging Environment dari Google #
Basic auth adalah cara paling mudah mencegah search engine mengindeks staging environment:
staging.example.com {
# Google dan crawler lain tidak bisa melewati basicauth
# Staging tidak akan muncul di hasil pencarian
basicauth {
deploy $2a$14$deployHashHere
qa $2a$14$qaHashHere
}
# Tambahkan header anti-indexing sebagai lapisan kedua
header X-Robots-Tag "noindex, nofollow"
reverse_proxy staging-backend:3000
}
Ini jauh lebih andal dibanding hanya mengandalkan robots.txt yang bisa diabaikan oleh crawler nakal.
Ringkasan #
- Caddy menggunakan bcrypt untuk password hash — gunakan
caddy hash-password --plaintext "password"untuk generate hash dan simpan hasilnya di Caddyfile.- Jangan pernah simpan password plaintext di Caddyfile — selalu gunakan bcrypt hash.
- Gunakan matcher untuk melindungi hanya path tertentu (
basicauth /admin/* { ... }), bukan seluruh site.- Setelah autentikasi berhasil,
{http.auth.user.id}berisi username yang bisa diteruskan ke backend viaheader_up.- Basic auth wajib menggunakan HTTPS — tanpa TLS, credentials bisa dicuri dari network traffic.
- Untuk aplikasi dengan kebutuhan auth yang lebih kompleks (OAuth, SSO, MFA), gunakan plugin seperti caddy-security atau solusi terpisah seperti Authelia.