10 Eylül 2025 Çarşamba

Passkey (FIDO2/WebAuthn) ile Parolasız Giriş: Adım Adım Kurulum ve En İyi Uygulamalar

Passkey nedir ve neden şimdi?

Şifreler tarihsel olarak en zayıf halkaydı: yeniden kullanım, kimlik avı, veri sızıntıları ve karmaşa. Passkey, FIDO2 ve WebAuthn standartlarını temel alarak parolayı tamamen devreden çıkarır. Kullanıcı, cihazındaki biyometrik sensör (Face ID, Touch ID, Windows Hello) veya donanımsal güvenlik anahtarıyla (YubiKey vb.) kimlik doğrular; site ise yalnızca herkese açık anahtarı saklar. Bu yaklaşım, kimlik avına dayanıklı, hızlı ve kullanıcı dostu bir deneyim sunar.

Mimari: Nasıl çalışır?

Passkey, tarayıcı ve işletim sistemi ile cihazdaki “Authenticator” (platform ya da harici) arasında köprü kuran WebAuthn API’sini kullanır. Sunucu tarafında “Relying Party” (RP) olarak adlandırılan uygulamanız, kullanıcıyı kaydederken ve oturum açarken kriptografik bir “challenge” üretir. Tarayıcı, navigator.credentials üzerinden bu challenge’ı imzalatır ve sonucu sunucuya gönderir. Sunucu, imzayı doğrular ve kullanıcıyı oturum açmış kabul eder. Bu süreçte parola yoktur; saklanan tek kalıcı bilgi, cihazın herkese açık anahtarı ve kimlikleyici meta verileridir.

Ön koşullar ve gereksinimler

- HTTPS zorunludur. Lokal geliştirme için localhost istisnadır, üretimde sertifikanızın düzgün kurulu olması gerekir.
- Modern tarayıcı desteği (Chrome, Edge, Safari, Firefox) yaygınlaşmıştır; mobil işletim sistemlerinde de yerleşik destek mevcuttur.
- Alan adı ve rpId uyumu: Örneğin uygulamanız auth.example.com’da ise RP ID’nizi example.com veya ilgili alt alan adıyla uyumlu ayarlayın.

Uygulama seçenekleri

1) Sıfırdan uygulama: Sunucu dilinize uygun bir WebAuthn kütüphanesi kullanın. Node.js için @simplewebauthn/server, Go için duo-labs/webauthn, Python için webauthn, Java için webauthn4j gibi olgun projeler mevcuttur. Bu kütüphaneler, challenge üretimi, attestation/assertion doğrulaması ve anahtar formatlarını sizin yerinize yönetir.

2) Kimlik sağlayıcıları: Auth0, Azure AD B2C, Okta, Firebase gibi servisler passkey desteğini hızla entegre etmenizi sağlar. Bu yol, güvenlik ve mevzuat tarafında işleri kolaylaştırırken, özelleştirme esnekliğini sınırlayabilir.

3) CMS ve hazır platformlar: Bazı modern CMS’ler ve e-ticaret eklentileri passkey desteği sunmaya başladı. Kod yazmadan aktivasyon yapmak mümkün olsa da RP ID, yedek yöntemler ve çok cihaz desteği gibi ayarları doğru yapılandırdığınızdan emin olun.

Adım adım temel kurulum

1) Kullanıcı modeli: Veritabanında kullanıcıya kalıcı bir benzersiz tanımlayıcı (user.id) atayın. E-posta/telefon gibi iletişim bilgilerini tutun; kurtarma senaryoları için gerekecektir.

2) Kayıt (registration) başlangıcı: /webauthn/register/options benzeri bir uç nokta üzerinden, kullanıcı için publicKeyCredentialCreationOptions oluşturun. Parametrelerde rpId, challenge (kısa ömürlü, tek kullanımlık), user bilgisi, algoritmalar (ES256 varsayılan), residentKey ve userVerification politikalarını belirleyin.

3) İstemci tarafı kayıt: Tarayıcıda navigator.credentials.create() çağrısı yapılır. Kullanıcı, biyometri veya güvenlik anahtarıyla onay verir. Dönen PublicKeyCredential nesnesini sunucuya gönderirsiniz.

4) Sunucu doğrulaması: Attestation verisini kontrol edin (origin, rpIdHash, challenge eşleşmesi, algoritmalar). Gerekirse attestation’ı “none” kabul ederek gizliliği artırın. Sonuçta credentialId, publicKey ve signCount değerlerini veritabanına kaydedin.

5) Giriş (authentication) başlangıcı: /webauthn/authenticate/options ile publicKeyCredentialRequestOptions üretin. İlgili kullanıcı için kayıtlı kimlikleyicileri gönderin ya da kullanıcı adı olmadan (discoverable credentials) giriş akışını destekleyin.

6) İstemci tarafı giriş: navigator.credentials.get() çağrısıyla imzalanmış assertion elde edilir ve sunucuya gönderilir.

7) Sunucu doğrulaması ve oturum: İmzayı publicKey ile doğrulayın, signCount artışını kontrol edin (geri sarma tespitleri için). Başarılıysa oturum oluşturun veya JWT üretin. Risk tabanlı ek doğrulamalar (cihaz parmak izi, IP, hız limiti) bu aşamada değerlendirilebilir.

UX ve güvenlik için en iyi uygulamalar

- Kullanıcıyı bilgilendirin: “Passkey, cihazınızda güvenle saklanır ve kimlik avına dayanıklıdır” gibi net açıklamalar ekleyin. İlk oturum açmada kısa bir tur (tooltip) deneyimi dönüşümü artırır.

- Çok cihaz desteği: Platform (telefon/laptop) ve harici (NFC/Bluetooth/USB) anahtarlarla kayıt izni verin. Böylece cihaz kaybında erişim riski azalır.

- Kurtarma stratejisi: En az bir yedek yöntem tanımlayın (destek bileti, güvenlik sorularından kaçının; e-posta veya TOTP daha güvenlidir). İş kritik ortamlarda yönetici onayı veya kimlik doğrulama akışıyla destekleyin.

- Gizlilik ve attestation: Çoğu tüketici uygulaması için attestation “none” politikası yeterlidir. Regülasyon gerektiren ortamlarda üretici sertifikalarını doğrulayan bir güven zinciri kullanın.

- RP ID ve alt alan adları: Oturum açma alan adınız ile uygulama alan adınız farklıysa, rpId ayarını yanlış yapılandırmak en yaygın hatalardandır. Tarayıcı hataları “rpId mismatch” olarak döner.

- Performans: Challenge süre sonunu kısa (örn. 60–120 sn) tutun, CDN önbelleğini bu uç noktalardan uzak tutun. Mobil tarayıcıların arka plan kısıtlarına dikkat edin.

Test ve sorun giderme

