19 Aralık 2025 Cuma

Güncel Rehber: Docker’da Rootless Mod ile Güvenli Konteyner Çalıştırma (Adım Adım)

Rootless Docker nedir ve neden önemli?

Docker’ı klasik kurulumla kullandığınızda, arka plandaki dockerd servisi genellikle root yetkileriyle çalışır. Bu, konteyner izolasyonu güçlü olsa bile “daemon” katmanında yetki seviyesinin yüksek olduğu anlamına gelir. Rootless Docker ise Docker daemon’ını ve konteynerleri root olmayan bir kullanıcıyla çalıştırarak olası bir kaçış senaryosunda zararın etkisini düşürür. Özellikle paylaşımlı sunucular, geliştirici makineleri ve CI ortamlarında “en az ayrıcalık” yaklaşımını uygulamak için güncel ve pratik bir yöntemdir.

Bu yazıda Rootless Docker’ın ne işe yaradığını, hangi sınırlamalara sahip olduğunu ve Linux üzerinde nasıl kurup günlük kullanımda problemsiz çalıştırabileceğinizi adım adım göreceksiniz. Odak noktası, güvenliği artırırken geliştirici deneyimini mümkün olduğunca bozmadan ilerlemek.

Ön koşullar ve desteklenen sistemler

Rootless mod en sorunsuz şekilde modern Linux dağıtımlarında çalışır. Ubuntu 22.04/24.04, Debian 12, Fedora gibi sistemler uygun adaylardır. Çekirdek tarafında kullanıcı isim alanları (user namespaces) ve cgroup desteği gibi bileşenler önemlidir. Ayrıca Rootless Docker, ağ tarafında çoğunlukla slirp4netns ile kullanıcı alanı NAT kullanır; performans ve port yönlendirme mantığı root’lu kurulumdan farklı olabilir.

Bu rehberde komutlar Debian/Ubuntu çizgisinde düşünülmüştür. Fedora veya Arch kullanıyorsanız paket isimleri değişebilir, mantık aynı kalır.

1) Gerekli paketler ve Docker kurulumu

Öncelikle Docker Engine’in kurulu olması gerekir. Resmî depodan kurulum önerilir. Kurulumdan sonra Rootless için gerekli yardımcı araçlar gerekebilir. Ubuntu/Debian’da çoğu zaman aşağıdakiler işinizi görür:

Komut örneği:
sudo apt update
sudo apt install -y uidmap slirp4netns fuse-overlayfs

Burada uidmap paketi rootless çalışmada kullanıcı kimliği eşlemeleri için kritik olan newuidmap/newgidmap araçlarını sağlar. fuse-overlayfs ise overlay dosya sistemi rootless senaryolarda daha iyi performans/uyumluluk sunabilir.

2) Rootless kurulumu başlatma

Docker kurulumunuzda genellikle dockerd-rootless-setuptool.sh adlı bir kurulum aracı bulunur. Bu araç, kullanıcı düzeyinde systemd servislerini ve gerekli dizinleri oluşturur.

Komut örneği:
dockerd-rootless-setuptool.sh install

Kurulum bittiğinde size DOCKER_HOST gibi ortam değişkenlerini ayarlamanızı öneren bir çıktı gösterebilir. Rootless Docker’da daemon, kullanıcıya ait bir UNIX soketi üzerinden çalışır. Bu da varsayılan /var/run/docker.sock yerine genellikle şu tarz bir yola işaret eder:

Örnek: unix:///run/user/1000/docker.sock

3) Ortam değişkeni ve kalıcı ayar

Mevcut terminal oturumunda Rootless Docker’ı kullanmak için aşağıdaki değişkeni tanımlayabilirsiniz:

Komut örneği:
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock

Kalıcı yapmak için bunu ~/.bashrc veya kullandığınız shell’in profil dosyasına ekleyebilirsiniz. Ardından Docker istemcisinin doğru daemon’a bağlandığını doğrulayın:

Komut örneği:
docker info

Çıktıda “rootless” ile ilgili bir ibare görmeniz veya daemon’ın user socket üzerinden çalıştığını doğrulamanız gerekir. Eğer hâlâ root’lu servise bağlanıyorsa DOCKER_HOST ayarını ve terminal oturumunuzu kontrol edin.

4) Systemd ile otomatik başlatma

Rootless kurulum çoğunlukla kullanıcı seviyesinde systemd servisi oluşturur. Servisi yönetmek için:

Komut örneği:
systemctl --user status docker
systemctl --user enable --now docker

Uzak oturumlarda veya yeniden başlatmalarda kullanıcı servisi çalışsın istiyorsanız “linger” açmak gerekebilir:

Komut örneği:
sudo loginctl enable-linger $(whoami)

5) Port yönlendirme ve ağ davranışı

Rootless modda 1024 altındaki portlara (80, 443 gibi) bağlanmak bazı dağıtımlarda doğrudan mümkün olmayabilir. Geliştirme ortamında alternatif olarak 8080/8443 gibi portlar kullanabilir ya da ters vekil (reverse proxy) yaklaşımına gidebilirsiniz. Örneğin Nginx’i root yetkisiyle host’ta dinleyip trafiği rootless konteyner portuna aktarabilirsiniz.

Basit bir test için bir web sunucusu çalıştırın:

Komut örneği:
docker run --rm -p 8080:80 nginx

Ardından tarayıcıdan http://localhost:8080 ile doğrulayın. Rootless ağ katmanı kullanıcı alanında çalıştığı için bazı senaryolarda performans root’lu kurulumdan düşük olabilir; ancak güvenlik hedefiniz yüksekse bu takas kabul edilebilir.

6) Sık karşılaşılan sorunlar ve çözüm ipuçları

“newuidmap: write to uid_map failed” gibi hatalar genellikle uidmap paketinin eksikliğine veya /etc/subuid ve /etc/subgid eşlemelerinin yetersizliğine işaret eder. Çoğu sistemde kurulum aracı bunları ayarlar, ancak sorun yaşıyorsanız kullanıcıya yeterli aralık tanımlandığından emin olun.

Disk sürücüsü ve overlay problemi yaşayanlar için fuse-overlayfs önemli bir çözümdür. Ayrıca Docker’ın storage driver seçimi rootless modda farklı davranabilir. Günlükleri kontrol etmek için:

