Web uygulamalarını dış dünyaya açarken güvenlik her zaman birinci öncelik olmalı. Caddy, modern ve sade yapısıyla bu konuda oldukça güçlü araçlar sunuyor. Bu yazıda Caddy’nin yerleşik Basic Auth mekanizmasını ve daha gelişmiş senaryolar için kullanılan Forward Auth yöntemini derinlemesine inceleyeceğiz. Homelab’ından kurumsal ortama kadar her ölçekte işe yarayan bu bilgileri gerçek dünya senaryolarıyla pekiştireceğiz.
Temel Kavramlar
Başlamadan önce iki kavramı netleştirelim.
Basic Auth, HTTP protokolünün standart bir parçasıdır. Tarayıcı, korunan bir kaynağa erişmek istediğinde sunucu 401 döner ve tarayıcı kullanıcıya bir kullanıcı adı/şifre kutusu gösterir. Bu bilgiler Base64 ile kodlanarak her istekte Authorization başlığında taşınır. Basit ama etkilidir.
Forward Auth ise daha sofistike bir yaklaşım. Caddy, bir isteği backend’e iletmeden önce harici bir kimlik doğrulama servisine sorar: “Bu kullanıcı geçebilir mi?” Eğer servis onay verirse istek hedefe ulaşır, vermezse kullanıcı login sayfasına yönlendirilir. Authelia, Authentik, Traefik Forward Auth gibi araçlar bu modelde çalışır.
Caddy Kurulumu ve Hazırlık
Eğer henüz Caddy kurulu değilse hızlıca başlayalım. Ubuntu/Debian için:
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
Caddy’nin düzgün çalıştığını doğrulayalım:
caddy version
sudo systemctl status caddy
Caddyfile genellikle /etc/caddy/Caddyfile konumunda bulunur. Yapılandırma değişikliklerinden sonra:
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
reload komutunu unutma, restart yerine reload kullanmak zero-downtime sağlar.
Basic Auth Yapılandırması
Şifre Hash’i Oluşturma
Caddy, şifreleri düz metin olarak saklamaz. bcrypt hash kullanır. Hash oluşturmak için:
caddy hash-password --plaintext "guclu_sifreniz"
Çıktı şuna benzer bir şey olacak:
$2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvK
Bu hash’i Caddyfile’da kullanacaksın. Şifreyi terminal geçmişinde bırakmak istemiyorsan interaktif modu kullan:
caddy hash-password
Komutu çalıştırınca şifreyi girmen istenir, hiçbir şey terminale yazılmaz.
Basit Bir Senaryo: Dahili Araçları Koruma
Diyelim ki bir Grafana instance’ın var ve bunu internete açmak zorunda kaldın ama Grafana’nın kendi auth’u dışında bir katman daha eklemek istiyorsun:
# /etc/caddy/Caddyfile
grafana.sirketin.com {
basicauth {
# kullanici_adi hashlenmis_sifre
admin $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvK
operator $2a$14$hDiXBMHkVyL3CxPP7Ro8Y.yRQdFGlZP8N4SvxT1mEd9.7UVz3Bxe6
}
reverse_proxy localhost:3000
}
Bu kadar. Caddy artık Grafana’ya gelen her isteği önce Basic Auth ile kontrol edecek.
Sadece Belirli Yolları Koruma
Bazen tüm siteyi değil, sadece admin panelini korumak istersin. route bloğu burada devreye girer:
# /etc/caddy/Caddyfile
uygulama.sirketin.com {
# /admin altindaki her sey korunuyor
route /admin/* {
basicauth {
admin $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvK
}
reverse_proxy localhost:8080
}
# Geri kalan her sey serbest
route {
reverse_proxy localhost:8080
}
}
Birden Fazla Site, Merkezi Kullanıcı Yönetimi
Birden fazla subdomain varsa her birine ayrı ayrı kullanıcı eklemek yerine snippet kullanabilirsin:
# /etc/caddy/Caddyfile
(ortak_auth) {
basicauth {
admin $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvK
mehmet $2a$14$AnotherHashForMehmetXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
ayse $2a$14$AnotherHashForAyseXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
}
}
grafana.sirketin.com {
import ortak_auth
reverse_proxy localhost:3000
}
prometheus.sirketin.com {
import ortak_auth
reverse_proxy localhost:9090
}
kibana.sirketin.com {
import ortak_auth
reverse_proxy localhost:5601
}
Bu yaklaşım, kullanıcı ekleme veya silme işlemlerini tek bir yerden yapmanı sağlar. Snippet’leri ayrı bir dosyaya taşıyıp import /etc/caddy/auth_users.conf şeklinde de kullanabilirsin.
Forward Auth ile Gelişmiş Kimlik Doğrulama
Basic Auth’un ciddi bir kısıtlaması var: Her uygulama için ayrı kullanıcı yönetimi, 2FA desteği yok, merkezi oturum yönetimi yok. Birden fazla uygulaması olan bir ortamda bu hızla kaosa dönüşür. Forward Auth burada kurtarıcı olur.
Forward Auth Nasıl Çalışır?
Akış şöyle işler:
- Kullanıcı
uygulama.sirketin.comadresine istek gönderir - Caddy bu isteği direkt backend’e iletmez, önce auth servisine (örneğin Authelia) bir sub-request gönderir
- Auth servisi kullanıcının oturumunu kontrol eder
- Oturum geçerliyse 200 döner ve Caddy isteği backend’e iletir
- Oturum geçersizse 401/302 döner ve kullanıcı login sayfasına yönlendirilir
Authelia ile Forward Auth Kurulumu
Authelia, self-hosted kimlik doğrulama için popüler bir seçenek. Docker Compose ile hızlıca ayağa kaldıralım:
# docker-compose.yml
version: '3.8'
services:
authelia:
image: authelia/authelia:latest
container_name: authelia
volumes:
- ./authelia/config:/config
ports:
- "9091:9091"
environment:
- TZ=Europe/Istanbul
restart: unless-stopped
redis:
image: redis:alpine
container_name: authelia_redis
volumes:
- ./authelia/redis:/data
restart: unless-stopped
Authelia için temel yapılandırma (./authelia/config/configuration.yml):
# Bu dosyayi tam olarak kopyalayin ve ihtiyaclariniza gore duzenleyin
server:
host: 0.0.0.0
port: 9091
log:
level: info
jwt_secret: cok_guclu_bir_jwt_secret_buraya_yazin
default_redirection_url: https://auth.sirketin.com
authentication_backend:
file:
path: /config/users_database.yml
access_control:
default_policy: deny
rules:
- domain: "*.sirketin.com"
policy: two_factor
session:
name: authelia_session
secret: baska_bir_guclu_secret
expiration: 3600
inactivity: 300
domain: sirketin.com
redis:
host: redis
port: 6379
storage:
local:
path: /config/db.sqlite3
notifier:
filesystem:
filename: /config/notification.txt
Caddy’de Forward Auth Yapılandırması
Authelia çalışır duruma geldikten sonra Caddy tarafını yapılandıralım:
# /etc/caddy/Caddyfile
# Auth servisi kendisi
auth.sirketin.com {
reverse_proxy localhost:9091
}
# Korunan uygulama - Authelia ile
grafana.sirketin.com {
forward_auth localhost:9091 {
uri /api/verify?rd=https://auth.sirketin.com
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
}
reverse_proxy localhost:3000
}
# Daha az kritik uygulama - sadece tek faktor
wiki.sirketin.com {
forward_auth localhost:9091 {
uri /api/verify?rd=https://auth.sirketin.com
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
}
reverse_proxy localhost:3001
}
copy_headers direktifi önemli. Authelia doğrulamadan geçen kullanıcının bilgilerini bu header’lara yazar, backend uygulamalar bu bilgileri kullanabilir. Örneğin Grafana, Remote-User header’ından kullanıcı adını alarak otomatik login yapabilir.
Authentik ile Forward Auth
Authentik (Authentik), Authelia’ya göre daha kapsamlı bir kimlik sağlayıcı. OAuth, SAML, LDAP desteği var. Forward auth yapılandırması biraz farklı:
# /etc/caddy/Caddyfile
# Authentik outpost endpoint'i
authentik.sirketin.com {
reverse_proxy localhost:9000
}
uygulama.sirketin.com {
forward_auth authentik.sirketin.com {
uri /outpost.goauthentik.io/auth/caddy
# Authentik'in set ettigi header'lari kopyala
copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Email X-Authentik-Uid
# Authentik'in kendi endpointlerine forward auth uygulanmamali
@skip not path /outpost.goauthentik.io/*
handle @skip {
forward_auth authentik.sirketin.com {
uri /outpost.goauthentik.io/auth/caddy
}
}
}
reverse_proxy localhost:8080
}
Gerçek Dünya Senaryo: Homelab Paneli
Tipik bir homelab senaryosunu ele alalım. Portainer, Grafana, Nextcloud ve bir wiki var. Nextcloud kendi auth’unu yönetiyor, diğerleri için merkezi bir çözüm istiyoruz.
# /etc/caddy/Caddyfile
# Snippet: Forward auth helper
(authelia_forward) {
forward_auth 127.0.0.1:9091 {
uri /api/verify?rd=https://auth.homelab.local
copy_headers Remote-User Remote-Groups Remote-Name Remote-Email
trusted_proxies private_ranges
}
}
# Auth portal
auth.homelab.local {
reverse_proxy 127.0.0.1:9091
tls internal
}
# Portainer - admin icin 2FA zorunlu
portainer.homelab.local {
import authelia_forward
reverse_proxy 127.0.0.1:9000
tls internal
}
# Grafana - dashboards
grafana.homelab.local {
import authelia_forward
# Grafana'ya kullanici bilgisini ilet
reverse_proxy 127.0.0.1:3000 {
header_up X-WEBAUTH-USER {http.request.header.Remote-User}
}
tls internal
}
# Nextcloud - kendi auth'unu kullaniyor
nextcloud.homelab.local {
reverse_proxy 127.0.0.1:8080 {
header_up Host {upstream_hostport}
}
tls internal
}
# Wiki.js
wiki.homelab.local {
import authelia_forward
reverse_proxy 127.0.0.1:3001
tls internal
}
tls internal direktifi Caddy’nin kendi CA’sı ile self-signed sertifika oluşturmasını sağlar. Yerel ağda kullanışlı.
Basic Auth ve Forward Auth’u Birlikte Kullanmak
Bazen her ikisini de birlikte kullanmak isteyebilirsin. Örneğin forward auth ile korunan bir API endpoint’ine programatik erişim için Basic Auth da desteklemek:
# /etc/caddy/Caddyfile
api.sirketin.com {
# API client'lari icin Basic Auth
@api_client {
path /v1/*
header Authorization "Basic *"
}
handle @api_client {
basicauth {
api_user $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvK
}
reverse_proxy localhost:8090
}
# Tarayici istekleri icin Forward Auth
handle {
forward_auth localhost:9091 {
uri /api/verify?rd=https://auth.sirketin.com
}
reverse_proxy localhost:8090
}
}
Güvenlik Notları ve Best Practices
Rate Limiting Eklemek
Basic Auth brute force saldırılarına karşı savunmasız olabilir. Caddy’nin rate_limit modülünü kullanmak için önce modülü içeren Caddy versiyonunu kullanman gerekiyor. Alternatif olarak Fail2ban ile birlikte kullanabilirsin:
# /etc/fail2ban/filter.d/caddy-auth.conf
[Definition]
failregex = ^.*"remote_addr":"<HOST>".*"status":401.*$
ignoreregex =
HTTPS Zorlamak
Caddy zaten HTTPS’i otomatik yönetir ama bir de HTTP’den redirect ekleyelim:
# /etc/caddy/Caddyfile
http://uygulama.sirketin.com {
redir https://uygulama.sirketin.com{uri} permanent
}
uygulama.sirketin.com {
basicauth {
admin $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvK
}
reverse_proxy localhost:8080
}
Aslında Caddy HTTPS’e otomatik redirect yapar, bu bloğu eklemek daha çok explicit olmak için.
Güvenli Header’lar Eklemek
Auth ile birlikte güvenlik header’larını da eklemek iyi bir pratik:
(guvenli_headerlar) {
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "strict-origin-when-cross-origin"
-Server
}
}
grafana.sirketin.com {
import guvenli_headerlar
forward_auth localhost:9091 {
uri /api/verify?rd=https://auth.sirketin.com
}
reverse_proxy localhost:3000
}
IP Kısıtlaması ile Katmanlı Güvenlik
Sadece belirli IP aralıklarından erişime izin vermek istiyorsan:
portainer.sirketin.com {
@yerel_ag {
remote_ip 192.168.1.0/24 10.0.0.0/8
}
handle @yerel_ag {
basicauth {
admin $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvK
}
reverse_proxy localhost:9000
}
handle {
respond "Erisim Engellendi" 403
}
}
Hata Ayıklama
Forward auth çalışmıyorsa önce şunları kontrol et:
- Auth servisinin çalıştığını doğrula:
curl -I http://localhost:9091/api/verify - Caddy loglarına bak:
journalctl -u caddy -f - Auth servisinin loglarına bak
- Cookie domain ayarlarının doğru olduğundan emin ol (Authelia’da
session.domain) - Sub-domain’lerin auth servisinin domain’iyle aynı üst domain’de olduğundan emin ol
Detaylı loglama için Caddyfile’a ekleyebilirsin:
{
debug
log {
output file /var/log/caddy/access.log {
roll_size 10mb
roll_keep 5
}
format json
level DEBUG
}
}
grafana.sirketin.com {
# ...
}
Global blok ({}) Caddyfile’ın en başında olmalı.
Sonuç
Caddy, Basic Auth ve Forward Auth konularında gerçekten sade ve güçlü bir çözüm sunuyor. Basic Auth, küçük ekipler veya dahili araçlar için hızlı ve yeterli bir koruma sağlarken, Forward Auth büyüyen ve olgunlaşan ortamlarda merkezi kimlik yönetiminin kapısını açıyor.
Hangi yöntemi seçeceğin ortamına bağlı: Birkaç dahili araç ve birkaç kullanıcı varsa Basic Auth yeterli ve fazlasıyla pratik. Düzinelerce uygulama, 2FA ihtiyacı ve merkezi kullanıcı yönetimi gerekiyorsa Authelia veya Authentik ile Forward Auth kaçınılmaz hale geliyor.
Şifre hash’lerini asla düz metin bırakma, her ortam için güçlü secret’lar kullan, logları düzenli izle ve mümkün olduğunca IP kısıtlamasıyla katmanlı güvenlik uygula. Caddy’nin temiz sözdizimi bu işleri yaparken seni gereksiz karmaşıklıktan koruyor, bunu bir avantaj olarak sonuna kadar kullan.