- Sanal kimlikleyici: Chrome DevTools > More tools > Virtual authenticator environment ile local test yapın; farklı alg, UV politikaları ve resident key senaryolarını simüle edin.

- Uçtan uca test: WebAuthn.io gibi topluluk araçlarıyla doğrulama akışınızı karşılaştırın. Farklı tarayıcı ve platformlarda (iOS, Android, Windows, macOS) gerçek cihaz testleri yapın.

- Yaygın hatalar: NotAllowedError (kullanıcı iptali veya zaman aşımı), InvalidStateError (mevcut credential ile tekrar kayıt), COSE algoritma uyumsuzluğu (ES256 önerilir) ve saat farkları (server/client saat uyuşmazlığı) sık karşılaşılır. Log’larda challenge-id eşleşmesini ve origin değerini mutlaka izleyin.

Sonuç

Passkey, hem güvenlik hem de kullanıcı deneyimi açısından parolaların doğal halefidir. Doğru RP ID yapılandırması, sağlam bir kurtarma stratejisi ve tarayıcılar arası test ile haftalar içinde üretime alınabilir. İster hazır bir kimlik sağlayıcısıyla hızlıca başlayın, ister kendi WebAuthn katmanınızı inşa edin; passkey, kimlik avına dayanıklı, hızlı ve modern bir giriş deneyimini standart hale getirir.

9 Eylül 2025 Salı

Ollama ve ChromaDB ile Yerel RAG Sistemi Kurulumu: Adım Adım Geliştirici Rehberi (2025)

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

Retrieval-Augmented Generation (RAG), büyük dil modellerinin (LLM) kurumsal veya özel verilerle beslendiğinde daha güncel, doğru ve izlenebilir cevaplar üretmesini sağlayan bir yaklaşım. Kısaca, önce vektör veritabanı üzerinden ilgili doküman parçalarını buluyor, sonra bu parçaları modelin istemine ekleyerek yanıt oluşturuyoruz. Yerel RAG ise verinizin cihazınızda kalmasına, maliyetin düşmesine ve düşük gecikme ile çalışmanıza olanak tanır. Bu yazıda Ollama, ChromaDB ve açık kaynak modellerle tamamen yerel bir RAG sistemi kuracağız.

Mimari ve gereksinimler

Mimari: (1) Gömme (embedding) modeli ile dokümanları vektörleştir, (2) ChromaDB’ye kaydet, (3) Soru geldiğinde en alakalı parçaları geri getir (retrieve), (4) LLM’e bu bağlamı vererek cevabı üret.

Gereksinimler: 8 GB+ RAM (tercihen 16 GB), modern CPU; GPU varsa daha iyi. macOS, Linux veya Windows üzerinde çalışabilir. Python 3.10+, ve terminal erişimi gerekir.

Kurulum: Ollama, model ve ChromaDB

1) Ollama kurulum
macOS: brew install ollama
Linux: curl -fsSL https://ollama.com/install.sh | sh
Windows: Resmi MSI kurulum paketini indirip çalıştırın
Ardından servis: ollama serve

2) Modelleri indir
ollama pull llama3.1:8b-instruct
ollama pull nomic-embed-text
Not: Kaynaklar kısıtlıysa daha ufak bir model (ör. llama3.2:3b-instruct) seçebilirsiniz. Embed modeli olarak mxbai-embed-large da iyi sonuç verir.

3) Python bağımlılıkları
python -m venv .venv && source .venv/bin/activate
pip install chromadb fastapi uvicorn pydantic
İsteğe bağlı: yeniden sıralama (re-ranking) için pip install sentence-transformers

Veri yükleme ve vektörleştirme

Dokümanlarınızı data/ klasörüne (PDF, TXT, MD) yerleştirdiğinizi varsayalım. Basitlik için düz metin örnekliyoruz. Üretim ortamında PDF parçalama (chunking) ve OCR katmanı düşünebilirsiniz.

Basit Python ingestor
import os, requests, uuid
import chromadb
from chromadb.utils import embedding_functions

OLLAMA_URL = "http://localhost:11434/api/embeddings"
EMBED_MODEL = "nomic-embed-text"

def embed_texts(texts):
  vecs = []
  for t in texts:
    r = requests.post(OLLAMA_URL, json={"model": EMBED_MODEL, "input": t})
    r.raise_for_status()
    vecs.append(r.json()["embedding"])
  return vecs

client = chromadb.PersistentClient(path="chroma_store")
collection = client.get_or_create_collection(name="docs", embedding_function=embed_texts)

def chunk(text, size=700, overlap=120):
  out=[]; i=0
  while i < len(text):
    out.append(text[i:i+size])
    i += size - overlap
  return out

docs_dir = "data"
for fname in os.listdir(docs_dir):
  path = os.path.join(docs_dir, fname)
  if not os.path.isfile(path): continue
  text = open(path, "r", encoding="utf-8").read()
  chunks = chunk(text)
  ids = [str(uuid.uuid4()) for _ in chunks]
  metas = [{"source": fname} for _ in chunks]
  collection.add(documents=chunks, metadatas=metas, ids=ids)
print("Indeksleme tamam.")

Sorgulama ve yanıt üretimi

Sorguda, ChromaDB’den en alakalı parçaları çekip bunları LLM istemine ekleyeceğiz. Ollama’nın üretim API’sini kullanacağız.

Basit sorgu/cevap
import requests
GEN_URL = "http://localhost:11434/api/generate"

def ask(query, k=4):
  res = collection.query(query_texts=[query], n_results=k)
  contexts = [d for d in res["documents"][0]]
  sources = [m["source"] for m in res["metadatas"][0]]
  context_block = "\\n\\n".join([f"[{i+1}] {c}" for i,c in enumerate(contexts)])
  prompt = f"Kontekstten yararlanarak yanıtla. Bilgiyi uydurma. Kaynak numaralarını belirt.\\nKontekst:\\n{context_block}\\n\\nSoru: {query}\\nCevap:"
  r = requests.post(GEN_URL, json={"model":"llama3.1:8b-instruct","prompt":prompt,"stream":False,"options":{"temperature":0.2}})
  r.raise_for_status()
  answer = r.json()["response"]
  return answer, list(set(sources))

print(ask("Şirketimizin yedekleme politikası nedir?"))

FastAPI ile basit REST API

Uygulamanızı diğer servislerin kullanabilmesi için REST olarak sunabilirsiniz.

from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()

class Q(BaseModel):
  query: str

@app.post("/ask")
def api_ask(q: Q):
  answer, sources = ask(q.query)
  return {"answer": answer, "sources": sources}

# Çalıştır: uvicorn app:app --reload --port 8000

Doğrulama, kalite ve ölçüm

