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

  1. Gereksinimler
  2. VM Oluşturma
  3. Docker Kurulumu
  4. Traefik Temel Kurulum
  5. Routing Kavramları
  6. Load Balancing
  7. WordPress Full Stack
  8. Monitoring (Prometheus + Grafana)
  9. Production Mimarisi
  10. 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

  1. http://<VM_IP>/grafana adresine git
  2. Giriş: admin / admin123
  3. ConnectionsData SourcesAddPrometheus
  4. URL: http://prometheus:9090
  5. Save & Test

Traefik Dashboard Import

  1. DashboardsNewImport
  2. ID: 17346
  3. 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.