Caddy ile Dosya Sunucusu ve Dizin Listeleme Yapılandırması

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/files dizininin caddy kullanıcısına ait olduğundan emin olun. ls -la /srv/files ile kontrol edin.
  • address already in use: Nginx veya Apache zaten 80/443’ü kullanıyordur. systemctl stop nginx yapın.
  • certificate error: İç ağda HTTPS kullanıyorsanız caddy trust komutuyla yerel CA’yı sisteme tanıtın.
  • 404 on browse: root direktifinin doğru dizini gösterdiğinden ve file_server browse satırının root‘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_auth direktifiyle 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.

Yorum yapın