- Halüsinasyonları azaltmak için sıcaklığı 0.0–0.3 aralığında tutun, prompt’a “bilgiyi uydurma, bilmiyorsan söyle” ifadesini ekleyin.
- Geri getirilen parça sayısını (k) 3–8 arası deneyin; çok yüksek k, gürültü katar.
- Parça boyutu (chunk size) 500–1000 arası genelde iyi sonuç verir, 10–15% örtüşme koruyun.
- Yeniden sıralama: Sentence-Transformers ile cross-encoder/ms-marco-MiniLM-L-6-v2 gibi bir re-ranker, isabeti belirgin artırabilir.
- Değerlendirme: Küçük bir altın soru-cevap seti hazırlayın; doğru kaynağa referans verilip verilmediğini ölçün.

Performans ve maliyet ipuçları

- Kantizasyon: Ollama’da llama3.1:8b-instruct-q4_K_M gibi kantize varyantlar RAM tüketimini düşürür.
- Önbellek: Sorgu → bağlam → cevap üçlüsünü dosya veya Redis ile önbelleğe alın. Yinelenen sorularda gecikme dramatik düşer.
- GPU: Metal (macOS) veya CUDA (Linux/Windows) desteği varsa model çıkarımı hızlanır.
- İndeks: ChromaDB’de kalıcı depolama (PersistentClient) ile büyük koleksiyonlarda yeniden başlatma maliyeti azalır.

Güvenlik ve uyumluluk

Yerel RAG’in en büyük artısı veri egemenliği. Yine de şu tedbirleri alın: hassas alanları maskeyle; kaynak metaverileri log’layın; modeli “yanlış kullanım” prompt’larına karşı kıstırın; uç noktalara (FastAPI) kimlik doğrulama ekleyin; yedekleri şifreleyin.

Hata ayıklama ve sık görülen problemler

- Bağlantı hatası: Ollama servisinin 11434 portunda çalıştığını doğrulayın (curl localhost:11434).
- Out-of-memory: Daha küçük/quantize model çekin; eşzamanlı istekleri düşürün.
- Alakasız sonuçlar: Farklı embedding modeli deneyin; chunk’ları daha iyi bölün; re-ranker ekleyin.
- Dil karışması: Prompt’u Türkçe olarak sabitleyin ve cevabı Türkçe isteyin.

Sonuç

Bu rehberle, Ollama ve ChromaDB kullanarak tamamen yerelde çalışan, ölçeklenebilir ve gizlilik dostu bir RAG sistemi kurdunuz. Temeller oturduktan sonra re-ranking, çoklu koleksiyon, rol tabanlı erişim ve kullanım analitiği gibi katmanları ekleyerek üretim kalitesine taşıyabilirsiniz. Küçük bir dizüstü bilgisayarda bile tatmin edici yanıtlar alınabildiğini görmek, RAG’in 2025’te neden “uygulamaya dönük yapay zekânın” omurgası olduğunu net biçimde gösteriyor.

8 Eylül 2025 Pazartesi

Dizüstünüzde Yerel Yapay Zeka: Ollama ile LLM Çalıştırma ve API Entegrasyonu (Güncel Rehber)

Giriş

Yerel olarak çalışan büyük dil modelleri (LLM), gizlilik, gecikme süresi ve maliyet açısından bulut tabanlı çözümlere güçlü bir alternatif sunuyor. Özellikle geliştiriciler, veri güvenliği kritik olan kurumlar ve offline çalışması gereken uygulamalar için yerel LLM’ler ciddi avantaj sağlıyor. Bu rehberde, açık kaynak odaklı Ollama ile Windows, macOS ve Linux üzerinde LLM çalıştırmayı, ilk model indirme ve etkileşim, API entegrasyonu ve performans ipuçlarını adım adım anlatıyorum.

Neden Yerel LLM?

Gizlilik ve kontrol: Veriniz makinenizden çıkmaz. Hassas dokümanlar, müşteri bilgileri veya fikri mülkiyet içerikleri buluta gönderilmeden işlenir.

Düşük gecikme: İnternet bağlantısı ve servis yoğunluğundan bağımsız, tutarlı yanıt süreleri elde edilir.

Maliyet: Deney, prototip ve düşük trafikli senaryolarda API maliyetleri olmadan ilerleme şansı sağlar.

Özelleştirme: Modeli ve çalışma parametrelerini dilediğiniz gibi ayarlayabilir, hatta kendi verilerinizle yerelde ince ayar (LoRA) yapabilirsiniz.

Önkoşullar ve Donanım Notları

- RAM: 8 GB minimum; 16 GB ve üzeri rahat bir deneyim sunar. Büyük bağlam pencereleri (context) için daha fazla RAM yararlıdır.

- GPU/VRAM: GPU hızlandırma şart değil, ancak 6–8 GB VRAM orta boy modellerde belirgin hız kazandırır. Apple Silicon (M1/M2/M3) cihazlarda Metal hızlandırma iyi sonuç verir.

- Disk: Modellerin boyutu kuantizasyona göre değişir. 4–10 GB arası tek bir model için tipik bir aralıktır; birden fazla model planlıyorsanız boş alanı buna göre düşünün.

Ollama Kurulumu

macOS: Homebrew kullanıyorsanız brew install ollama komutuyla kurulum yapabilirsiniz. Alternatif olarak resmi sitedeki yönergeleri izleyebilirsiniz.

Windows: Resmi yükleyiciyi indirip çalıştırın. Kurulumdan sonra Ollama hizmeti arka planda çalışmaya başlar.

Linux: Dağıtımınıza uygun olarak resmi kurulum komutunu kullanın. Tipik kurulum için: curl -fsSL https://ollama.com/install.sh | sh. Ardından servisi başlatın: ollama serve.

İlk Modeli Çalıştırma

Ollama, “komut ver, model çekilsin ve çalışsın” deneyimi sunar. Örneğin:

ollama run mistral

Komut, ilgili modeli indirir ve etkileşimli bir kabuk açar. Alternatif olarak bir başka popüler seçenek:

ollama run llama3

İlk mesajınızı yazıp Enter’a basmanız yeterli. Çıkmak için /bye kullanabilirsiniz.

Model Yönetimi ve Faydalı Komutlar

ollama list — İndirilen modelleri ve boyutlarını listeler.

ollama pull MODEL_ADI — Modeli önceden indirir (ör. ollama pull llama3).

ollama show MODEL_ADI — Parametreler ve etiketler hakkında bilgi verir.

ollama rm MODEL_ADI — İlgili modeli diskten kaldırır.

API ile Entegrasyon

Ollama yerelde bir HTTP API sunar. Varsayılan uç nokta: http://localhost:11434. Basit bir üretim (generate) çağrısı için:

curl http://localhost:11434/api/generate -d '{ "model": "mistral", "prompt": "Merhaba! Bugün hava nasıl?" }'