Komut örneği:
journalctl --user -u docker --no-pager -n 200

Kaynak tüketimi ve limitler konusunda da cgroup v2 uyumluluğu önemlidir. Modern dağıtımlar cgroup v2 ile daha sorunsuzdur. “docker info” çıktısında cgroup sürümünü kontrol ederek ilerleyin.

Sonuç: Rootless Docker kimler için ideal?

Rootless Docker, tek başına tüm güvenlik sorunlarını sihirli şekilde çözmez; yine de konteyner çalıştırma katmanında root yetkisini ortadan kaldırarak saldırı yüzeyini ciddi biçimde azaltır. Kişisel geliştirme makineleri, eğitim ortamları, çok kullanıcılı sistemler ve güvenlik hassasiyeti yüksek ekipler için güncel ve uygulanabilir bir yaklaşımdır. Eğer amacınız “konteyner çalıştırıyorum, ama host üzerinde root daemon istemiyorum” ise Rootless mod, bugün tercih edilebilecek en pratik çözümlerden biridir.

18 Aralık 2025 Perşembe

Web Sitelerinde Core Web Vitals İyileştirme Rehberi: INP, LCP ve CLS’yi Gerçekten Düşürmek

Core Web Vitals neden hâlâ önemli?

Google’ın Core Web Vitals metrikleri (LCP, CLS ve güncel olarak FID yerine geçen INP) sadece “SEO puanı” için değil, ziyaretçinin sayfayı akıcı kullanabilmesi için de kritik. Özellikle mobil trafikte, birkaç yüz milisaniyelik gecikme bile etkileşimi düşürüyor. Bu rehberde, geliştirici araçlarıyla sorunu bulup, kod seviyesinde uygulanabilir optimizasyonları adım adım ele alacağım.

1) Ölçmeden iyileştirme olmaz: Doğru metrik kaynağını seçin

İlk hata, yalnızca laboratuvar testlerine bakıp (Lighthouse gibi) gerçek kullanıcı verisini (field data) göz ardı etmek. Başlangıç için şu kaynakları birlikte kullanın: PageSpeed Insights (CrUX saha verisi + lab), Chrome DevTools Performance (iz sürme), WebPageTest (farklı cihaz/ağ senaryoları) ve mümkünse RUM (Real User Monitoring) ile gerçek ziyaretçiden telemetri toplama. Hedefiniz net olmalı: LCP < 2,5 sn, CLS < 0,1 ve INP < 200 ms.

2) LCP (Largest Contentful Paint): “En büyük” içeriği hızlandırın

LCP çoğu sitede “hero” görseli, başlık alanı veya üstteki büyük bir kart bileşeni olur. LCP’yi iyileştirmenin ana fikri şudur: kritik içeriğe giden yolu kısaltın. Önce DevTools’ta Performance kaydı alın, “Timings” ve “LCP” işaretini bulun; ardından LCP öğesinin ne olduğunu tespit edin.

Uygulanabilir adımlar: 1) Sunucu yanıt süresini düşürün (TTFB). CDN kullanın, HTML’i önbelleğe alın, dinamik sorguları azaltın. 2) Kritik CSS’i öne alın; sayfanın üst kısmını boyamak için gereken CSS’i geciktirmeyin. 3) Render-blocking kaynakları azaltın: büyük JS paketlerini başlangıçta yüklemek LCP’yi uzatır. 4) Web fontları için doğru stratejiyi seçin: font-display: swap gibi ayarlar, metnin beklemesini azaltır.

3) CLS (Cumulative Layout Shift): Kaymaların kaynağını kapatın

CLS çoğu zaman “reklam alanı sonradan geldi”, “görsel boyutu belirtilmedi”, “font geç yüklendi ve satırlar oynadı” gibi sebeplerle yükselir. Sorunun güzelliği şu: Genellikle birkaç net düzeltmeyle ciddi düşer.

Uygulanabilir adımlar: 1) Görseller ve iframe’ler için genişlik/yükseklik belirtin ya da CSS ile en-boy oranını sabitleyin. 2) Üst kısma dinamik banner ekliyorsanız yer tutucu alan ayırın. 3) Geç yüklenen fontlarda satır kaymasını azaltmak için benzer metriklere sahip font fallback’leri seçin. 4) “Yukarıdan açılan” çerez bildirimi gibi bileşenleri sayfa içeriğini itmek yerine, sabit konumda (overlay) tasarlamayı değerlendirin.

4) INP (Interaction to Next Paint): Etkileşim gecikmesini azaltmanın kısa yolu

INP, kullanıcının tıklama/dokunma/klavye gibi etkileşiminden sonra arayüzün bir sonraki çizimine kadar geçen süreyi ölçer. Kısaca: JS ana iş parçacığını (main thread) tıkamayın. Büyük framework projelerinde bile INP’yi düşüren en etkili hamle, “gereksiz iş”i doğru zamana yaymaktır.

Uygulanabilir adımlar: 1) Uzun süren görevleri bölün: 200–300 ms’yi aşan işlemleri küçük parçalara ayırın. 2) Olay dinleyicilerini sadeleştirin; her tıklamada ağır DOM işlemleri yapmayın. 3) “Passive event listener” kullanın (özellikle scroll/touch). 4) Üçüncü taraf script’leri (chat, analytics, tag manager) denetleyin; INP’yi en çok bunlar bozabilir. Mümkünse gecikmeli yükleyin veya daha hafif alternatiflere geçin.

5) Pratik bir kontrol listesi: Hızlı kazanımlar

Kontrol listesi: (1) Ana sayfa ve en çok trafik alan 3 şablonda ölçüm alın. (2) LCP öğesini belirleyip kritik yolu kısaltın. (3) CLS için boyut belirtmeyen medya alanlarını tespit edin. (4) INP için Performance kaydında “Long Task” avına çıkın. (5) Üçüncü taraf script’leri tek tek devre dışı bırakıp etkisini ölçün. (6) Değişiklik sonrası PageSpeed Insights + gerçek kullanıcı verisiyle doğrulayın.

6) Sık yapılan hatalar ve doğru yaklaşım

