Dosya paylaşımı söz konusu olduğunda çoğu sysadmin hâlâ Nginx veya Apache’ye uzanır. Oysa Caddy, özellikle iç ağ dosya sunucuları ve geliştirme ortamları için inanılmaz derecede pratik bir alternatif sunuyor. Tek satır Caddyfile ile çalışan bir dosya sunucusu kurmak, üstüne directory listing eklemek ve bunu güvenli hâle getirmek düşündüğünüzden çok daha az zaman alıyor. Bu yazıda gerçek dünya senaryoları üzerinden Caddy’nin file server özelliğini derinlemesine inceleyeceğiz.
Caddy’nin File Server Özelliği Neden Öne Çıkıyor?
Caddy’yi diğer web sunucularından ayıran birkaç temel özellik var. Otomatik HTTPS, sıfır bağımlılıklı tek binary yapısı ve son derece okunabilir konfigürasyon sözdizimi bunların başında geliyor. File server söz konusu olduğunda ise file_server direktifi hem sadeliği hem de esnekliği bir arada sunuyor.
Nginx’te bir dizini listelemek için autoindex on; diyorsunuz, ama görünüm berbat ve özelleştirme imkânı sınırlı. Caddy’de ise hem görsel olarak daha düzgün bir arayüz geliyor hem de authentication, CORS, custom headers gibi özellikleri kolayca üstüne yığabiliyorsunuz.
Caddy file server’ın öne çıkan özellikleri:
- Otomatik HTTPS (Let’s Encrypt veya ZeroSSL)
- Yerleşik directory listing arayüzü
- Hidden dosyaları gizleme seçeneği
- Belirli dosya uzantılarını engelleme
- Symlink takibi kontrolü
- Etag ve cache header’larını otomatik yönetme
Caddy Kurulumu
Önce sistemimize Caddy kuralı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
RHEL/CentOS/Rocky Linux için:
dnf install 'dnf-command(copr)'
dnf copr enable @caddy/caddy
dnf install caddy
Kurulumu doğrulayalım:
caddy version
# Çıktı: v2.7.6 h1:...
systemctl status caddy
# Servisin durumunu kontrol ediyoruz
Caddy varsayılan olarak /etc/caddy/Caddyfile dosyasını kullanıyor. Servis dosyası /lib/systemd/system/caddy.service altında bulunuyor ve caddy kullanıcısıyla çalışıyor.
Basit File Server Yapılandırması
En temel kullanım senaryosundan başlayalım. Diyelim ki /srv/files dizinini web üzerinden erişilebilir yapmak istiyoruz.
# /etc/caddy/Caddyfile
fileserver.sirket.local {
root * /srv/files
file_server browse
}
Bu kadar. browse parametresi directory listing’i aktif ediyor. Şimdi dizini oluşturup Caddy’ye sahipliği verelim:
sudo mkdir -p /srv/files
sudo chown -R caddy:caddy /srv/files
sudo chmod -R 755 /srv/files
# Test amaçlı dosyalar oluşturalım
sudo -u caddy mkdir -p /srv/files/{belgeler,yazilim,yedekler}
sudo -u caddy touch /srv/files/belgeler/rapor-2024.pdf
sudo -u caddy touch /srv/files/yazilim/setup-v2.3.exe
# Caddy'i yeniden yükleyelim
sudo systemctl reload caddy
Tarayıcıdan http://fileserver.sirket.local adresine gittiğinizde Caddy’nin yerleşik directory listing arayüzünü göreceksiniz. Dosya boyutları, değiştirilme tarihleri ve navigasyon linklerini içeren temiz bir sayfa geliyor.
Gelişmiş File Server Direktifleri
Temel yapılandırmanın ötesine geçelim. Gerçek bir iç ağ dosya sunucusu için çok daha fazla ince ayar gerekiyor.
# /etc/caddy/Caddyfile
fileserver.sirket.local {
root * /srv/files
file_server browse {
# Gizli dosyaları listeden çıkar
hide .git .env .htpasswd *.bak *.tmp
# Dizin sıralama: name, size, time
# Bu özellik Caddy v2.6+ ile geliyor
}
# Belirli dosya türlerini indirme olarak sun
@downloads {
path *.exe *.msi *.pkg *.deb *.rpm
}
header @downloads Content-Disposition "attachment"
# Cache ayarları
header Cache-Control "public, max-age=3600"
# Dizin listeleme için özel header
encode gzip zstd
}
hide parametresi özellikle önemli. Git repolarını veya ortam değişkeni dosyalarını yanlışlıkla servis etmek istemiyorsunuz. Glob pattern desteklediği için *.bak gibi ifadeler kullanabiliyorsunuz.
Kimlik Doğrulama ile Güvenli File Server
İç ağ olsa bile dosyalarınızı açık bırakmak istemezsiniz. Caddy’de basic authentication son derece kolay:
# Önce şifreyi hash'leyelim
caddy hash-password
# Şifreyi girin, hash değerini kopyalayın
# Çıktı: $2a$14$...
# /etc/caddy/Caddyfile
fileserver.sirket.local {
root * /srv/files
basicauth /* {
ahmet $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkqzwpVqYNVMnHEBXPV23e
mehmet $2a$14$9t2.IARtHMbRNqXJCmz/T.3nXBcvjjbJNaewY0e2FyiB8JuP.nO4m
}
file_server browse {
hide .git .env *.secret
}
# Giriş denemelerini loglayalım
log {
output file /var/log/caddy/fileserver-access.log {
roll_size 50mb
roll_keep 5
}
format json
}
}
Daha kurumsal bir yapı için .htpasswd benzeri ayrı bir dosyadan okuma yapmak isteyebilirsiniz. Caddy şu an için inline hash kullanıyor, ama environment variable ile de şifre yönetimi yapılabiliyor:
# Şifreleri ortam değişkeni olarak tutmak için
# /etc/caddy/caddy.env dosyası oluşturun
AHMET_HASH=$2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkqzwpVqYNVMnHEBXPV23e
# systemd service override'a env dosyasını ekleyin
# /etc/systemd/system/caddy.service.d/override.conf
[Service]
EnvironmentFile=/etc/caddy/caddy.env
Çoklu Dizin ve Sanal Host Yapılandırması
Gerçek dünyada genellikle birden fazla bölüm için ayrı dosya sunucuları gerekiyor. Bir IT departmanının ihtiyacını karşılayan yapılandırma örneği:
# /etc/caddy/Caddyfile
# IT ekibi için genel paylaşım
files.sirket.local {
root * /srv/files/genel
file_server browse {
hide .git .env
}
basicauth /* {
ituser $2a$14$abc123hashburaya
}
}
# Yazılım deposu - sadece IT adminleri
yazilim.sirket.local {
root * /srv/files/yazilim
file_server browse
basicauth /* {
itadmin $2a$14$xyz789hashburaya
}
# Sadece iç ağdan erişime izin ver
@external {
not remote_ip 192.168.0.0/16 10.0.0.0/8
}
respond @external "Erisim reddedildi" 403
}
# Yedek dosyaları - salt okunur, sadece listeleme
yedekler.sirket.local {
root * /srv/backups
file_server browse {
hide *.log *.tmp
}
# Sadece görüntüleme, indirme engel
@nodownload {
not path */
not path *.tar.gz *.zip
}
respond @nodownload "Bu dosyayi indiremezsiniz" 403
}
Bu yapıda remote_ip matcher’ı kullanarak IP bazlı kısıtlama ekliyoruz. Dışarıdan gelen istekler için 403 dönüyor.
Otomatik HTTPS ile Production’a Taşıma
Caddy’nin en büyük avantajlarından biri gerçek bir domain için otomatik SSL sertifikası alması. Eğer sunucunuz internete açıksa:
# Public domain için - Caddy otomatik sertifika alır
files.sirketiniz.com {
root * /srv/public-files
file_server browse {
hide .git .env .htpasswd
}
basicauth /* {
kullanici $2a$14$gercek_hash_buraya
}
# Security headers
header {
X-Content-Type-Options nosniff
X-Frame-Options DENY
Referrer-Policy no-referrer
-Server
}
# Rate limiting için (Caddy enterprise'da var, community sürümü için)
log {
output file /var/log/caddy/files-access.log {
roll_size 100mb
roll_keep 7
roll_keep_for 30d
}
}
encode gzip zstd
}
Caddy sunucu başladığında otomatik olarak Let’s Encrypt’e başvuruyor, sertifikayı alıyor ve 443’te HTTPS başlatıyor. Port 80’den gelen trafiği otomatik olarak yönlendiriyor. Sertifika yenileme de tamamen otomatik.
İç ağ için self-signed veya özel CA sertifikası kullanmak istiyorsanız:
# İç ağ için TLS yapılandırması
fileserver.sirket.local {
tls /etc/caddy/certs/sirket.local.crt /etc/caddy/certs/sirket.local.key
root * /srv/files
file_server browse
}
API ile Dinamik Yapılandırma
Caddy’nin adminler arasında az bilinen özelliklerinden biri JSON API’si. Caddyfile kullanmadan REST API üzerinden yapılandırma yapabiliyorsunuz:
# Mevcut yapılandırmayı görüntüle
curl localhost:2019/config/
# Yeni bir route ekle (çalışırken, restart olmadan)
curl -X POST localhost:2019/config/apps/http/servers/srv0/routes
-H "Content-Type: application/json"
-d '{
"match": [{"host": ["yeni-files.sirket.local"]}],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{"handler": "vars", "root": "/srv/yeni-dizin"},
{"handler": "file_server", "browse": {}}
]
}
]
}
]
}'
# Yapılandırma değişikliğini kontrol et
curl localhost:2019/config/ | python3 -m json.tool
Bu özellik özellikle otomasyon senaryolarında çok işe yarıyor. Yeni bir müşteri eklediğinizde veya CI/CD pipeline’ınızda dinamik olarak yeni dosya servisleri oluşturabilirsiniz.
Pratik Senaryo: Geliştirme Ekibi için Build Artifact Sunucusu
Çok sık karşılaşılan gerçek dünya senaryosu: CI/CD pipeline’ı build artifact’larını bir dizine atıyor, geliştirici ekibi bu dosyalara web üzerinden erişmek istiyor.
# Dizin yapısını oluşturalım
sudo mkdir -p /srv/builds/{android,ios,web,backend}
sudo chown -R caddy:caddy /srv/builds
# CI runner'ın yazabilmesi için
sudo usermod -aG caddy jenkins
# veya
sudo chmod 775 /srv/builds
# /etc/caddy/Caddyfile
builds.dev.sirket.local {
root * /srv/builds
file_server browse {
hide .git *.log
}
# CI runner IP'sinden yazma izni (WebDAV değil, sadece örnek)
# Gerçekte dosyaları CI doğrudan dizine yazıyor
basicauth /* {
devteam $2a$14$devteam_hash_buraya
qateam $2a$14$qateam_hash_buraya
manager $2a$14$manager_hash_buraya
}
# Son build dosyalarını önbellekten hızlı sun
@static {
path *.apk *.ipa *.zip *.tar.gz
}
header @static {
Cache-Control "public, max-age=86400"
Content-Disposition "attachment"
}
# HTML/JSON dosyaları tarayıcıda göster
@viewable {
path *.html *.json *.txt *.log
}
header @viewable Content-Disposition "inline"
log {
output file /var/log/caddy/builds-access.log {
roll_size 50mb
roll_keep 10
}
format json
}
encode gzip
}
Bu yapılandırmada APK, IPA gibi ikili dosyalar indirme olarak sunulurken, HTML ve JSON dosyaları tarayıcıda görüntülenebiliyor. Ekip üyeleri farklı rollerle sisteme giriyor.
Sorun Giderme ve Debug İpuçları
Caddy ile çalışırken sık karşılaşılan sorunlar ve çözümleri:
# Caddyfile sözdizimini kontrol et
caddy validate --config /etc/caddy/Caddyfile
# Mevcut yapılandırmayı JSON olarak göster
caddy adapt --config /etc/caddy/Caddyfile
# Debug modunda çalıştır
caddy run --config /etc/caddy/Caddyfile --watch
# Servis loglarını takip et
journalctl -u caddy -f
# Erişim loglarını filtrele
tail -f /var/log/caddy/fileserver-access.log | jq '.request.uri'
# Sertifika durumunu kontrol et
caddy trust # local CA'yı sisteme ekler
# Port 80/443'ün kullanımda olup olmadığını kontrol et
ss -tlnp | grep -E '80|443'
Yaygın hatalar ve çözümleri:
- permission denied:
/srv/filesdizininin caddy kullanıcısına ait olduğundan emin olun.ls -la /srv/filesile kontrol edin. - address already in use: Nginx veya Apache zaten 80/443’ü kullanıyordur.
systemctl stop nginxyapın. - certificate error: İç ağda HTTPS kullanıyorsanız
caddy trustkomutuyla yerel CA’yı sisteme tanıtın. - 404 on browse:
rootdirektifinin doğru dizini gösterdiğinden vefile_server browsesatırınınroot‘tan sonra geldiğinden emin olun.
Performans Optimizasyonu
Büyük dosyalar veya yoğun trafik için ince ayarlar:
# /etc/caddy/Caddyfile
{
# Global ayarlar
servers {
timeouts {
read_body 30s
read_header 10s
write 0s # Büyük dosyalar için 0 (timeout yok)
idle 5m
}
}
}
files.sirket.local {
root * /srv/files
file_server browse {
hide .git
}
# Büyük dosyalar için buffer'ı artır
# Bu caddy'nin dahili ayarı, reverse_proxy'de daha belirgin
encode {
gzip {
level 4 # 1-9 arası, 4 iyi bir denge
}
# Büyük binary dosyaları sıkıştırma
minimum_length 1024
match {
header Content-Type text/*
header Content-Type application/json*
header Content-Type application/javascript*
}
}
# ETag ve conditional request desteği otomatik geliyor
# Tarayıcı cache için
header /static/* Cache-Control "public, max-age=604800, immutable"
}
Sıkıştırma için minimum_length ve match bloğu önemli. Zaten sıkıştırılmış ZIP, tar.gz, JPG gibi dosyaları tekrar sıkıştırmaya çalışmak hem CPU israf hem de bazen dosyayı büyütüyor.
Caddy’yi Nginx ile Birlikte Kullanma
Bazı durumlarda Caddy’yi doğrudan 80/443’e almak yerine Nginx’in arkasına reverse proxy olarak koymak isteyebilirsiniz. Bu özellikle mevcut bir Nginx kurulumunuz olduğunda geçerli:
# Caddy'yi 8080'de dinletmek için
# /etc/caddy/Caddyfile
:8080 {
root * /srv/files
file_server browse
}
# Nginx tarafında proxy geçişi
# /etc/nginx/conf.d/fileserver.conf
server {
listen 80;
server_name files.sirket.local;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Bu yaklaşım geçiş dönemlerinde veya Nginx üzerinde çalışan SSL termination’ınızı korumak istediğinizde mantıklı.
Sonuç
Caddy’nin file server özelliği, özellikle iç ağ dosya paylaşımı ve geliştirme ortamları için göz ardı edilemeyecek kadar pratik. Nginx’te beş satır konfigürasyon yazdığınız şeyi Caddy’de tek satırla halledebiliyorsunuz, üstüne de otomatik HTTPS geliyor.
Hangi durumlarda Caddy file server tercih edilmeli:
- Hızlıca iç ağ dosya sunucusu kurmak gerektiğinde
- Geliştirici ekibi için build artifact deposu oluştururken
- Küçük ve orta ölçekli şirketlerde IT dosya paylaşımı için
- HTTPS karmaşasıyla uğraşmak istemediğinizde
- Single binary ile minimum bağımlılık istediğinizde
Dikkat edilmesi gerekenler:
- Caddy enterprise olmadan bazı gelişmiş özellikler (rate limiting gibi) yok
- Çok büyük ölçekli statik dosya sunumunda Nginx hâlâ daha iyi performans veriyor
- Basic auth yetersiz kalıyorsa harici auth servislerini
forward_authdirektifiyle entegre edin
Sonuç olarak Caddy, sysadmin araç kutunuzda mutlaka yer alması gereken bir araç. File server özelliği ise günlük hayatta ne kadar sık işinize yarayacağını ilk kullandığınızda anlıyorsunuz. Deneyin, sonrasında Nginx’e geri dönmek istemeyebilirsiniz.