Caddy Web Sunucusu Kurulum ve Temel Kullanım Rehberi

Modern web altyapısında Nginx ve Apache’nin yanına güçlü bir rakip çıktı: Caddy. Go diliyle yazılmış bu web sunucusu, otomatik HTTPS, sıfır bağımlılık ve son derece sade yapılandırma dosyasıyla sistem yöneticilerinin hayatını ciddi ölçüde kolaylaştırıyor. Özellikle Let’s Encrypt sertifikalarını elle uğraşmadan otomatik alan adı doğrulamasıyla yönetmesi, Caddy’yi production ortamlarında bile tercih edilen bir çözüm haline getiriyor. Bu yazıda Caddy’yi sıfırdan kuracak, Caddyfile sözdizimini öğrenecek ve gerçek dünya senaryolarıyla yapılandırmayı kavrayacağız.

Caddy Nedir ve Neden Kullanılır?

Caddy, 2015 yılında Matt Holt tarafından geliştirilen, Go ile yazılmış modern bir web sunucusudur. Klasik web sunucularından en temel farkı otomatik TLS özelliğidir. Nginx veya Apache’de HTTPS kurmak için certbot kurmanız, cron job yazmanız, sertifika yenileme süreçlerini takip etmeniz gerekir. Caddy’de ise alan adınızı Caddyfile’a yazmanız yeterli; gerisini Caddy halleder.

Caddy’nin öne çıkan özellikleri şunlardır:

  • Otomatik HTTPS: Let’s Encrypt ve ZeroSSL üzerinden sertifika alır, yeniler, yönetir
  • HTTP/2 ve HTTP/3 desteği: Kutudan çıkar çıkmaz aktif gelir
  • Sade yapılandırma dili: Caddyfile, Nginx config’e kıyasla çok daha okunabilir
  • API tabanlı yönetim: JSON API üzerinden dinamik yapılandırma değiştirme imkanı
  • Tek binary: Hiçbir bağımlılık yok, tek dosya kurulum
  • Reverse proxy, yük dengeleme, dosya sunumu: Hepsi dahili modüller olarak geliyor

Küçük projelerde, hobi sunucularında veya hızlı prototip ortamlarında Caddy neredeyse rakipsiz. Büyük ölçekli yapılarda da özellikle HTTPS yönetimi açısından ciddi avantaj sağlıyor.

Kurulum

Ubuntu/Debian Üzerine Kurulum

Caddy’nin resmi APT deposunu sisteme ekleyerek kurulum yapabilirsiniz. Bu yöntemle hem kurulum hem de gelecekteki güncellemeler sorunsuz yönetilir.

# Gerekli paketleri kur
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl

# Caddy GPG anahtarını ekle
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' 
  | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg

# APT deposunu ekle
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' 
  | sudo tee /etc/apt/sources.list.d/caddy-stable.list

# Caddy'yi kur
sudo apt update && sudo apt install caddy

Kurulumun ardından Caddy servisi otomatik olarak başlar ve /etc/caddy/Caddyfile dosyası oluşturulur.

RHEL/CentOS/Rocky Linux Üzerine Kurulum

# COPR deposunu etkinleştir
dnf copr enable @caddy/caddy

# Caddy'yi kur
dnf install caddy

# Servisi başlat ve sistem açılışında otomatik başlasın
systemctl enable --now caddy

Binary ile Manuel Kurulum

Daha fazla kontrol isteyenler veya özel bir Caddy sürümü kullananlar için manuel kurulum seçeneği de var:

# GitHub releases sayfasından en son sürümü indir
curl -L "https://github.com/caddyserver/caddy/releases/latest/download/caddy_linux_amd64.tar.gz" 
  -o caddy.tar.gz

# Arşivi aç
tar -xzf caddy.tar.gz

# Binary'yi sistem dizinine taşı
sudo mv caddy /usr/local/bin/
sudo chmod +x /usr/local/bin/caddy

# Caddy kullanıcısını oluştur
sudo useradd --system --home /var/lib/caddy --shell /usr/sbin/nologin caddy

# Gerekli dizinleri oluştur
sudo mkdir -p /etc/caddy /var/lib/caddy /var/log/caddy
sudo chown -R caddy:caddy /var/lib/caddy /var/log/caddy