Sadece Lighthouse skorunu yükseltmeye odaklanmak çoğu zaman yanıltıcıdır; çünkü kullanıcılar farklı cihaz ve ağlarda geziyor. Diğer hata, her şeyi aynı anda optimize etmeye çalışmak. En iyi yöntem: önce en çok etkileyen metriği seçin (örneğin LCP), en büyük darboğazı giderin, sonra diğerine geçin. Küçük ama doğrulanmış iyileştirmeler, bir “büyük refactor”dan daha güvenli sonuç verir.

Sonuç

Core Web Vitals optimizasyonu, “tek seferlik” değil, ölçüm-iyileştirme döngüsüdür. LCP’de kritik içeriği hızlandırın, CLS’de düzen kaymalarını kökten engelleyin, INP’de ana iş parçacığını rahatlatın. Bu üçlüde doğru teşhis ve küçük ama hedefli dokunuşlarla hem kullanıcı deneyimini hem de organik görünürlüğü aynı anda güçlendirebilirsiniz.

Docker Compose ile Yerel Geliştirme Ortamı Kurma: PostgreSQL + Redis + Uygulama Servisi (İleri Seviye How-To)

Docker Compose neden hâlâ en pratik seçenek?

Yerel geliştirme ortamı kurarken en çok vakit yediren şey, bağımlılıkların (veritabanı, cache, mesaj kuyruğu, reverse proxy vb.) makineden makineye farklı davranmasıdır. Docker Compose, birden fazla servisi tek bir dosyada tanımlayıp ayağa kaldırarak “bende çalıştı” problemini ciddi ölçüde azaltır. Bu yazıda PostgreSQL ve Redis’i, bir uygulama servisiyle birlikte aynı ağda koşturacak; kalıcı veri, healthcheck, profil ve ortam değişkeni yönetimi gibi ileri seviye pratiklere değineceğiz.

1) Proje yapısı: düzenli başlamak önemli

Örnek bir dizin yapısı oluşturalım. Terminalde bir klasör açıp içerisine aşağıdaki gibi dosyalar koymanız yeterli: docker-compose.yml, .env ve isterseniz uygulamanız için bir Dockerfile. Uygulama diliniz önemli değil; Compose tarafında servislerin birbirini görmesi ve konfigürasyonun taşınabilir olması hedef.

2) .env ile gizli bilgileri yönetmek

Compose dosyasına gömmek yerine şifreleri ve sık değişen değerleri .env içine almak daha temizdir. Proje köküne bir .env dosyası oluşturun ve örnek olarak şunları ekleyin: POSTGRES_DB=appdb, POSTGRES_USER=appuser, POSTGRES_PASSWORD=gucluSifre123, REDIS_PASSWORD=redisSifre123. Bu dosyayı versiyon kontrolüne koymamayı unutmayın; gerekirse örnek bir .env.example

3) docker-compose.yml: PostgreSQL + Redis + app

Aşağıdaki Compose tanımı, üç servisi aynı network üzerinde çalıştırır. PostgreSQL için kalıcı volume, Redis için parola ve iki servis için healthcheck ekledik. Uygulama servisini ise örnek bir “app” konteyneri olarak tanımlıyoruz; burada kendi Dockerfile’ınızı kullanabilir ya da hazır bir imajla test edebilirsiniz.

docker-compose.yml içeriği:

version: "3.9"
services:
  db:
    image: postgres:16-alpine
    container_name: local-postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 5s
      timeout: 3s
      retries: 20

  redis:
    image: redis:7-alpine
    container_name: local-redis
    restart: unless-stopped
    command: ["sh", "-c", "redis-server --requirepass ${REDIS_PASSWORD}"]
    ports:
      - "6379:6379"
    healthcheck:
      test: ["CMD-SHELL", "redis-cli -a ${REDIS_PASSWORD} ping | grep PONG"]
      interval: 5s
      timeout: 3s
      retries: 20

  app:
    build: .
    container_name: local-app
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    environment:
      DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
      REDIS_URL: redis://:${REDIS_PASSWORD}@redis:6379/0
    ports:
      - "8080:8080"

volumes:
  pgdata:

4) Uygulama servisi için minimal Dockerfile fikri

“app” servisi için örnek bir Dockerfile ihtiyacınız olacak. Kendi stack’inize göre değişir; ancak temel prensip aynıdır: bağımlılıkları kur, kaynak kodu kopyala, uygulamayı çalıştır. Örneğin Node.js kullanıyorsanız node:20-alpine ile başlayabilir; Python’da python:3.12-slim tercih edebilirsiniz. Önemli nokta, Compose içindeki bağlantı adreslerinin db ve redis servis adları üzerinden verilmesidir; çünkü konteynerlar aynı Compose ağı içinde DNS ile birbirini bu isimlerle bulur.

5) Çalıştırma, log takibi ve durdurma

Kurulumdan sonra proje kökünde şu komut yeterlidir: docker compose up -d. İlk çalıştırmada imajlar indirileceği için birkaç dakika sürebilir. Servislerin durumunu görmek için docker compose ps, logları takip etmek için docker compose logs -f kullanın. Her şeyi kapatmak için docker compose down işinizi görür; veriyi de silmek istiyorsanız (PostgreSQL volume) docker compose down -v uygulayabilirsiniz.

6) Sık yapılan hatalar ve pratik ipuçları

En yaygın hata, uygulama içinde veritabanına localhost ile bağlanmaya çalışmaktır. Konteyner içinden “localhost”, o konteynerın kendisini ifade eder; bu yüzden bağlantı adresi db:5432 olmalı. İkinci hata, servisler hazır olmadan uygulamanın ayağa kalkmasıdır; burada kullandığımız healthcheck ve depends_on condition: service_healthy yaklaşımı bu sorunu büyük ölçüde azaltır. Son olarak, geliştirme sürecinde dosya değişikliklerini anında görmek istiyorsanız volumes ile proje klasörünü konteynere mount edebilir, fakat bu ayarı işletim sisteminize ve kullandığınız dile göre dikkatle yapmalısınız.

Sonuç: taşınabilir, tekrarlanabilir bir yerel ortam