Streaming yanıt almak için istemcinizde chunk’ları işleyebilir veya HTTP/2 ile daha pürüzsüz bir akış sağlayabilirsiniz. Çoğu dilde basit bir fetch/requests ile entegrasyon dakikalar içinde tamamlanır. Parametreler (ör. temperature, top_p, num_ctx) aynı JSON içinde belirtilebilir.

Performans İpuçları

Kuantizasyon seçimi: Küçük disk izi ve hızlı ilk token için Q4 serisi (ör. q4_k_m) iyi bir başlangıçtır; kalite gerekirse Q5/Q6 düşünebilirsiniz. Ollama çoğu model için mantıklı bir varsayılan indirir.

Bağlam penceresi (num_ctx): Daha büyük bağlam, daha çok RAM/VRAM kullanır. İhtiyacınıza göre 4K–16K aralığında deneyin.

GPU kullanımı: Uygunsa GPU hızlandırmayı etkinleştirin. NVIDIA için sürücü/CUDA tarafı düzenli; Apple Silicon’da Metal otomatikleşmiştir. Çalışma anında performans farkını kolayca hissedersiniz.

İlk token süresi: Soğuk başlangıçta üst seviye modeller birkaç saniye geç yanıt verebilir. Sık kullanılan modelleri “sıcak” tutmak için servis açık kalsın.

Kaliteyi Artırma: İpuçları ve Prompt Tasarımı

Sistem talimatı: Yanıtı kısıtlamayan, görev odaklı net bir sistem mesajı üretim kalitesini yükseltir.

Yapılandırılmış çıktı: JSON şema, maddeler veya adım adım çözüm isteyin. Örneğin: “Lütfen JSON döndür: {title, summary, keywords}”.

Kısa bağlamlar: Gereksiz detayları azaltıp örnek odaklı içerik verin; yerel modellerde bağlam ekonomisi fark yaratır.

Güvenlik ve Kurumsal Kullanım

Yerelde çalışma, veri sızıntısı riskini doğal olarak azaltır. Yine de uygulama düzeyinde giriş/çıkış filtreleri, PII maskeleme ve log politikasını konumlandırın. Paylaşılan iş istasyonlarında model dizinlerinin erişim izinlerini düzenlemek iyi bir fikirdir.

Sorun Giderme

Model indirme yavaş: Ayna (mirror) seçeneklerini kullanın ya da indirmeyi önceden planlayın. Ağ kesintilerinde indirme tekrar başlatılabilir.

Yüksek bellek kullanımı: Daha agresif kuantizasyon seçin, num_ctx değerini düşürün veya daha küçük bir model deneyin.

Yanıt kalitesi yetersiz: Talimatı netleştirin, örnek verin, gerekirse farklı bir model ailesi (mistral, llama, phi, qwen) deneyin.

Sonuç

Ollama, yerel LLM çalıştırmayı basit bir komutla mümkün kılıyor. Geliştirici bilgisayarında hızlı prototip, kurum içinde gizli veriyle güvenli deneme veya offline asistan gibi senaryolarda verimli bir temel sunuyor. Kurulumu tamamlayıp ilk modeli koşturduktan sonra, API üzerinden uygulamanıza entegre etmek yalnızca birkaç satır kod. Doğru kuantizasyon ve bağlam ayarıyla, oldukça akıcı ve ekonomik bir yapay zeka deneyimi elde edebilirsiniz.

7 Eylül 2025 Pazar

Docker Buildx ile Çok Mimarili İmaj Oluşturma ve GitHub Actions ile Otomatik Yayınlama (2025 Rehberi)

Giriş

Apple Silicon (ARM64), Raspberry Pi gibi cihazlarla birlikte “aynı imajı farklı mimarilerde çalıştırma” ihtiyacı günlük hayatın bir parçası oldu. Docker Buildx, tek bir komutla linux/amd64 ve linux/arm64 için çok mimarili (multi-arch) imajlar üretmenizi sağlıyor. Bu rehberde, yerelde Buildx ile derleme, doğru Dockerfile pratikleri, imajı Docker Hub’a itme ve son olarak GitHub Actions ile otomatik yayımlamayı adım adım anlatıyorum.

Önkoşullar

- Docker 24+ veya Docker Desktop (BuildKit varsayılan açık olmalı)
- Docker Hub veya GHCR hesabı (örneklerde Docker Hub kullanacağım)
- GitHub deposu (Actions için)

Buildx Kurulumu ve Kontrolü

Güncel Docker Desktop, buildx ve QEMU emülasyonu ile birlikte gelir. Terminalde aşağıdaki komutlarla Buildx’in aktif olduğunu kontrol edin:

docker buildx version
docker buildx ls

Gerekirse yeni bir builder oluşturabilirsiniz:

docker buildx create --name multiarch --use
docker buildx inspect --bootstrap

“qemu not registered” gibi bir hata alırsanız, Docker Desktop’ı güncelleyin veya Linux için QEMU’yu kurun. Çoğu yeni kurulumda ekstra adım gerekmeyecektir.

Örnek Dockerfile (Go ile statik ikili)

Dil bağımsız olarak çalışabilirsiniz; ancak Go ile statik ikili üretmek multi-arch derlemelerde idealdir. Minimal ve güvenli bir imaj için distroless veya scratch tabanını tercih edin.

# Dockerfile
# 1) Build aşaması
FROM golang:1.22-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# CGO kapalı, statik derleme
RUN CGO_ENABLED=0 GOOS=linux GOARCH=$(go env GOARCH) go build -ldflags="-s -w" -o app ./cmd/server

# 2) Minimal çalışma aşaması
FROM gcr.io/distroless/static:nonroot
WORKDIR /app
COPY --from=builder /src/app /app/app
USER nonroot:nonroot
EXPOSE 8080
ENTRYPOINT ["/app/app"]

Not: Go projesinde “./cmd/server” yolu örnektir. Projenize göre düzenleyin. Go dışındaki dillerde (Node.js, Python) multi-stage ve mimariye uygun resmi taban imajları kullanın. .dockerignore dosyasıyla gereksiz dosyaları dışarıda bırakmayı unutmayın.

Yerelde Çok Mimarili İmaj Derleme ve İtme

Önce Docker Hub’a giriş yapın:

docker login

Ardından Buildx ile iki mimariye birden derleyip tek bir çoklu manifest altında toplayın ve push edin:

docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t KULLANICI_ADI/uygulama:1.0.0 \
  -t KULLANICI_ADI/uygulama:latest \
  --provenance=true --sbom=true \
  --push .

Manifest’i doğrulamak için:

docker buildx imagetools inspect KULLANICI_ADI/uygulama:latest

GitHub Actions ile Otomatik Yayınlama

Her push veya tag ile otomatik imaj üretmek için .github/workflows/docker.yml adında bir iş akışı oluşturun. Aşağıdaki örnek, semantik sürüm etiketlerini otomatik algılar ve iki mimariye birden push eder. Docker Hub kullanıcı adı ve erişim token’ınızı repo Secrets kısmında DOCKERHUB_USERNAME ve DOCKERHUB_TOKEN olarak saklayın.