Kurulum Doğrulama

# Caddy sürümünü kontrol et
caddy version

# Servis durumunu kontrol et
sudo systemctl status caddy

# Portu dinleyip dinlemediğini kontrol et
ss -tlnp | grep caddy

Caddyfile Sözdizimi

Caddy’nin yapılandırma dosyası olan Caddyfile, minimal ve anlaşılır bir sözdizime sahip. Temel yapı şu şekilde:

alan_adi {
    direktif parametreler
}

Temel Statik Dosya Sunumu

En basit kullanım senaryosu: bir dizini web üzerinden sunmak.

# /etc/caddy/Caddyfile

example.com {
    root * /var/www/html
    file_server
}

Bu kadar. Caddy bu yapılandırmayı gördüğünde otomatik olarak Let’s Encrypt’ten SSL sertifikası alır, HTTP’yi HTTPS’e yönlendirir ve /var/www/html dizinini sunar.

Localhost üzerinde geliştirme yaparken ise Caddy kendi kendine imzalı sertifika üretir:

localhost:8080 {
    root * /home/kullanici/proje/public
    file_server
}

Reverse Proxy Yapılandırması

En sık kullanılan senaryo budur. Arkada çalışan bir Node.js, Python veya başka bir uygulama için Caddy’yi önüne proxy olarak koyuyorsunuz:

api.example.com {
    reverse_proxy localhost:3000
}

Birden fazla backend instance’ı varsa yük dengeleme de dahili olarak çalışır:

api.example.com {
    reverse_proxy localhost:3000 localhost:3001 localhost:3002
}

Caddy varsayılan olarak round-robin algoritmasıyla dağıtım yapar. İsterseniz bunu değiştirebilirsiniz:

api.example.com {
    reverse_proxy {
        to localhost:3000 localhost:3001
        lb_policy least_conn
        health_uri /health
        health_interval 10s
    }
}

lb_policy için kullanılabilir değerler:

  • round_robin: Sıralı dağıtım (varsayılan)
  • least_conn: En az bağlantıya sahip sunucuya yönlendir
  • ip_hash: İstemci IP’ye göre sabit yönlendirme
  • random: Rastgele seçim

Gerçek Dünya Senaryoları

Senaryo 1: WordPress Sitesi + PHP-FPM

Bir müşteri için shared hosting yerine VPS üzerinde WordPress kuracaksınız. PHP-FPM zaten çalışıyor, MySQL hazır. Sadece Caddy yapılandırması lazım:

wordpress.musteri.com {
    root * /var/www/wordpress
    
    # PHP dosyalarını PHP-FPM'e gönder
    php_fastcgi unix//run/php/php8.1-fpm.sock
    
    # Statik dosyaları doğrudan sun
    file_server
    
    # WordPress için gerekli yönlendirmeler
    @notFound {
        not file
        not path /wp-admin/*
    }
    rewrite @notFound /index.php
    
    # Hassas dosyalara erişimi engelle
    @sensitive {
        path /.git/* /wp-config.php /.env
    }
    respond @sensitive 403
    
    # Gzip sıkıştırma
    encode gzip
    
    # Erişim logları
    log {
        output file /var/log/caddy/wordpress.log
        format json
    }
}

Bu yapılandırma ile:

  • Otomatik HTTPS aktif
  • PHP sayfaları PHP-FPM’e yönlendiriliyor
  • Hassas dosyalar korunuyor
  • Yanıtlar sıkıştırılıyor
  • JSON formatında erişim logu tutuluyor

Senaryo 2: Mikro Servis Mimarisi

Farklı portlarda çalışan birkaç servisi tek alan adı altında toplamak istiyorsunuz:

app.example.com {
    # /api/* isteklerini backend servise gönder
    handle /api/* {
        reverse_proxy localhost:8080
    }
    
    # /auth/* isteklerini kimlik doğrulama servisine gönder
    handle /auth/* {
        reverse_proxy localhost:8081
    }
    
    # /uploads/* için doğrudan dosya servisi
    handle /uploads/* {
        root * /var/www
        file_server
    }
    
    # Gerisi React uygulaması
    handle {
        root * /var/www/frontend/build
        file_server
        try_files {path} /index.html
    }
    
    encode gzip zstd
}

try_files direktifi burada kritik: React gibi SPA uygulamalarında client-side routing için her 404’ü index.html’e yönlendirmek gerekir.

Senaryo 3: Temel HTTP Kimlik Doğrulama

Bir iç araç veya staging ortamı için basit parola koruması eklemek:

# Önce bcrypt ile parola hash'i oluştur
caddy hash-password --plaintext "gizliparola123"

Çıktı olarak bir hash string alacaksınız. Bunu Caddyfile’a ekleyin:

staging.example.com {
    reverse_proxy localhost:4000
    
    basicauth /* {
        admin $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvC
        developer $2a$14$abc123...
    }
}

Senaryo 4: Subdomain Wildcard ve Çoklu Site

Aynı sunucuda onlarca siteniz varsa wildcard eşleştirme işinizi kolaylaştırır. Bunun için DNS sağlayıcınızın API desteği gerekir (Cloudflare, Route53 vb.):

# Cloudflare DNS modülüyle Caddy'yi derle
xcaddy build --with github.com/caddy-dns/cloudflare
*.example.com {
    tls {
        dns cloudflare {env.CF_API_TOKEN}
    }
    
    @site1 host site1.example.com
    handle @site1 {
        root * /var/www/site1
        file_server
    }
    
    @site2 host site2.example.com
    handle @site2 {
        reverse_proxy localhost:5000
    }
}

{env.CF_API_TOKEN} ifadesi ortam değişkeninden token okur. Bunu /etc/caddy/caddy.env dosyasında saklayın ve systemd servis dosyasına EnvironmentFile direktifiyle dahil edin.

Yapılandırma Yönetimi

Caddyfile Doğrulama ve Yeniden Yükleme

Yapılandırma dosyanızı kaydetmeden önce mutlaka doğrulayın:

# Caddyfile sözdizimini kontrol et
caddy validate --config /etc/caddy/Caddyfile

# Servisi durdurmadan yapılandırmayı yeniden yükle
sudo systemctl reload caddy

# Veya Caddy'nin kendi komutuyla
caddy reload --config /etc/caddy/Caddyfile

systemctl reload ile Caddy zero-downtime reload yapar. Yani aktif bağlantılar kesilmez, sadece yeni yapılandırma geçerli olur.

Ortam Değişkenleri Kullanımı

API anahtarlarını veya hassas bilgileri Caddyfile’a yazmak yerine ortam değişkenlerinden okuyabilirsiniz:

# /etc/caddy/caddy.env dosyası oluştur
cat > /etc/caddy/caddy.env << EOF
CF_API_TOKEN=buraya_cloudflare_token
DB_HOST=localhost
DOMAIN=example.com
EOF

chmod 600 /etc/caddy/caddy.env

Systemd servis dosyasını düzenleyin:

sudo systemctl edit caddy

Açılan editöre şunu yazın:

[Service]
EnvironmentFile=/etc/caddy/caddy.env

Artık Caddyfile içinde {env.CF_API_TOKEN} veya {env.DOMAIN} şeklinde kullanabilirsiniz:

{env.DOMAIN} {
    reverse_proxy localhost:3000
}

Caddy JSON API

Caddy’nin güçlü yönlerinden biri REST API üzerinden dinamik yapılandırma yapabilmektir. Servis yeniden başlatmaya gerek kalmaz:

# Mevcut yapılandırmayı görüntüle
curl localhost:2019/config/

# Yeni bir route ekle (dinamik olarak)
curl localhost:2019/config/apps/http/servers/srv0/routes 
  -X POST 
  -H "Content-Type: application/json" 
  -d '{
    "match": [{"host": ["yeni-site.example.com"]}],
    "handle": [{"handler": "reverse_proxy", "upstreams": [{"dial": "localhost:7000"}]}]
  }'

# Yapılandırmayı Caddyfile formatından JSON'a çevir
caddy adapt --config /etc/caddy/Caddyfile

Log Yönetimi ve İzleme

Caddy’nin log sistemi oldukça esnek. JSON formatında loglama yapılandırması:

{
    log {
        output file /var/log/caddy/caddy.log {
            roll_size 100mb
            roll_keep 5
            roll_keep_for 720h
        }
        level INFO
    }
}

example.com {
    log {
        output file /var/log/caddy/access.log
        format json {
            time_format "2006-01-02T15:04:05Z07:00"
        }
    }
    
    reverse_proxy localhost:3000
}

Üstteki {} bloğu global ayarlar bölümüdür, alan adı bloklarının dışına yazılır.

Logları gerçek zamanlı izlemek için:

# Systemd journal üzerinden
sudo journalctl -u caddy -f

# Log dosyasını takip et
sudo tail -f /var/log/caddy/access.log | jq .

# Sadece hata loglarını gör
sudo journalctl -u caddy -p err

Güvenlik Yapılandırması

Rate Limiting

Caddy’de rate limiting için caddy-ratelimit modülü gereklidir. Ama temel koruma için header ve respond direktifleriyle bazı senaryoları ele alabilirsiniz:

api.example.com {
    # Güvenlik header'ları ekle
    header {
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
        X-XSS-Protection "1; mode=block"
        Referrer-Policy strict-origin-when-cross-origin
        Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
        -Server
    }
    
    # Belirli IP'leri engelle
    @blocked {
        remote_ip 192.168.100.50 10.0.0.100
    }
    abort @blocked
    
    reverse_proxy localhost:8080
}

TLS Yapılandırması

Varsayılan TLS ayarları genellikle yeterli olsa da ince ayar yapabilirsiniz:

example.com {
    tls {
        protocols tls1.2 tls1.3
        ciphers TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        curves x25519 secp384r1
    }
    
    reverse_proxy localhost:3000
}

Kendi Sertifikanızı Kullanmak

Let’s Encrypt yerine kendi sertifikanızı kullanmak isterseniz:

example.com {
    tls /etc/ssl/certs/example.com.crt /etc/ssl/private/example.com.key
    
    reverse_proxy localhost:3000
}

Sık Karşılaşılan Sorunlar ve Çözümleri

Port 80/443 zaten kullanımda hatası:

# Hangi servis portu kullanıyor?
sudo ss -tlnp | grep ':80|:443'

# Nginx veya Apache varsa durdur
sudo systemctl stop nginx
sudo systemctl disable nginx

Let’s Encrypt sertifika alamıyor:

Genellikle DNS henüz propagate olmamıştır veya port 80 kapalıdır. Kontrol adımları:

# Port 80'in dışarıdan erişilebilir olduğunu kontrol et
curl -v http://example.com

# DNS'in doğru IP'ye işaret ettiğini kontrol et
dig example.com +short

# Caddy loglarında detaya bak
sudo journalctl -u caddy --since "10 minutes ago"

Staging ortamı için Let’s Encrypt rate limit sorunları:

Test aşamasında gerçek sertifika almak yerine Let’s Encrypt staging ortamını kullanın:

{
    acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}

example.com {
    reverse_proxy localhost:3000
}

Sonuç

Caddy, özellikle HTTPS yönetimini otomatik hale getirmesiyle sistem yöneticilerinin tekrarlayan ve hata prone işlerini ortadan kaldırıyor. Nginx ile karşılaştırdığınızda yapılandırma dosyaları çok daha okunabilir, sertifika yenileme cron job’larıyla uğraşmak zorunda kalmıyorsunuz ve HTTP/2, HTTP/3 gibi modern protokoller kutudan çıkar çıkmaz çalışıyor.

Küçük bir VPS üzerinde birkaç site yönetiyorsanız, mikro servis mimarisinde reverse proxy ihtiyacınız varsa ya da hızlıca güvenli bir web sunucusu ayağa kaldırmak istiyorsanız Caddy mükemmel bir seçim. Büyük ölçekli yapılarda Nginx’in daha fazla özelleştirme imkanı sunduğu doğru, ancak Caddy’nin geliştirme hızı ve modül ekosistemi giderek büyüyor.

En iyi öğrenme yöntemi olduğu gibi: bir test sunucusu alın, bu yazıdaki örnekleri uygulayın ve kendi senaryolarınıza göre genişletin. Caddy’nin resmi dokümantasyonu da (caddyserver.com/docs) oldukça kapsamlı ve güncel, takıldığınız noktalarda ilk başvuru kaynağınız olsun.

Yorum yapın