Bu yapı sayesinde PostgreSQL ve Redis’i tek komutla ayağa kaldırıp uygulamanızla aynı ağda konuşturabilirsiniz. Üstelik ekipteki herkes aynı Compose dosyasını kullandığı için ortam farklılıkları azalır, hata ayıklama hızlanır. İsterseniz bir sonraki adım olarak profil ekleyip (ör. test/prod), ya da ters proxy (Nginx/Traefik) ile TLS ve routing katmanı ekleyerek daha da gerçekçi bir geliştirme ortamı kurabilirsiniz.

17 Aralık 2025 Çarşamba

Kubernetes’te Argo Rollouts ile Canary Dağıtımı: Adım Adım Kurulum ve Ölçüme Dayalı Otomasyon

Özet

Canary dağıtımı, üretimde yeni sürümü küçük bir trafik yüzdesiyle deneyerek hataları erken yakalamayı hedefleyen, modern ve güvenli bir yayınlama tekniğidir. Bu yazıda, Kubernetes üzerinde Argo Rollouts kullanarak canary dağıtımı nasıl kurulur, NGINX Ingress ile trafik nasıl paylaştırılır ve Prometheus ile ölçüme dayalı otomatik promosyon/geri alma (rollback) nasıl yapılır adım adım anlatıyorum.

Neden Argo Rollouts?

Argo Rollouts, Kubernetes’in Deployment nesnesine gelişmiş progressive delivery yetenekleri ekleyen bir CRD (Custom Resource Definition) çözümüdür. Canary, Blue/Green, A/B testleri, metric tabanlı onaylar, otomatik rollback ve NGINX/ALB/Istio gibi çoklu trafik yöneticileri desteği sunar. Tek komutla izleme ve görselleştirme sağlayan kubectl argo rollouts eklentisi ile süreç oldukça şeffaftır.

Gereksinimler

- Kubernetes 1.21+ bir küme (yerelde kind/minikube veya bulutta managed).
- kubectl ve yönettiğiniz namespace üzerinde yetki.
- NGINX Ingress Controller (canary anotasyonlarını destekleyen sürüm).
- Prometheus (temel HTTP başarı oranı ölçümü için).

Kurulum

1) Argo Rollouts CRD ve kontrol düzlemini kurun:
kubectl apply -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml

2) Komut satırı eklentisini yükleyin (macOS örneği):
brew install argoproj/tap/kubectl-argo-rollouts
Linux/Windows için ikili dosyayı Argo Rollouts sürüm sayfasından indirip PATH’e ekleyebilirsiniz.

3) NGINX Ingress Controller kurulu değilse resmi manifest ya da Helm chart ile kurun. Trafik yönlendirme için Rollout nesnesinde trafficRouting: nginx kullanacağız.

Manifest Tasarımı

Canary stratejisinde iki Service kullanılır: stable ve canary. Ingress, Argo Rollouts tarafından ağırlıklandırılmış şekilde bu Service’lere trafik dağıtır. Aşağıdaki örnekler özlü tutulmuştur; isimleri ve etiketleri kendi uygulamanıza göre uyarlayın.

Stable ve Canary Service (aynı selector’ı paylaşır, Rollouts yönetir):
apiVersion: v1
kind: Service
metadata:
  name: myapp-stable
spec:
  selector:
   app: myapp
  ports:
  - port: 80
    targetPort: 8080

apiVersion: v1
kind: Service
metadata:
  name: myapp-canary
spec:
  selector:
   app: myapp
  ports:
  - port: 80
    targetPort: 8080

Ingress (Argo Rollouts, bu Ingress’i kullanarak NGINX canary anotasyonlarıyla ağırlık verir):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
spec:
  rules:
 - host: myapp.example.com
   http:
    paths:
    - path: /
     pathType: Prefix
     backend:
      service:
       name: myapp-stable
       port:
        number: 80

AnalysisTemplate (Prometheus ile başarı oranı ölçümü):
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: success-rate
spec:
  args:
  - name: service
  metrics:
  - name: http-success-rate
   interval: 30s
   count: 3
   successCondition: result[0] >= 0.99
   failureLimit: 1
   provider:
    prometheus:
     address: http://prometheus-server.monitoring.svc.cluster.local:9090
     query: sum(rate(http_requests_total{service="{{args.service}}",code=~"2.."}[1m])) / sum(rate(http_requests_total{service="{{args.service}}"}[1m]))

Rollout (canary adımları, NGINX trafik yönlendirme ve metrik analizi ile):
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: myapp
spec:
  replicas: 4
  selector:
   matchLabels:
    app: myapp
  template:
   metadata:
    labels:
     app: myapp
   spec:
    containers:
    - name: web
     image: ghcr.io/org/myapp:1.1.0
     ports:
     - containerPort: 8080
  strategy:
   canary:
    canaryService: myapp-canary
    stableService: myapp-stable
    trafficRouting:
     nginx:
      stableIngress: myapp-ingress
    steps:
    - setWeight: 20
    - pause: { duration: 120 }
    - analysis:
      templates:
      - templateName: success-rate
       args:
       - name: service
        value: myapp
    - setWeight: 50
    - pause: { duration: 120 }

Dağıtımı Başlatma ve İzleme

Manifestleri uygulayın: kubectl apply -f . Ardından rollout durumunu canlı izleyin: kubectl argo rollouts get rollout myapp -w. Eklenti, hangi adımda olunduğunu, mevcut ağırlığı ve analiz sonuçlarını gösterir. Metrikler eşik altında kalırsa Argo Rollouts otomatik rollback yapar; eşik üstünde ise bir sonraki adıma geçer ve sonunda sürüm terfi eder.

İpuçları ve En Sık Yapılan Hatalar

- Prometheus sorgunuzun doğru label’ları kullandığından emin olun. Bazı exporter’larda HTTP durum etiketi code yerine status olabilir.
- NGINX Ingress sürümünüzün canary anotasyonlarını desteklediğini doğrulayın; aksi halde ağırlıklandırma çalışmaz.
- Düşük trafik ortamlarında oran metrikleri dalgalıdır. interval ve count değerlerini artırmak yalancı negatifleri azaltır.
- Rollout öncesi readinessProbe ve livenessProbe ayarlarını düzgün yapılandırın; aksi halde analiz başlamadan pod’lar çakılabilir.