name: Docker Multi-Arch

on:
  push:
    branches: [ "main" ]
    tags: [ "v*" ]

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      id-token: write
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Docker metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: |
            ${{ secrets.DOCKERHUB_USERNAME }}/uygulama
          tags: |
            type=ref,event=branch
            type=ref,event=tag
            type=sha

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
          provenance: true
          sbom: true

Bu akışta setup-qemu-action emülasyon için, build-push-action ise derleme ve push için kullanılır. metadata-action, tag yönetimini kolaylaştırır; main branch için “latest” benzeri etiketler ve tag push için semantik sürümler üretir.

OCI Etiketleri, Güvenlik ve İpuçları

- OCI etiketleri (org.opencontainers.image.*) ile kaynak kod, lisans ve açıklama bilgilerini ekleyin. metadata-action bunu otomatik sağlar.
- sbom: true ve provenance: true ile tedarik zinciri görünürlüğünü artırın.
- .dockerignore ile node_modules, build çıktıları, test verileri gibi gereksiz klasörleri dışarıda tutun; imaj boyutu ve gizlilik açısından önemlidir.
- Çok aşamalı (multi-stage) Dockerfile ile sadece gereken dosyaları çalışma imajına kopyalayın.
- Bazı dil ekosistemlerinde mimariye özgü bağımlılıklar olabilir. Özellikle Python’da native modüller içeren paketlerde uygun taban imajını ve derleme araçlarını kullanın.

Yaygın Hatalar ve Çözümleri

- Hata: “no match for platform in manifest” — Kullandığınız baz imaj ilgili mimariyi desteklemiyor. Aynı imajın çok mimarili varyantını (ör. alpine, debian-slim) tercih edin.
- Hata: “exec format error” — Yanlış mimari için derlenmiş ikiliyi çalıştırıyorsunuz. Multi-stage içinde hedef GOARCH/GOOS (veya eşdeğerleri) doğru ayarlanmalı.
- Hata: “qemu not registered” — QEMU emülasyonu kurulu değil. GitHub Actions’ta setup-qemu-action kullanın; yerelde Docker Desktop güncel olsun.
- Hata: “denied: requested access to the resource is denied” — Registry girişiniz veya tag adı hatalı. docker login ve depo adını doğrulayın.

Sonuç

Buildx sayesinde tek bir komutla amd64 ve arm64 için üretim yapabilir, tek bir etiket altında birleştirip dağıtabilirsiniz. GitHub Actions ile bunu CI/CD’ye bağladığınızda yeni sürümleriniz saniyeler içinde Docker Hub’a düşer. Doğru baz imaj, temiz Dockerfile ve önbellekleme stratejileri ile hem derleme sürenizi hem de imaj boyutlarınızı önemli ölçüde iyileştirebilirsiniz.

6 Eylül 2025 Cumartesi

Docker ve OpenTelemetry ile Node.js Uygulamasında Dağıtık İzleme: Adım Adım Kurulum Kılavuzu

Giriş

Modern mikroservis mimarilerinde bir isteğin sistem içinde nasıl yol aldığını anlamak, performans sorunlarını çözmek ve kök neden analizi yapmak için dağıtık izleme artık bir zorunluluk. OpenTelemetry (OTel), dil bağımsız açık standartları ve zengin SDK’ları ile Node.js uygulamalarınızda izleme (tracing) kurulumunu kolaylaştırır. Bu yazıda, Docker + OpenTelemetry Collector + Jaeger kullanarak Node.js tabanlı bir serviste uçtan uca izlemeyi adım adım kuracağız. Amaç, üretime yakın bir geliştirme deneyimi sağlamak, gecikmeleri ölçmek ve bağımlılıkları görünür kılmaktır.

Mimari ve Bileşenler

Kuracağımız basit topolojide üç temel bileşen bulunuyor: 1) Otomatik enstrümantasyonla iz verisi üreten Node.js servisi, 2) OTLP üzerinden iz kabul edip yöneten OpenTelemetry Collector, 3) Sorgulama ve görselleştirme için Jaeger. Collector, gelecekte Grafana Tempo, Honeycomb veya Zipkin gibi hedeflere geçişi kolaylaştıran bir ara katman görevi görür.

Node.js Projesini Hazırlama

Yeni bir proje başlatın ve gerekli bağımlılıkları kurun. Örnek bir Express API üzerinden gideceğiz, fakat otomatik enstrümantasyon HTTP, gRPC, MySQL, Redis gibi birçok paketi destekler.

# Projeyi başlat
npm init -y

# Express ve OpenTelemetry paketleri
npm i express
npm i @opentelemetry/sdk-node @opentelemetry/api @opentelemetry/resources \
@opentelemetry/semantic-conventions @opentelemetry/auto-instrumentations-node \
@opentelemetry/exporter-otlp-grpc

Ardından uygulama girişinde OpenTelemetry’yi başlatacak bir dosya oluşturun. Bu dosya, servis adı ve ortam gibi meta bilgileri de ekler.

// tracing.js
'use strict';
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-otlp-grpc');

