Traefik Reverse Proxy Rehber 🚀
Bu rehber, KVM sanallaştırma üzerinde Traefik reverse proxy ile production-ready bir WordPress ortamı kurulumunu adım adım açıklar.
✅ Eğitim İlerleme Durumu
Tamamlanan Konular
- [x] KVM + Cloud-init ile VM oluşturma
- [x] Docker + Docker Compose kurulumu
- [x] Traefik temel kurulum ve dashboard
- [x] Path-based routing (/whoami, /nginx, /adminer)
- [x] Middleware kullanımı (StripPrefix)
- [x] Load Balancing (Round-Robin)
- [x] Sticky Sessions (Cookie tabanlı)
- [x] WordPress + MariaDB + Redis full stack
- [x] Scaling (3+ WordPress instance)
- [x] Prometheus + Grafana monitoring
- [x] Traefik Dashboard import (Grafana)
- [x] Database + App mimarisi
- [x] Shared Volume ile dosya senkronizasyonu
Yapılacak Konular
- [ ] HTTPS/SSL (Let's Encrypt ile otomatik sertifika)
- [ ] Basic Auth / Forward Auth (Kimlik doğrulama)
- [ ] Host-based Routing (Domain bazlı yönlendirme)
- [ ] Rate Limiting (İstek sınırlama)
- [ ] Health Check (Sağlık kontrolü)
- [ ] Redis Cache aktifleştirme (WordPress Redis plugin)
- [ ] Multi-sunucu kurulumu (NFS/S3)
- [ ] MySQL Replikasyonu (Master-Slave)
- [ ] Docker Swarm / Kubernetes entegrasyonu
- [ ] CI/CD Pipeline (Otomatik deployment)
- [ ] Backup ve Disaster Recovery
- [ ] WAF (Web Application Firewall)
- [ ] CDN entegrasyonu
📋 İçindekiler
- Gereksinimler
- VM Oluşturma
- Docker Kurulumu
- Traefik Temel Kurulum
- Routing Kavramları
- Load Balancing
- WordPress Full Stack
- Monitoring (Prometheus + Grafana)
- Production Mimarisi
- Sorun Giderme
📦 Gereksinimler
Host Makine
- Ubuntu 22.04/24.04 LTS
- KVM/QEMU kurulu
- En az 8 GB RAM (VM için 4 GB)
- En az 50 GB disk
Kurulu Olması Gerekenler
# KVM araçları
sudo apt install qemu-kvm libvirt-daemon-system virtinst cloud-image-utils -y
# Ağ kontrolü
virsh net-list --all
🖥️ VM Oluşturma
1. Ubuntu 24.04 Cloud Image İndir
cd /var/lib/libvirt/images
sudo wget https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img
2. KVM Cloud-init VM Oluşturucu ile VM Oluştur
| Parametre | Değer |
|---|---|
| VM Adı | traefik-lab |
| RAM | 4096 MB |
| CPU | 2 vCPU |
| Disk | 30 GB |
| OS Variant | ubuntu24.04 |
| Network | default |
| IP Mode | DHCP |
3. VM'e Bağlan
# IP adresini öğren
virsh domifaddr traefik-lab
# SSH ile bağlan
ssh ubuntu@<VM_IP>
# Terminal düzeltmesi (gerekirse)
bash
🐳 Docker Kurulumu
1. Resmi Docker Kurulumu
# Sistem güncelle
sudo apt update && sudo apt upgrade -y
# Docker kur
curl -fsSL https://get.docker.com | sudo sh
# Kullanıcıyı docker grubuna ekle
sudo usermod -aG docker $USER
newgrp docker
# Docker'ı otomatik başlat
sudo systemctl enable docker
# Test
docker --version
docker compose version
2. Beklenen Çıktı
Docker version 29.x.x
Docker Compose version v2.x.x
🔷 Traefik Temel Kurulum
1. Proje Dizini Oluştur
mkdir -p ~/traefik-lab
cd ~/traefik-lab
2. Temel docker-compose.yml
services:
traefik:
image: traefik:v2.11
container_name: traefik
environment:
- DOCKER_API_VERSION=1.45
command:
- "--api.dashboard=true"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8080:8080" # Dashboard
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
whoami:
image: traefik/whoami
container_name: whoami
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=PathPrefix(`/whoami`)"
- "traefik.http.routers.whoami.entrypoints=web"
- "traefik.http.routers.whoami.middlewares=whoami-strip"
- "traefik.http.middlewares.whoami-strip.stripprefix.prefixes=/whoami"
restart: unless-stopped
3. Başlat ve Test Et
docker compose up -d
docker compose ps
# Test
curl http://localhost/whoami
4. Dashboard Erişimi
http://<VM_IP>:8080
🔀 Routing Kavramları
Traefik Temel Bileşenleri
| Bileşen | Açıklama |
|---|---|
| Entrypoints | Traefik'in dinlediği portlar (80, 443) |
| Routers | Gelen isteği hangi servise yönlendireceğini belirler |
| Services | Backend container'lar |
| Middlewares | İstek/yanıt üzerinde işlem yapar |
Routing Kuralları
Path-based Routing
labels:
- "traefik.http.routers.myapp.rule=PathPrefix(`/api`)"
Host-based Routing
labels:
- "traefik.http.routers.myapp.rule=Host(`app.example.com`)"
Kombinasyon
labels:
- "traefik.http.routers.myapp.rule=Host(`example.com`) && PathPrefix(`/api`)"
Middleware Örnekleri
StripPrefix
Path'i serviseden önce siler:
labels:
- "traefik.http.routers.api.middlewares=api-strip"
- "traefik.http.middlewares.api-strip.stripprefix.prefixes=/api"
Basic Auth
labels:
- "traefik.http.routers.secure.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$xyz..."
Rate Limiting
labels:
- "traefik.http.middlewares.ratelimit.ratelimit.average=100"
- "traefik.http.middlewares.ratelimit.ratelimit.burst=50"
⚖️ Load Balancing
Temel Kavram
Aynı servisten birden fazla instance çalıştırıldığında Traefik otomatik olarak istekleri dağıtır.
Scaling
docker compose up -d --scale whoami=3
Test
# Her istek farklı container'a gider
for i in {1..6}; do curl -s http://<VM_IP>/whoami | grep Hostname; done
Beklenen Çıktı (Round-Robin)
Hostname: container1
Hostname: container2
Hostname: container3
Hostname: container1
Hostname: container2
Hostname: container3
Sticky Sessions
Aynı kullanıcının her zaman aynı container'a gitmesi için:
labels:
- "traefik.http.services.myapp.loadbalancer.sticky.cookie=true"
- "traefik.http.services.myapp.loadbalancer.sticky.cookie.name=server_id"
📝 WordPress Full Stack
Mimari
┌──────────────────┐
İnternet ────▶ │ Traefik │
└────────┬─────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ WordPress │ │ WordPress │ │ WordPress │
│ #1 │ │ #2 │ │ #3 │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
└───────────────────┼───────────────────┘
▼
┌─────────────────┐
│ MariaDB │
└─────────────────┘
docker-compose.yml (Full Stack + Monitoring)
services:
traefik:
image: traefik:v2.11
container_name: traefik
environment:
- DOCKER_API_VERSION=1.45
command:
- "--api.dashboard=true"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--metrics.prometheus=true"
ports:
- "80:80"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
db:
image: mariadb:10.11
container_name: wordpress-db
environment:
MYSQL_ROOT_PASSWORD: rootpass123
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wppass123
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
container_name: wordpress-redis
wordpress:
image: wordpress:6.4-php8.2-apache
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: wppass123
WORDPRESS_DB_NAME: wordpress
volumes:
- wp_data:/var/www/html
labels:
- "traefik.enable=true"
- "traefik.http.routers.wordpress.rule=PathPrefix(`/`)"
- "traefik.http.routers.wordpress.entrypoints=web"
- "traefik.http.routers.wordpress.priority=1"
- "traefik.http.services.wordpress.loadbalancer.sticky.cookie=true"
- "traefik.http.services.wordpress.loadbalancer.sticky.cookie.name=wp_server"
depends_on:
db:
condition: service_healthy
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
command:
- '--config.file=/etc/prometheus/prometheus.yml'
grafana:
image: grafana/grafana:latest
container_name: grafana
environment:
- GF_SERVER_ROOT_URL=http://<VM_IP>/grafana
- GF_SERVER_SERVE_FROM_SUB_PATH=true
- GF_SECURITY_ADMIN_PASSWORD=admin123
labels:
- "traefik.enable=true"
- "traefik.http.routers.grafana.rule=PathPrefix(`/grafana`)"
- "traefik.http.routers.grafana.entrypoints=web"
volumes:
db_data:
wp_data:
prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'traefik'
static_configs:
- targets: ['traefik:8080']
Çalıştırma
docker compose up -d --scale wordpress=3
Erişim URL'leri
| Servis | URL |
|---|---|
| WordPress | http://<VM_IP> |
| Traefik Dashboard | http://<VM_IP>:8080 |
| Grafana | http://<VM_IP>/grafana |
Giriş Bilgileri
| Servis | Kullanıcı | Şifre |
|---|---|---|
| WordPress | admin | (kurulumda belirlenen) |
| MariaDB | wpuser | wppass123 |
| MariaDB Root | root | rootpass123 |
| Grafana | admin | admin123 |
📊 Monitoring (Prometheus + Grafana)
Grafana Kurulumu
- http://<VM_IP>/grafana adresine git
- Giriş:
admin/admin123 - Connections → Data Sources → Add → Prometheus
- URL:
http://prometheus:9090 - Save & Test
Traefik Dashboard Import
- Dashboards → New → Import
- ID:
17346 - Load → Prometheus seç → Import
🏭 Production Mimarisi
Tek Sunucu vs Multi Sunucu
Tek Sunucu (Şu Anki Lab)
┌─────────────────────────────────────┐
│ TEK SUNUCU │
│ ┌─────────────────────────────┐ │
│ │ Docker Volume │ │
│ │ (wp_data) │ │
│ └─────────────────────────────┘ │
│ ▲ ▲ ▲ │
│ │ │ │ │
│ WP #1 WP #2 WP #3 │
└─────────────────────────────────────┘
✅ Lokal volume paylaşımı çalışır
Multi Sunucu (Production)
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ SUNUCU 1 │ │ SUNUCU 2 │ │ SUNUCU 3 │
│ WP #1 │ │ WP #2 │ │ WP #3 │
│ 📁 Lokal │ │ 📁 Lokal │ │ 📁 Lokal │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└────────────────┼────────────────┘
▼
┌─────────────────┐
│ SHARED STORAGE │
│ NFS / S3 │
└─────────────────┘
❌ Lokal volume çalışmaz, shared storage lazım
Production Çözümleri
1. NFS (Network File System)
volumes:
wp_data:
driver: local
driver_opts:
type: nfs
o: addr=192.168.1.100,rw,nolock
device: ":/exports/wordpress"
2. S3 + Offload Plugin
- Media dosyaları S3'e yükle
- WordPress S3 Offload plugin kullan
- Lokal dosya sistemi sadece kod için
3. GlusterFS / Ceph
- Dağıtık dosya sistemi
- Tüm node'lar aynı dosyaları görür
Önerilen Production Mimarisi
┌─────────────────┐
│ LOAD BALANCER │
│ (Traefik) │
└────────┬────────┘
│
┌──────────────────────┼──────────────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ NODE 1 │ │ NODE 2 │ │ NODE 3 │
│ WP + PHP │ │ WP + PHP │ │ WP + PHP │
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
│ │ │
└──────────────────────┼──────────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ MySQL │ │ Redis │ │ S3 │
│ (Master) │ │ (Cache) │ │ (Media) │
└───────────┘ └───────────┘ └───────────┘
Bileşen Karşılaştırması
| Bileşen | Tek Sunucu | Multi Sunucu |
|---|---|---|
| Dosya Paylaşımı | Docker Volume ✅ | NFS/S3 gerekli |
| Session | Sticky Cookie ✅ | Redis Session |
| Cache | APCu | Redis (shared) |
| Database | Lokal MySQL | MySQL Cluster/RDS |
| Media | Lokal | S3/CDN |
🔧 Sorun Giderme
Docker API Hatası
Error: client version 1.24 is too old
Çözüm: environment ekleyin:
environment:
- DOCKER_API_VERSION=1.45
404 Not Found
Çözüm: StripPrefix middleware ekleyin veya routing kuralını kontrol edin.
Container Görünmüyor
# Logları kontrol et
docker compose logs traefik
# Container'ları listele
docker compose ps
Dashboard Boş
# Traefik'i yeniden başlat
docker compose restart traefik
VM Restart Sonrası Container'lar Başlamıyor
# Docker'ı otomatik başlat
sudo systemctl enable docker
# Container'ları başlat
cd ~/traefik-lab
docker compose up -d
📌 Hızlı Referans
Komutlar
# Başlat
docker compose up -d
# Scale
docker compose up -d --scale wordpress=3
# Durdur
docker compose down
# Loglar
docker compose logs -f traefik
# Temizlik
docker compose down -v --remove-orphans
docker system prune -af
VM Yönetimi
# VM listele
virsh list --all
# VM başlat
virsh start traefik-lab
# VM kapat
virsh shutdown traefik-lab
# VM'e bağlan
ssh ubuntu@<VM_IP>
📚 Ek Kaynaklar
Bu rehber 2025-12-05 00:09 tarihinde güncellenmiştir.