Performans ve Maliyet Değerlendirmesi

Canary adımları önemlidir çünkü ağ ve uygulama gecikmelerindeki küçük oynamaları yakalar. Ancak her adımda fazladan pod ve ölçüm maliyeti oluşur. Kritik servisler için 20%→50%→100% gibi 2-3 adıma bölmek çoğu senaryoda yeterli olur. Trafik çok yüksekse daha fazla adım ve daha uzun duraklatmalarla güvenlik marjı artırılabilir.

Sonuç

Argo Rollouts, Kubernetes üzerinde canary dağıtımını pratik ve güvenli hale getiriyor. NGINX Ingress ile trafik ağırlıklandırma ve Prometheus ile metrik bazlı doğrulama birleştiğinde, üretimde hataları kullanıcıların küçük bir yüzdesiyle sınırlayıp otomatik geri alma yapabilirsiniz. Küçükten başlayın, metriklerinizi doğrulayın ve ihtiyaçlarınıza göre adım sayısı ile eşikleri düzenleyerek olgun bir progressive delivery akışı elde edin.

16 Aralık 2025 Salı

Yerelde RAG Asistanı Kurulumu: Python, FAISS ve FastAPI ile Adım Adım

RAG nedir ve neden yerelde kurmalısınız?

RAG (Retrieval-Augmented Generation), bir büyük dil modelinin (LLM) yanıt üretmeden önce kendi veritabanınızdan veya belgeliklerinizden ilgili parçaları çekmesini sağlayan bir yaklaşım. Böylece model, güncel ve doğrulanabilir bilgiye dayanarak cevap verir, halüsinasyon oranı düşer ve alanınıza özgü bir asistan elde edersiniz. Bu yazıda, internete kapalı bir ortamda, Python, FAISS ve FastAPI kullanarak hızlı ve hafif bir RAG asistanını nasıl kurabileceğinizi adım adım anlatıyorum.

Mimari bileşenler ve gereksinimler

Minimal bir RAG sistemi dört temel bileşenden oluşur: metin ön işleme ve parçalara ayırma, embedding üretimi, vektör dizin (FAISS) ve yanıt üretici (LLM). Yerel kurulum için Python 3.10+ bir ortam, sentence-transformers ile çok dilli bir embedding modeli, faiss-cpu dizini ve HTTP üzerinden istek alıp yanıtlamak için FastAPI yeterli. İsterseniz yanıt üretici olarak Ollama üzerinden Llama 3 ailesi gibi bir yerel modeli kullanabilir, ya da sisteminize uygun bir başka LLM’i bağlayabilirsiniz.

Kurulum adımları: ortam, paketler ve veri hazırlığı

Önce izole bir Python sanal ortamı oluşturun ve temel paketleri kurun. Gerekli çekirdek paketler tipik olarak fastapi, uvicorn, faiss-cpu, sentence-transformers, pydantic ve metin işleme için regex/unidecode gibi küçük yardımcılar olur. Eğer yerel bir model kullanacaksanız Ollama’yı yükleyip örneğin “llama3” veya “mistral” gibi bir modeli indirin. Belgelerinizi tek bir klasörde toplayın; PDF, DOCX ve düz metinleri mümkünse metne dönüştürüp temizleyin. Tekrarlayan başlıklar, sayfa dipnotları ve tablolar metni kirlettiği için önceden sadeleştirme yapmak ileride kaliteyi ciddi biçimde artırır.

Embedding üretimi ve FAISS ile dizinleme

RAG’in çekirdeği, metni anlam uzayına taşıyan embedding’lerdir. Türkçe ağırlıklı bir kurulum için çok dilli bir model seçmek pratik olur. intfloat/multilingual-e5-base veya sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 iyi başlangıç seçenekleridir. Belgeleri 500–800 karakter aralığında, 50–100 karakter örtüşmeli parçalara bölerseniz hem hatırlama oranı hem bağlam bütünlüğü dengelenir. Her parçayı embedding modelinden geçirip bir vektör matrisi üretin; ardından FAISS’te IndexFlatIP (cosine benzeri iç çarpım) veya daha büyük veri için HNSW/IVF tabanlı bir dizin kurun. Dizin ve meta verileri (ör. belge kimliği, başlık, sayfa numarası) disk üzerinde saklayarak soğuk başlatma sürelerini azaltabilirsiniz.

Sorgu işleme hattı: geri getirme, yeniden sıralama ve yanıt üretimi

İstemci bir soru sorduğunda önce soruyu embedding modellerinden geçirip FAISS’e benzerlik araması yapın. İlk aşamada genellikle top-k=5–8 yeterlidir. Sonuçları kalite için hafif bir yeniden sıralama (re-rank) aşamasından geçirmek özellikle uzun ve benzer parçalarda fark yaratır; isterseniz küçük bir cross-encoder veya basit bir skor birleştirme (benzerlik + anahtar kelime çakışması) yaklaşımı kullanın. Son olarak en iyi 3–5 parçayı bir prompt şablonunda LLM’e vererek yanıt üretin. İyi bir şablon, modele “yalnızca verilen bağlama dayanması”, “kaynakları listelemesi” ve “emin olmadığı noktalarda netçe belirtmesi” yönünde talimatlar içerir. Bu aşamada streaming yanıt (chunk bazlı) hem his olarak daha hızlıdır hem de istemci tarafında kullanıcı deneyimini iyileştirir.

FastAPI ile uç noktalar ve basit bir API tasarımı

Sunucu tarafında iki temel uç nokta yeterlidir: /index ve /query. İlk uç nokta yeni belge eklemeyi, embedding ve dizine yazmayı üstlenir. İkincisi kullanıcı sorusunu alır, geri getirme ve yeniden sıralama yapar, LLM’den gelen yanıtı döndürür. Yanıta kaynak parçaların kimliklerini ve güven puanlarını dahil ederseniz istemci tarafında “bu cevabın kanıtı” şeritleri gösterebilirsiniz. Üretim ortamında CORS ayarlarını, basit bir oran sınırlama (rate limit) ve temel kimlik doğrulamayı eklemeyi unutmayın.

Performans, kalite ve bakım ipuçları