const sdk = new NodeSDK({
  resource: new Resource({
    [SemanticResourceAttributes.SERVICE_NAME]: 'node-api',
    [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: process.env.NODE_ENV || 'dev',
  }),
  traceExporter: new OTLPTraceExporter({
    url: process.env.OTEL_EXPORTER_OTLP_ENDPOINT || 'http://otel-collector:4317'
  }),
  instrumentations: [getNodeAutoInstrumentations()],
});

sdk.start()
  .then(() => console.log('OpenTelemetry başlatıldı'))
  .catch((err) => console.error('OTel hatası:', err));

process.on('SIGTERM', () => {
  sdk.shutdown().finally(() => process.exit(0));
});

Basit bir Express sunucusu ekleyelim. tracing.js, uygulamadan önce yüklenmelidir ki tüm modüller doğru enstrümante edilsin.

// index.js
'use strict';
require('./tracing'); // OTel ön yükleme

const express = require('express');
const app = express();

app.get('/health', (req, res) => {
  res.json({ ok: true, ts: Date.now() });
});

app.get('/slow', async (req, res) => {
  await new Promise(r => setTimeout(r, 300)); // yapay gecikme
  res.send('yavaş yanıt');
});

app.listen(3000, () => console.log('API 3000 portunda'));

OpenTelemetry Collector ve Jaeger ile Docker Compose

Collector, uygulamadan gelen OTLP verilerini alıp Jaeger’a iletecek. Aşağıda temel bir docker-compose yapısı ve Collector konfigürasyonu bulunuyor.

# docker-compose.yml
version: '3.9'
services:
  api:
    build: .
    command: node index.js
    environment:
      NODE_ENV: dev
      OTEL_EXPORTER_OTLP_ENDPOINT: http://otel-collector:4317
      OTEL_TRACES_SAMPLER: parentbased_traceidratio
      OTEL_TRACES_SAMPLER_ARG: '0.5'
    ports:
      - "3000:3000"
    depends_on:
      - otel-collector

  otel-collector:
    image: otel/opentelemetry-collector-contrib:0.103.0
    command: ["--config=/etc/otelcol-config.yaml"]
    volumes:
      - ./otelcol-config.yaml:/etc/otelcol-config.yaml:ro
    ports:
      - "4317:4317"   # OTLP gRPC
      - "4318:4318"   # OTLP HTTP (opsiyonel)
    depends_on:
      - jaeger

  jaeger:
    image: jaegertracing/all-in-one:1.57
    ports:
      - "16686:16686" # Jaeger UI

Collector’ın konfigürasyon dosyası, OTLP alıcıyı etkinleştirir ve verileri Jaeger’a yollar. İleride Zipkin, Tempo veya başka hedeflere ek ihracatçılar tanımlayabilirsiniz.

# otelcol-config.yaml
receivers:
  otlp:
    protocols:
      grpc:
      http:

exporters:
  jaeger:
    endpoint: jaeger:14250
    tls:
      insecure: true

processors:
  batch:
    timeout: 1s
    send_batch_size: 512

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [batch]
      exporters: [jaeger]

Çalıştırma ve Doğrulama

Proje köküne basit bir Dockerfile ekleyin. Node tabanlı minimal bir imaj, üretime giden yolda iyi bir başlangıçtır.

# Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]

Artık ortamı ayağa kaldırabilirsiniz. Aşağıdaki komut, API, Collector ve Jaeger’ı birlikte çalıştırır.

docker compose up --build

Tarayıcıdan http://localhost:16686 adresine gidip Jaeger UI’ı açın. Service menüsünde “node-api” servis adını göreceksiniz. Ayrıntılı izler için bir iki istek atın:

curl http://localhost:3000/health
curl http://localhost:3000/slow

Jaeger üzerinden isteklerin gecikme dağılımını, span ağaçlarını, endpoint bazlı hataları ve bağımlılık grafini analiz ederek performans darboğazlarını hızla teşhis edebilirsiniz.

En İyi Uygulamalar ve İpuçları

Örnek konfigürasyonda örnekleme oranını yüzde 50 olarak ayarladık. Üretimde, trafik seviyesine göre oranı düşürmek ve belirli endpoint’lerde dinamik örnekleme uygulamak mantıklıdır. Ayrıca, Resource etiketlerine versiyon, bölge ve takım bilgisi eklemek arama ve filtrelemeyi kolaylaştırır. Kolektörde attributes veya transform işlemcileri ile PII verileri kırpma/anonimleştirme adımları ekleyebilirsiniz. Gecikmeleri daha iyi yorumlamak için kritik yerlerde manuel span eklemek (ör. yoğun CPU işlemi, harici API çağrıları) fayda sağlar.

Güvenlik açısından Collector ile uygulama arasındaki trafiği mTLS ile şifrelemek ve dış ağlara ihracatta TLS’i etkinleştirmek önemlidir. Gözlemlenebilirlik verisi de kritiktir; erişim kontrolü, saklama süresi ve maliyet optimizasyonu (ör. örnekleme, toplu gönderim ayarları) planlanmalıdır. CI/CD’de, tracer başlatma hatalarını görünür kılmak için sağlık kontrolleri ve basit duman testleri ekleyin.

Sonuç

OpenTelemetry, Node.js servisleriniz için satıcı bağımsız, geleceğe dönük bir izleme altyapısı kurmanızı sağlar. Docker ile izleme yığınını dakikalar içinde ayağa kaldırabilir, Collector aracılığıyla hedef sistemleri esnekçe değiştirebilir, Jaeger ile sorunları hızla teşhis edebilirsiniz. Bugünkü kurulum, üretime geçişte ihtiyaç duyacağınız dinamik örnekleme, ek işlemciler, metrik ve log toplama gibi yeteneklerin de temelini oluşturur. İlk adımı attınız; şimdi span’ları zenginleştirip gerçek kullanıcı senaryolarını görünür kılma zamanı.

5 Eylül 2025 Cuma

Ollama ile Yerelde LLM Çalıştırma Rehberi: Kurulum, GPU Hızlandırma ve İpuçları

Giriş: Neden Yerelde LLM Çalıştırmalı?

Bulut maliyetlerinin arttığı, veri gizliliğinin ise daha kritik hale geldiği bir dönemde, büyük dil modellerini (LLM) yerel makinenizde çalıştırmak hem hızlı deney imkânı hem de verilerinizi cihazınızdan dışarı çıkarmadan çalışma rahatlığı sağlar. Ollama, GGUF formatındaki modern modelleri tek komutla indirip kullanmanıza olanak veren hafif ve kullanımı kolay bir araçtır. Bu rehberde Windows, macOS ve Linux üzerinde Ollama kurulumunu, GPU hızlandırmasını, performans ayarlarını ve uygulamanıza entegre etmenin pratik yollarını anlatıyorum.

Ön Koşullar ve Donanım Gereksinimleri

LLM’leri yerelde çalıştırırken CPU, RAM ve özellikle GPU VRAM kapasitesi önemlidir. 7B parametreli, 4-bit sıkıştırılmış (quantized) bir model için genellikle 6–8 GB VRAM ve en az 8–16 GB sistem RAM tavsiye edilir. 13B için 12 GB ve üzeri VRAM ideal; 70B gibi devasa modeller ise çoğunlukla masaüstü sınıfını aşar. Yine de Ollama, VRAM yetersizse katmanların bir kısmını CPU’ya taşıyabilir; bu durumda yanıt süresi uzar.

Kurulum: Windows, macOS ve Linux

- Windows: En kolay yol resmi yükleyici veya winget ile kurulumdur. Komut satırına winget install Ollama.Ollama yazın. Kurulum bittiğinde ollama komutuna erişebiliyor olmalısınız.

- macOS: Homebrew kullanıyorsanız brew install ollama yeterlidir. Apple Silicon (M1/M2/M3) üzerinde Metal hızlandırma ile iyi performans alırsınız.

- Linux: Resmi sitedeki script ile kurabilirsiniz: curl -fsSL https://ollama.com/install.sh | sh. Ardından servis otomatik başlatılır ve http://localhost:11434’te API hazır olur.

Model İndirme ve İlk Çalıştırma

Ollama, modelleri depodan çekmek için pull, etkileşimli çalıştırmak için run komutlarını kullanır. Örneğin 8B boyutlu bir Llama 3 varyantını denemek için: ollama pull llama3:8b ve ardından ollama run llama3:8b. İlk indirme birkaç dakika sürebilir. Türkçe için Llama 3 ailesi, Mistral veya Gemma tabanlı GGUF modelleri de tercih edilebilir. Komut satırında sistem yönergeleri (system prompt) verebilir, çıktıyı kısaltmak için Ctrl+C ile durdurabilirsiniz.

GPU Hızlandırma ve İnce Ayar

Uygun sürücüler yüklüyse Ollama GPU’yu otomatik kullanır: Windows/NVIDIA için CUDA, macOS için Metal, Linux/AMD için ROCm desteğiyle çalışır. Performans düşükse modelin kuantizasyon varyantını değiştirin. Örneğin Q4_K_M daha az VRAM kullanır, Q6_K veya Q8_0 kaliteyi artırır ama daha fazla bellek ister. Bazı durumlarda GPU kullanımını sınırlamak için model seçeneklerinde gpu_layers değerini düşürmek yararlı olabilir.

Akıcı diyaloglar için bağlam penceresini artırabilirsiniz. Örnek seçenekler: num_ctx (bağlam uzunluğu), temperature, top_p ve repeat_penalty. Uzun dökümanlarla çalışırken num_ctx’i yükseltmek gerekir; ancak bu bellek kullanımını artırır. Sık tekrarlanan ifadeleri azaltmak için repeat_penalty değerini 1.1–1.2 aralığında deneyebilirsiniz.

API ile Entegrasyon: cURL ve Python

Ollama, varsayılan olarak http://localhost:11434 adresinde REST API sunar. Basit bir metin üretimi için cURL ile örnek istek:

curl -X POST http://localhost:11434/api/generate -d '{ "model": "llama3:8b", "prompt": "Türkçe olarak üç maddede kuantizasyonu açıkla.", "options": { "num_ctx": 4096, "temperature": 0.7 } }'

Python tarafında requests ile akışlı (stream) yanıtlar alabilirsiniz. İstek gövdesine stream: true eklerseniz kelime kelime akan sonuçları terminale yazdırabilirsiniz. Bu sayede sohbet uygulaması kurmak veya web arayüzünde canlı çıktı göstermek kolaylaşır.

Performans İpuçları ve Model Seçimi

- Doğru boyut: 7B–8B modeller, dizüstüler için tatlı noktadır. 13B daha kaliteli yanıtlar verse de masaüstü GPU’ları gerektirebilir.

- Kuantizasyon: Q4 aileleri hızlı ve hafif; Q5–Q8 kaliteyi artırır. Uygulama senaryonuza göre dengeyi bulun.

- Önbellek: Model, bağlam önbelleğini (KV cache) kullanır. Aynı yönergelerle tekrar çalışırken hızlanma görürsünüz. Uzun oturumlarda bağlam yönetimi (önemli kısımları sabitleme) fayda sağlar.

- Türkçe doğruluğu: Modelden Türkçe üretim istemek için yönergenizi açık yazın (örn. “Lütfen Türkçe yanıtla”). Gerekirse sistem mesajına yazım kurallarına uyma ve kısa/uzun yanıt tercihlerinizi ekleyin.

Gizlilik, Ağ Erişimi ve Güvenlik

Varsayılan yapılandırmada API sadece yerel cihaza (localhost) açıktır. Uzaktan erişime açmak istiyorsanız güçlü bir parola/kapsayıcı ağ politikası, ters proxy ve gerekiyorsa VPN kullanın. Yerelde çalıştığınız için metinleriniz buluta gitmez; yine de günlükleri ve uygulama kayıtlarını şirket politikalarına uygun konumlarda saklayın.

Sorun Giderme

- Model yüklenmiyor: Disk alanını ve indirme bütünlüğünü kontrol edin. Gerekirse ollama rm ile modeli silip tekrar indirin.

- VRAM hataları: Daha düşük bir kuantizasyon seçin (Q4), gpu_layers’ı azaltın veya bağlam penceresini küçültün. Ollama çoğu durumda otomatik olarak CPU’ya düşer, ancak bu performansı etkiler.

- Windows’ta sürücü: NVIDIA sürücülerinin güncel olduğundan emin olun. Performans sorunları genellikle eksik ya da eski sürücülerden kaynaklanır.

- Çakışan port: 11434 portunu kullanan başka bir servis varsa kapatın veya Ollama’yı farklı bir portta başlatın.

Sonuç

Ollama, yerelde LLM çalıştırmayı birkaç komuta indirgeyerek hızlı prototipleme ve gizlilik odaklı üretim senaryolarını mümkün kılıyor. Doğru model boyutu ve kuantizasyon seçimiyle dizüstü bilgisayarda dahi tatmin edici Türkçe sonuçlar alabilirsiniz. GPU hızlandırması, bağlam ayarları ve API entegrasyonu ile dakikalar içinde chatbot, özetleyici veya kod asistanı geliştirmek elinizde. Küçük adımlarla başlayın, ölçümleyin ve kullanım amacınıza en uygun yapılandırmayı kademeli olarak bulun.

Passkeys (WebAuthn) ile Şifresiz Giriş: Adım Adım Uygulama Rehberi

Şifrelerle boğuşmanın sonuna gelmek üzereyiz. Passkeys, yani FIDO2/WebAuthn tabanlı şifresiz kimlik doğrulama, hem kullanıcı deneyimini iyileştiriyor hem de oltalama saldırılarına karşı çok daha güçlü bir koruma sağlıyor. Bu rehberde, modern web uygulamalarına passkey desteğini nasıl ekleyebileceğinizi, mimari gereksinimleri ve en iyi uygulamaları sade bir dille anlatıyorum.

Neden Passkeys? Klasik parolalar tahmin edilebilir, tekrar kullanılır ve sızıntılarda kolayca ele geçirilir. Passkeys ise cihaz tabanlı, kök anahtarları donanımda korunan (Secure Enclave/TPM) bir anahtar çifti yaklaşımı kullanır. Özel anahtar cihazda kalır, sunucu yalnızca herkese açık anahtarı saklar. Giriş sırasında sunucu tarafından verilen bir “challenge” imzalanır; bu sayede oltalama siteleri doğru kök bağlamı oluşturamadığı için doğrulama başarısız olur.

Passkey Nedir? Kısa Teknik Özet

Passkeys, WebAuthn API’si ve FIDO2 standartlarının bir birleşimidir. Tarayıcı (veya mobil OS), “platform authenticator” (cihaz üzerindeki biyometri/PIN) ya da “cross-platform authenticator” (USB/NFC güvenlik anahtarı) kullanarak kullanıcıyı doğrular. Uyumlu tarayıcılar: Chrome, Safari, Edge, Firefox (bazı platform kısıtları olabilir). Uyumlu işletim sistemleri: iOS/iPadOS 16+, macOS Ventura+, Android 9+, Windows 10/11 (Güncel) vb.

Mimari ve Gereksinimler

- Zorunlu HTTPS: WebAuthn yalnızca güvenli kökenlerde çalışır. Geliştirme için localhost istisnası vardır.
- Relying Party ID (rpId): Genellikle alan adınız. rpId, kök alanla eşleşmeli ve alt alanlar için doğru yapılandırılmalı.
- Sunucu tarafı saklama: Kullanıcı başına credentialId, publicKey, signCount (veya counter), userHandle gibi alanlar güvenli biçimde saklanmalı.
- Oturum yönetimi: Başarılı doğrulama sonrası session veya JWT üretin. Session sabitleme ve CSRF’ye dikkat edin.

Kayıt (Registration) Akışı

1) Sunucu challenge üretir: Kullanıcı kayıt sayfasında “Passkey oluştur” dediğinde sunucu tek kullanımlık bir challenge (rastgele bayt dizisi) üretir ve front-end’e gönderir. Yanıtınız; rp (name, id), user (id, name, displayName), pubKeyCredParams (örn. -7 ES256), authenticatorSelection (residentKey=required, userVerification=required) gibi parametreleri içermeli.