İlk indekslemeyi hızlandırmak için toplu gömme (batch) boyutunu donanımınıza göre ayarlayın; CPU’da 16–64 arası genelde güvenlidir. Dizin aramasında hız/kalite dengesini sağlamak üzere IVF ya da HNSW gibi yaklaşık yakın komşu (ANN) yapılarını deneyin ve geri getirme anında efSearch benzeri parametreleri kademeli artırın. Kalite için chunk boyutu ve örtüşmesini alanınıza göre yeniden ayarlayın; teknik dökümanlarda daha uzun, SSS türü içerikte ise daha kısa parçalar daha iyi sonuç verir. Ayrıca yinelenen metinleri, versiyonlanmış kopyaları ve tarih geçmişlerini indeks dışında tutmak, cevapların tekrara düşmesini engeller.

Düzenli bir değerlendirme seti oluşturun: 30–50 soruluk, doğru cevap ve kaynak eşleşmesi içeren bir küçük benchmark ile sürümler arasında regresyon olup olmadığını görebilirsiniz. Ölçüt olarak geri getirme için recall@k, cevap üretimi için ise doğruluk, faydalılık ve kaynak isabetini manuel etiketleme ile kontrol etmek etkilidir. Basit bir geri bildirim mekanizması (kullanıcı oylaması, “yanlıştı/düzelt” düğmesi) gerçek kullanımda iyileştirme fırsatlarını hızla ortaya çıkarır.

Güvenlik, gizlilik ve dağıtım

Yerel RAG sistemleri çoğu zaman hassas verilerle çalışır. Bu nedenle PII tespiti ve maskeleme, uçtan uca TLS, erişim loglarının minimal ve anonim tutulması önemlidir. Küçük bir ek katman olarak belirli sorgulara kural tabanlı filtre uygulayabilir, gizli etiketli içerikleri yanıt bağlamına girmeden önce temizleyebilirsiniz. Dağıtım için hafif bir konteyner imajı, tek bir health-check uç noktası ve kalıcı depolama bağlanmış bir FAISS dizini çoğu ekip için yeterli, ölçeklenebilir ve sürdürülebilir bir başlangıç sunar.

Sonuç

Python, FAISS ve FastAPI ile yerelde çalışan bir RAG asistanı kurmak sanıldığından daha erişilebilir. Doğru embedding modeli, düzenli bir parçalara ayırma stratejisi ve iyi tasarlanmış bir prompt ile, alanınıza özel, hızlı ve güvenilir bir bilgi asistanına sahip olursunuz. İlk sürümü basit tutun, kullanım verisi geldikçe yeniden sıralama ve değerlendirme mekanizmasını güçlendirin; böylece hem maliyeti hem karmaşıklığı kontrol altında tutarken yüksek kaliteli cevaplar üreten bir sistem inşa edebilirsiniz.

15 Aralık 2025 Pazartesi

WebAuthn ve Passkeys ile Parolasız Giriş: Node.js Üzerinde Adım Adım Entegrasyon Rehberi

Giriş

Parolalar hem kullanıcılar hem de geliştiriciler için yıllardır en zayıf halka. Güvenlik ihlalleri, kimlik avı ve kullanım zorluğu derken şifrelerin yerini alan yeni standartlar artık olgunlaştı: WebAuthn ve Passkeys. Apple, Google ve Microsoft ekosistemlerinde yerleşik olan Passkey’ler; biyometrik doğrulama (Face ID, Touch ID), cihaz PIN’i veya güvenlik anahtarlarıyla kullanıcıyı güvenli ve hızlı şekilde doğrular. Bu yazıda, Node.js üzerinde modern bir Passkey (FIDO2/WebAuthn) entegrasyonunu adım adım ele alacağız.

Neden Passkey?

Passkey, kullanıcı tarafında kriptografik anahtar çifti üretir ve yalnızca kayıt olduğunuz alan adıyla (relying party) çalışır. Bu sayede kimlik avı saldırılarına karşı dirençlidir, veri sızıntılarında şifre yeniden kullanımı riski yoktur ve kullanıcı deneyimi önemli ölçüde iyileşir. iCloud Anahtar Zinciri ve Google Password Manager gibi yöneticiler, passkey’leri cihazlar arasında senkronize edebilir; güvenlik anahtarları (YubiKey, Titan Key) ise kurumsal ortamda donanımsal güvence sağlar.

Mimari ve Akış

WebAuthn entegrasyonu iki ana adımdan oluşur: Kayıt ve Giriş. Kayıtta sunucu bir challenge üretir, tarayıcı üzerinden kullanıcının cihazında anahtar çifti oluşturulur ve sunucuya attestation verisiyle beraber kimlik bilgisi (credential) kaydedilir. Girişte sunucu yine bir challenge üretir, cihaz özel anahtarla imzalar ve sunucu imzayı, sayacı (signCount) ve relying party değerlerini doğrular.

Ön Koşullar ve Güvenlik

Üretimde mutlaka HTTPS kullanın; WebAuthn tarayıcılar tarafından güvenli bağlam gerektirir. rpID alan adınız (ör. example.com), origin ise tam köken (ör. https://example.com) olmalıdır. Oturum yönetimi için HttpOnly, Secure ve SameSite cookie ayarlarına dikkat edin. Kullanıcı deneyimini iyileştirmek için mümkünse User Verification değerini required seçin; böylece biyometrik veya PIN doğrulaması zorunlu olur.

Sunucu Kurulumu (Node.js)

Sunucuda Express veya benzeri bir framework kullanabilirsiniz. WebAuthn doğrulama ve dönüşüm adımlarında kendiniz sıfırdan implementasyon yazmak yerine toplulukta yaygın kütüphanelerden yararlanmak geliştirme hızını artırır. Örneğin @simplewebauthn/server ve @simplewebauthn/browser ikilisi, kurulum ve doğrulama mantığını açık biçimde sunar. Kayıt için iki uç nokta tanımlayın: /register/options (kayıt seçenekleri üretir) ve /register/verify (kayıt yanıtını doğrular). Giriş için benzer şekilde /login/options ve /login/verify oluşturun.

Kayıt seçeneklerini üretirken rpID ve rpName (marka adınız), user.id (stabil benzersiz kimlik), user.name (kullanıcı adı/e‑posta), user.displayName, authenticatorSelection ve attestationType gibi alanları doldurun. Çoğu senaryo için attestationType = none, residentKey = preferred veya passkey zorunlu ise required, userVerification = required iyi varsayılanlardır. Challenge değerini kriptografik olarak güçlü bir rastgelelik ile üretin ve oturumda kısa süreli saklayın.

Kullanıcı tarayıcıda kayıt yanıtı döndüğünde sunucu tarafında doğrulama yapın. Başarılı doğrulamada şu bilgileri veritabanında tutun: credentialID (base64url), credentialPublicKey, counter (signCount), transports ve tercihen cihaz adına ilişkin meta. Bu kayıtlar kullanıcı hesabıyla ilişkilendirilir ve çoklu cihaz/passkey senaryolarında birden fazla credential desteklenir.

İstemci (Tarayıcı) Entegrasyonu

Tarayıcı tarafında navigator.credentials.create() çağrısı kayıt için, navigator.credentials.get() ise giriş için kullanılır. Modern tarayıcılarda Conditional UI desteği ile kullanıcı “Parolayı yazmadan” doğrudan giriş önerisi alabilir. Özellikle mobilde bu deneyim, geleneksel şifre formuna göre çok daha hızlıdır. İstemci kodunda sunucudan gelen PublicKeyCredentialCreationOptions veya PublicKeyCredentialRequestOptions nesnelerini doğru şekilde dönüştürmeyi (ArrayBuffer <-> base64url) unutmayın.

Passkey’lerin bulut senkronizasyonu açıksa (iCloud/Google Password Manager), kullanıcı yeni cihazında da sorunsuz giriş yapabilir. Kurumsal katmanda donanımsal güvenlik anahtarlarıyla (USB/NFC/BLE) aynı akışı takip edersiniz; sadece transports alanı farklılık gösterir.

Giriş Doğrulaması ve Sayaç Yönetimi

Girişte sunucu challenge üretir ve tarayıcı assertion döndürür. Sunucu, imzayı credentialPublicKey ile doğrular, rpIDHash ve origin kontrolünü yapar ve signCount değerini karşılaştırır. Donanım bazı senaryolarda sayacı artıramayabilir; bu durumda kütüphanenin “signCount kludge” dokümantasyonuna bakın. Başarılı doğrulamada kullanıcı oturumunu açın ve sayacı güncelleyin.

UX, Erişilebilirlik ve Geri Dönüş Planı

Kullanıcıya net talimatlar verin: “Cihazınızın biyometrisini kullanın” gibi. Geri dönüş planı olarak e‑posta tabanlı sihirli bağlantı veya tek kullanımlık kurtarma kodları tanımlayın. Güvenlik anahtarlarını tercih eden kullanıcılar için “harici anahtar ekle” seçeneği sunun. Çoklu cihaz desteğinde, kullanıcı hesabı ayarlarına eklenen/çıkarılan tüm kimlik bilgilerini listelemeniz önemlidir.

Uyumluluk ve Test

Geliştirme sürecinde webauthn.io veya tarayıcı geliştirici araçlarının “Security” ve “WebAuthn” panellerinden yararlanın. iOS Safari, Android Chrome, macOS ve Windows ortamlarında çapraz test yapın. Alan adı ve köken uyuşmazlığı en yaygın hatadır; yerelde test ederken localhost için HTTPS kullanmayı veya tünel servisleriyle geçici bir alan adı oluşturmayı düşünün.

Sonuç

Passkey ve WebAuthn, parolasız geleceğin pratik ve güvenli yolu. Node.js üzerinde birkaç uç nokta ve doğru yapılandırma ile güncel tarayıcılar ve işletim sistemleri arasında kusursuz bir deneyim sunabilirsiniz. Doğru varsayılanlar (attestation none, userVerification required), güçlü bir TLS yapılandırması, sağlam oturum yönetimi ve iyi bir geri dönüş planı ile projenizi bugün üretime taşımanız mümkün.

14 Aralık 2025 Pazar

Next.js ile Passkey (WebAuthn) Entegrasyonu: Şifresiz Giriş İçin Adım Adım Rehber

Giriş

Şifresiz kimlik doğrulama, web uygulamalarında güvenliği yükseltirken kullanıcı deneyimini de ciddi biçimde iyileştiriyor. Passkey (FIDO2/WebAuthn) tabanlı giriş, parolaları ortadan kaldırarak kimlik doğrulamayı cihazın güvenli donanımına emanet eder. Bu yazıda, Next.js ile Passkey entegrasyonunu adım adım ele alacak; sunucu ve istemci akışlarını, doğru yapılandırmayı, veri modelini ve canlıya alma ipuçlarını paylaşacağım.

Passkey ve WebAuthn Nedir?

WebAuthn, tarayıcı ile sunucu arasında kriptografik anahtarlar kullanarak kullanıcı doğrulamayı standartlaştırır. Passkey ise bu standardın son kullanıcıya yansıyan yüzü: Apple, Google ve Microsoft ekosistemlerinde anahtarlar güvenli biçimde saklanır ve cihazlar arasında senkronize olabilir. Kullanıcı, biyometri veya cihaz kilidi ile yetkilendirme yapar; sunucu tarafında hiçbir parola tutulmaz.

Neden Passkey?

- Kimlik avı (phishing) direncine sahiptir: Anahtarlar alan adına (RP ID) bağlıdır, başka bir sitede kullanılamaz.
- Kullanıcı deneyimi yüksektir: Parola üretme, hatırlama ve reset akışları büyük ölçüde ortadan kalkar.
- Uygulama bakım maliyeti azalır: Parola karma algoritmaları, karmaşık parola politikaları gibi işler minimize olur.

Önkoşullar ve Mimari

- Next.js 13/14 (App Router) veya 12 (Pages) ile Node.js 18+.
- Üretimde HTTPS zorunludur; geliştirmede localhost desteklenir.
- RP ID, alan adınız (ör. example.com) olmalı; origin tam URL’nizdir (ör. https://example.com).
- Sunucuda kriptografik doğrulama için Node runtime kullanın; Edge runtime, bazı kütüphanelerde sınırlı kalabilir.

Kütüphaneler ve Temel Akış

Node.js ekosisteminde @simplewebauthn/server ve tarayıcı tarafında @simplewebauthn/browser ile stabil bir deneyim elde edebilirsiniz. Kayıt (registration) ve giriş (authentication) iki ayrı fakat benzer akışla ilerler: Sunucu bir challenge üretir, tarayıcı navigator.credentials üzerinden güvenli cihaz akışını tetikler ve yanıt sunucuda doğrulanır.

Kayıt (Registration) Akışı

1) Sunucu uç noktası: /api/passkey/register/options
Sunucu generateRegistrationOptions ile kullanıcıya özgü bir challenge üretir. Parametrelerde rpID (alan adınız), rpName, user.id (kalıcı ve benzersiz), user.name, attestation (çoğunlukla none) ve discoverable credentials için authenticatorSelection.residentKey="preferred", userVerification="preferred" kullanabilirsiniz. Challenge’ı ve kullanıcı kimliğini kısa süreli (örn. 5 dk) Redis gibi bir depoda saklayın.

2) İstemci adımı:
Tarafınıza dönen PublicKeyCredentialCreationOptions ile @simplewebauthn/browser kütüphanesindeki startRegistration çağrılır. Tarayıcı biyometri/donanım akışını yönetir ve yanıt üretir.