2) İstemci credential oluşturur: Tarayıcı, navigator.credentials.create({ publicKey: ... }) çağrısıyla cihazın biyometrisi/PIN’i üzerinden kullanıcıyı doğrular ve bir credential üretir. Kullanıcı rızası alınır ve işlem OS düzeyinde güvenlidir.

3) Sunucu doğrular ve kaydeder: İstemciden dönen attestation ve clientDataJSON, sunucuda doğrulanır. Güvenilir bir kütüphane ile (Node.js: @simplewebauthn/server; Java: WebAuthn4J; Python: webauthn) kontrol edebilirsiniz. Başarılıysa credentialId, publicKey ve signCount veritabanına yazılır. Attestation politikasını “none” tutarak gizliliği artırabilir veya kurumsal senaryolarda belirli üreticileri zorunlu kılabilirsiniz.

Giriş (Authentication) Akışı

1) Sunucu challenge üretir: Giriş düğmesine basıldığında sunucu yeni bir challenge üretir ve istemciye gönderir. allowCredentials ile kayıtlı credentialId’leri listeleyebilir veya “discoverable credentials” kullanıyorsanız listeyi boş bırakabilirsiniz.

2) İstemci imza oluşturur: navigator.credentials.get({ publicKey: ... }) çağrısı yapılır. Kullanıcı biyometri/PIN ile onay verir ve cihaz challenge’ı imzalar.