3) Sunucu doğrulaması: /api/passkey/register/verify
verifyRegistrationResponse ile gelen veriyi doğrulayın. Başarılıysa veritabanına credentialId (Base64URL), publicKey, counter, transports, backedUp gibi alanları ekleyin. Aynı kullanıcı için birden fazla cihaz desteği sağlamak üzere bir “kullanıcı-kimlik bilgisi” tablosu kullanın.

Giriş (Authentication) Akışı

1) Sunucu uç noktası: /api/passkey/login/options
generateAuthenticationOptions ile challenge üretin. Kullanıcının e-posta veya kullanıcı adı verdiği senaryoda allowCredentials ile ilgili kimlik bilgilerini sınırlayabilir; tamamen kullanıcı adı girmeden “sinyalsiz” giriş için discoverable credentials’ı destekleyebilirsiniz.

2) İstemci adımı:
startAuthentication çağrısı tarayıcıda WebAuthn akışını tetikler; kullanıcı cihaz kilidi veya biyometri ile onaylar.

3) Sunucu doğrulaması:
verifyAuthenticationResponse ile yanıtı doğrulayın. Counter değeri artmıyorsa veya geriye gidiyorsa potansiyel klonlama şüphesi doğar; kontrol edip güncelleyin. Başarılı doğrulamada oturum belirtecini (HttpOnly, Secure, SameSite=Lax) ayarlayın.

Veri Modeli ve Saklama

Veri tabanı şeması örneği: user_credentials(id, user_id, credential_id, public_key, counter, transports, backed_up, created_at). credential_id ve public_key için Base64URL normalize edin. Kullanıcı silme ve cihaz yönetimi (ör. “Bu cihazı kaldır”) arayüzü sağlayın.

Yapılandırma Ayrıntıları ve İpuçları

- Origin/RP ID eşleşmesi kritik: https://app.example.com için RP ID example.com veya alt alan adınızın köküne uygun olmalı. 127.0.0.1 yerine localhost kullanın.
- HTTPS zorunlu; yalnızca http://localhost istisnadır.
- Attestation çoğu senaryoda “none”; kurumsal güven zinciri gereksiniminde metadata doğrulamayı (MDS) değerlendirin.
- userVerification: “required”, uygulamanızın risk profiline göre zorunlu biyometri sağlar.
- Challenge tek kullanımlık ve kısa ömürlü olmalı, tekrar kullanımda reddedilmeli.
- Edge vs Node: Doğrulama kütüphanesinin Node kriptosuna ihtiyacı olabilir; Next.js API Routes’ı Node runtime’da çalıştırın.

UX Önerileri

- Yeni kullanıcı kayıt akışında parolasız varsayılanı sunun; uygun cihaz yoksa e-posta sihirli bağlantı veya tek seferlik kod ile yedek akış bırakın.
- Giriş sayfasında “Passkey ile devam et” butonu tek tıklama ile süreci başlatmalı; başarısızlıkta otomatik olarak yedek akışa yönlendirin.
- Cihaz yönetimi sayfasında kayıtlı cihaz adlarını, eklenme tarihini ve kaldırma seçeneklerini gösterin.

Hata Ayıklama ve Sık Karşılaşılan Sorunlar

- “The relying party ID is not a registrable domain suffix” uyarısı: RP ID yanlış. Geliştirmede localhost kullanın; üretimde çıplak alan adı veya uygun alt alan.
- “NotAllowedError” hatası: Kullanıcı onaylamadı veya tarayıcı akışı zaman aşımına uğradı. Zaman aşımı süresini makul tutun ve net geri bildirim verin.
- “This device doesn’t support passkeys”: Eski OS/tarayıcı olabilir; güncellemeyi önerin ve yedek kimlik doğrulamasını aktif tutun.

Güvenlik En İyi Uygulamaları

- Oturum çerezlerini HttpOnly ve Secure olarak ayarlayın; CSRF riskine karşı SameSite=Lax veya CSRF belirteci kullanın.
- Rate limiting ve IP/cihaz parmak iziyle kötüye kullanımı azaltın.
- Kök alan adından başka ortamlara (staging) dağıtırken RP ID ve origin’i doğru güncelleyin.
- Yedek kurtarma (ör. e-posta + ek doğrulama) ve cihaz kaybı senaryolarını önceden tasarlayın.

Sonuç

Passkey (WebAuthn), modern web uygulamalarında güvenlik ve kullanılabilirliği aynı anda yükselten bir yapı taşı. Next.js ekosisteminde @simplewebauthn ile kısa sürede kayıt ve giriş akışlarını hayata geçirebilir, phishing’e dirençli, hızlı ve kullanıcı dostu bir kimlik doğrulama deneyimi sunabilirsiniz. Doğru RP ID/origin eşleşmesi, kısa ömürlü challenge’lar ve sağlam bir cihaz yönetimi arayüzü ile üretime hazır bir çözüm elde etmek zor değil.