3) Sunucu imzayı doğrular: clientDataJSON ve authenticatorData içindeki rpIdHash, origin, flags (UP, UV), signCount ve signature doğrulanır. counter artışı kontrol edilerek tekrar oynatma (replay) engellenir. Başarılıysa oturum başlatılır.

Senkrone ve Cihaza Bağlı Passkeys

- Senkrone Passkeys: Apple, Google ve Microsoft ekosistemlerinde aynı hesabın bağlı cihazları arasında uçtan uca şifreli senkronizasyon yapılır. Kullanıcı için harika UX, ancak kurumsal ortamlarda veri politikaları gözden geçirilmeli.
- Cihaza Bağlı (Device-bound): Anahtar yalnızca oluşturulduğu cihazda bulunur. Daha sıkı güvenlik isteyen sektörlerde tercih edilir. Gerekirse ikisi bir arada desteklenebilir.

UX İpuçları ve Koşullu UI

- Koşullu UI: Chrome ve Safari, giriş formu odaklandığında otomatik passkey önerisi sunabilir. Bu, “parola yerine passkey” mesajını doğal şekilde yerleştirir.
- Adım adım benimsetme: İlk girişte kullanıcıya “Şifresiz giriş ekle (önerilir)” çağrısı yapın. Zorunlu kılmayın, alternatif bırakın.
- Geri dönüş planı: Kullanıcı cihazını kaybedebilir. E-posta/OTP veya destek kanalını yalnızca hesap kurtarma için sunun; normal girişte passkey’i önceliklendirin.
- Platform/cross-platform seçimi: Dizüstü kullanıcıları için platform authenticator yeterli olabilir; saha ekipleri için güvenlik anahtarları (USB/NFC) mantıklı.

Güvenlik ve Uyum

- Phishing direnci: rpId ve origin eşlemesi, yanlış etki alanıyla giriş yapılmasını engeller.
- Gizlilik: Attestation’ı çoğunlukla “none” tutarak cihaz damgalanmasını önleyin.
- Sertleştime: HSTS, COOP/COEP, güçlü TLS ayarları, zaman senkronizasyonu. Sunucu saat sapması doğrulamayı bozabilir.
- Uyumluluk: En güncel tarayıcı/OS sürümlerini hedefleyin. Eski cihazlar için parola + 2FA yedek planı bulundurun.

Uygulama İskeleti: Hızlı Kontrol Listesi

- Alan adınızı ve rpId’nizi netleştirin, HTTPS zorunludur.
- Veritabanında kullanıcı tablo şemasına credentialId (base64url), publicKey (COSE), signCount, createdAt, lastUsed alanlarını ekleyin.
- Kayıt ve giriş için ayrı endpoint’ler tanımlayın; her ikisi de nonce/challenge üretmeli ve kısa süreli saklamalı.
- Kütüphane seçin: Node.js için @simplewebauthn, Java için WebAuthn4J, Python için webauthn gibi olgun çözümler kullanın.
- Test: Chrome DevTools “Virtual Authenticator” ile farklı senaryoları (resident key, UV required) test edin.
- Telemetri: Başarı/başarısızlık oranlarını, tarayıcı/OS kırılımını izleyin; eğitim içerikleriyle dönüşümü artırın.

Sık Karşılaşılan Hatalar

- origin/rpId uyuşmazlığı: www ve çıplak alanı karıştırmayın; üretimde tek bir kök alan belirleyin.
- HTTP yerine HTTPS: Geliştirme dışında çalışmaz; sertifikayı doğru kurun.
- Yanlış COSE algoritması: Sunucu ve istemci aynı algoritmaları kabul etmeli (ör. ES256).
- Counter tutarsızlığı: signCount geriye düşerse cihaza güveni düşürün ve yeniden kayıt isteyin.

Özetle, passkeys hem güvenlik hem de kullanıcı deneyimi açısından önümüzdeki yılların standardı olacak. Doğru mimariyle kurguladığınızda, kullanıcılarınızın parolaları hatırlamasını istemez, oltalama riskini azaltır ve destek taleplerini düşürürsünüz. Küçük bir PoC ile başlayın, slayt yerine gerçek kullanıcı akışı tasarlayın ve dönüşüm metriklerini yakından takip edin. Bir kez oturduğunda, “Şifremi unuttum” döneminin kapandığını hissedeceksiniz.