Spitfire
KurulumDocker · Kubernetes · Windows · runner

Kurulum rehberi

Kurulum tek komuttur. Komut, sürümün kurulum paketini spitfire.tr'den indirip SHA-256'sını doğrular ve ~/spitfire klasörüne açar; imajı Docker Hub'dan çeker. Aynı komut güncellemeyi de yapar, ayarlarınız korunur.

Gereksinimler

  • Linux ya da macOS; Docker ve Docker Compose v2.
  • Windows 10/11 ya da Windows Server: Docker Desktop (Linux konteynerleri) ve PowerShell. Docker'sız bir Windows sunucuya runner, Windows hizmeti olarak kurulur.
  • Kubernetes için ayrıca kubectl ve bir cluster erişimi.
  • Makinenin Docker Hub'a ve spitfire.tr'ye erişimi. Go, Node ya da kaynak kod gerekmez.

Tek makine (Docker)

Postgres, controller, web arayüzü ve 2 runner ayağa kalkar.

curl -fsSL https://spitfire.tr/install.sh | bash -s -- docker

Seçenekler: --port 8470, --runners 4, --location istanbul; hepsi için ~/spitfire/install.sh --help.

Kubernetes

Aktif kubectl context'ine, spitfire namespace'ine kurar; node'lar imajı Docker Hub'dan çeker.

curl -fsSL https://spitfire.tr/install.sh | bash -s -- kubernetes
curl -fsSL https://spitfire.tr/install.sh | bash -s -- kubernetes --context prod --namespace loadtest --runners 3

Pod'lar root olmadan, salt okunur kök dosya sistemiyle, yetkisiz ve RuntimeDefault seccomp ile çalışır. NetworkPolicy'ler Postgres'e yalnız controller'ın, düz metin runner portuna (8475) yalnız bu kurulumun runner'larının erişmesine izin verir (CNI destekliyorsa) 0.5.5+.

Windows (Docker Desktop)

PowerShell'de tek komut; kurulum paketini doğrulayıp %USERPROFILE%\spitfire klasörüne açar ve Docker Desktop'ta Postgres, controller ve 2 runner başlatır. Yönetici yetkisi gerekmez; betik yalnız o işlem için çalıştırma izni alır.

irm https://spitfire.tr/install.ps1 | iex

Seçeneklerle (port, runner sayısı, lokasyon):

& ([scriptblock]::Create((irm https://spitfire.tr/install.ps1))) docker -Port 8470 -Runners 4 -Location istanbul

Docker'sız bir Windows sunucuya runner: arayüzde Runners → Kayıt anahtarı → Windows sekmesindeki komutu Yönetici PowerShell'de çalıştırın. Runner, Windows ile başlayan ve çökerse yeniden başlatılan spitfire-runner-1 hizmeti olur; ayarları yalnız SYSTEM ve Administrators'ın okuyabildiği %ProgramData%\Spitfire altında durur.

Kurulum kodu: Select-String SPITFIRE_SETUP_CODE $env:USERPROFILE\spitfire\deploy\docker\.env. Kaldırma: powershell -ExecutionPolicy Bypass -File $env:USERPROFILE\spitfire\uninstall.ps1 docker. Windows kurulumu 0.5.3 sürümüyle gelir.

İlk giriş ve kurulum kodu

Kurulum sonunda adres ve tek kullanımlık kurulum kodu basılır. Adresi açın ve bu kodla ilk yönetici hesabını oluşturun.

Kodu kaybettiyseniz yenisi gerekmez; ilk yönetici oluşana kadar saklanır:

grep SPITFIRE_SETUP_CODE ~/spitfire/deploy/docker/.env
kubectl -n spitfire get secret spitfire-secrets -o jsonpath='{.data.SPITFIRE_SETUP_CODE}' | base64 -d

Oturum anahtarı tarayıcıda, betiklerin okuyamadığı bir çerezde (HttpOnly) tutulur; sayfa yenilense de oturum sürer, oturum düşerse arayüz giriş ekranına döner 0.5.6+.

Giriş denemesi sınırı 0.5.4+

Parola tahminine karşı giriş, kurulum kodu ve SSO dönüşü sınırlıdır: bir istemci adresi art arda 30 deneme yapabilir, sonra 2 sn'de bir; bir hesap 10 yanlış parolayı kabul eder, sonra dakikada bir (farklı adreslerden gelse de; doğru parola sayılmaz). Sınır aşılınca ekran ne kadar beklemek gerektiğini söyler, API Retry-After ile 429 döner.

Çok kullanıcı tek bir proxy ya da NAT arkasından geliyorsa adres sınırını yükseltin: deploy/docker/.env (ya da spitfire-secrets) içine SPITFIRE_SIGNIN_BURST=200. İstemci adresi X-Forwarded-For'dan yalnız istek loopback'ten ya da özel ağdan (önde bir ingress/ters vekil) geldiğinde alınır; genel adresli bir vekil (bulut yük dengeleyici, Cloudflare) SPITFIRE_TRUSTED_PROXIES ile tanıtılır 0.5.5+.

Başka lokasyondan runner

Uzak runner'lar controller'a dışarı doğru, anahtar sabitlemeli TLS ile bağlanır; yük sunucusunda gelen port açmanız gerekmez. Arayüzde Runners → Kayıt anahtarı penceresi komutu token ve pin'le hazırlar:

curl -fsSL https://spitfire.tr/install.sh | bash -s -- runner --controller spitfire.example.com:8471 --token sfrun_… --ca-pin sha256:… --runners 2

Docker olmayan sunucular için aynı pencerede systemd ile tek dosyalık kurulum komutu da vardır.

Docker'sız kurulan runner'lar (systemd ya da Windows servisi) sonraki sürümlerde kendini günceller: Runners sayfasında eski sürümdeki runner'ın yanındaki Güncelle'ye basın. Runner yeni sürümü controller'dan gRPC portu üzerinden indirir, Spitfire'ın imzasını kendisi doğrular (imzasız ya da daha eski bir sürümü kabul etmez) ve yeniden başlar; koşudaki runner güncellenmez. Docker ve Kubernetes'teki runner'lar imajlarıyla, kurulum komutuyla güncellenir. Daha önce kurulmuş runner'larda bu özellik bir kez kurulum komutunu yeniden çalıştırınca açılır 0.5.9+.

CI/CD 0.5.3+

Kayıtlı bir test pipeline'dan controller'da, kendi runner'larınızla koşar; adım sonucu bekler ve eşiklere göre geçer ya da kalır. Kimlik: arayüzde profil menüsü → API token'ları'ndan oluşturulan kişisel token, pipeline'ın gizli değişkeni SPITFIRE_TOKEN olarak. Token yalnız okur, koşu başlatır ve durdurur. Test sayfasındaki CI düğmesi aşağıdaki adımları o testin adıyla hazırlar.

GitHub Actions

# .github/workflows/load-test.yml içinde bir adım / a step
- name: Load test
  env:
    SPITFIRE_URL: https://spitfire.example.com
    SPITFIRE_TOKEN: ${{ secrets.SPITFIRE_TOKEN }}
  run: |
    curl -fsSL "$SPITFIRE_URL/api/v1/runner-dist/spitfire-cli-linux-amd64.gz" | gunzip > spitfire && chmod +x spitfire
    ./spitfire cloud run "Checkout" --report report.pdf

GitLab CI

load-test:
  image: basistekbt/spitfire:latest
  variables:
    SPITFIRE_URL: https://spitfire.example.com   # SPITFIRE_TOKEN: CI/CD → Variables (masked)
  script:
    - spitfire cloud run "Checkout" -l istanbul=60 -l frankfurt=40 -o summary.json

Windows (PowerShell)

$env:SPITFIRE_URL = 'https://spitfire.example.com'   # $env:SPITFIRE_TOKEN: pipeline secret
Invoke-WebRequest "$env:SPITFIRE_URL/api/v1/runner-dist/spitfire-cli-windows-amd64.exe" -OutFile spitfire.exe -UseBasicParsing
.\spitfire.exe cloud run 'Checkout'
exit $LASTEXITCODE

Çıkış kodları: 0 geçti, 99 eşik kırıldı, 97 eşik koşuyu durdurdu, 2 test veri değiştiriyor ve --confirm-writes verilmedi, 1 diğer hatalar. Seçenekler: --runners N, -l istanbul=60:2 (lokasyon payı), --label zone=a, --timeout 20m, -o summary.json, --report rapor.pdf, --report-lang en.

Entegrasyonlar 0.5.3+

Arayüzde Entegrasyonlar (yönetici): koşuların başlangıç ve bitişini webhook ile bildirin, canlı metrikleri OpenTelemetry ya da Prometheus ile izleme sisteminize verin. Önce aynı sayfada Spitfire'ın herkese açık adresini girin; bildirimlerdeki koşu bağlantıları onunla kurulur.

Webhook

Seçilen olaylarda (run.started, run.finished, schedule.failed) adrese POST ile JSON gider. Başlıklar: X-Spitfire-Event, X-Spitfire-Delivery, X-Spitfire-Schema; gizli anahtar tanımlıysa X-Spitfire-Signature: sha256=<hex> (gövdenin HMAC-SHA256'sı). Ek başlık (ör. alıcının token'ı) eklenebilir. 2xx başarıdır; ağ hatası, 408, 429 ve 5xx 2 sn, 15 sn ve 1 dk sonra yeniden denenir, diğer 4xx denenmez. Her deneme Gönderimler geçmişinde görünür. targets, testin yük bindirdiği sunuculardır; summary yalnız run.finished'da gelir. Şema sürümü içinde alanlar yalnız eklenir.

{
  "schema": "spitfire.run-event/v1",
  "event": "run.finished",
  "deliveryId": "6f1c…",
  "sentAt": "2026-09-29T12:00:58Z",
  "controller": { "url": "https://spitfire.example.com", "version": "0.5.10" },
  "run": {
    "id": "3b9e…", "url": "https://spitfire.example.com/runs/3b9e…",
    "testId": "a1f0…", "testName": "Checkout", "testVersion": 7,
    "status": "finished", "result": "thresholds_failed",
    "startedAt": "2026-09-29T11:55:00Z", "endedAt": "2026-09-29T12:00:57Z",
    "plannedSeconds": 360, "plannedEndAt": "2026-09-29T12:01:00Z",
    "maxVUs": 200, "runners": 2, "locations": ["istanbul=60%", "frankfurt=40%"],
    "requestedBy": "Ayşe", "note": "GitHub Actions · shop@1a2b3c4d", "tags": ["ci"],
    "modifiesData": false
  },
  "targets": [
    { "protocol": "http", "host": "shop.example.com", "url": "https://shop.example.com", "steps": 3 },
    { "protocol": "postgres", "host": "db.internal", "port": "5432", "connection": "orders", "steps": 1 }
  ],
  "summary": {
    "requests": 182340, "failed": 12, "rps": 506.5, "errorRate": 0.00007,
    "p50Ms": 38, "p95Ms": 612, "p99Ms": 980, "peakVUs": 200, "checksPassRate": 0.999,
    "thresholds": [{ "metric": "req_duration", "expr": "p(95)<500", "observed": 612, "passed": false }]
  }
}

Controller bir koşu sürerken yeniden başlarsa koşu interrupted olarak kapanır ve açılışta onun run.finished'ı da gönderilir (result: error, abortReason: controller restarted); alıcıdaki koşu açık kalmaz (0.5.4+).

İmzayı doğrulama

import hashlib, hmac

def verified(body: bytes, header: str, secret: str) -> bool:
    # header: the X-Spitfire-Signature value, "sha256=<hex>"
    want = "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(want, header or "")
import { createHmac, timingSafeEqual } from 'node:crypto'

export function verified(body, header, secret) {   // body: the raw request bytes
  const want = Buffer.from('sha256=' + createHmac('sha256', secret).update(body).digest('hex'))
  const got = Buffer.from(header ?? '')
  return got.length === want.length && timingSafeEqual(got, want)
}

Prometheus

/metrics: runner'lar (spitfire_runners), etkin koşular ve her canlı koşunun spitfire_run_vus, spitfire_run_requests_per_second, spitfire_run_error_ratio, spitfire_run_latency_ms{quantile}, spitfire_run_requests_total, spitfire_step_requests_total değerleri. Kimlik: kişisel API token'ı.

Controller'ın kendi sağlığı da aynı uçta 0.5.5+: spitfire_internal_runner_messages_dropped_total, spitfire_internal_db_writes_dropped_total / _failed_total (sıfırdan büyükse sonuçlarda boşluk vardır), spitfire_internal_deliveries_total{result}, spitfire_internal_deliveries_pending (bekleyen webhook), spitfire_internal_http_responses_total{code}, ayrıca Go çalışma zamanı değerleri. Log toplayıcılar için SPITFIRE_LOG_FORMAT=json (runner: SPITFIRE_RUNNER_LOG_FORMAT).

scrape_configs:
  - job_name: spitfire
    scheme: https
    metrics_path: /metrics
    authorization:
      credentials: sfpat_…        # a personal API token
    static_configs:
      - targets: ['spitfire.example.com']

OpenTelemetry (OTLP)

Koşu sürerken metrikler OTLP/HTTP (JSON) ile toplayıcıya gönderilir: uç nokta temel adrestir, sonuna /v1/metrics eklenir (ör. https://otel-collector:4318); kimlik başlıkları (Authorization, Api-Token…) şifreli saklanır. Metrikler: spitfire.vus, spitfire.request.rate, spitfire.request.error_rate, spitfire.request.duration.p50/p95/p99, spitfire.requests, spitfire.step.requests; etiketler spitfire.run.id, spitfire.test.name ve hedef sunucu için server.address.

Raporlar 0.5.3+

Koşu sayfasında Rapor: HTML (yeni sekmede), PDF, CSV (adım ve lokasyon özeti ya da saniye saniye). Paylaşım bağlantısı raporu hesabı olmayan birine 1–90 gün gösterir; istenince iptal edilir, her görüntüleme denetim kaydına yazılır. Raporu bir betikten almak için:

curl -fsS -H "Authorization: Bearer $SPITFIRE_TOKEN" "https://spitfire.example.com/api/v1/runs/<run-id>/report?format=pdf&lang=tr" -o rapor.pdf
curl -fsS -H "Authorization: Bearer $SPITFIRE_TOKEN" "https://spitfire.example.com/api/v1/runs/<run-id>/export?kind=timeseries" -o saniyeler.csv

Zamanlanmış koşular ve bildirimler 0.5.3+

Test sayfasında Zamanla: saatlik, her gece, hafta içi, haftalık ya da 5 alanlı bir cron ifadesi, seçtiğiniz saat diliminde. Zamanlama onu oluşturan kullanıcı adına, o kullanıcının güncel yetkileriyle koşar. En sık 5 dakikada bir; önceki koşu sürerken yenisi atlanır; controller kapalıyken 10 dakikadan fazla geciken koşu sonradan telafi edilmez, kaçırıldı olarak işaretlenir. Hepsi Test → Zamanlanmış koşular'da; "Şimdi koştur" ile hemen denenebilir.

Bildirim kanalları

Entegrasyonlar → Bildirim kanalları → Kanal ekle, kanal türünü seçin:

  • Slack: Slack'te Incoming Webhook oluşturup adresini yapıştırın. Renkli mesaj: sonuç, istek sayısı, p95, hata oranı, kırılan eşikler, koşu bağlantısı.
  • Microsoft Teams: kanalda Workflows → "Post to a channel when a webhook request is received" akışını oluşturup adresini yapıştırın. Aynı bilgiler bir adaptive card'da, "Koşuyu aç" düğmesiyle.
  • E-posta: aynı sayfadaki E-posta (SMTP) kartına sunucunuzu girin (STARTTLS, TLS ya da güvenilir ağda şifresiz; parola şifreli saklanır) ve deneme e-postası gönderin. Biten koşunun PDF raporu ekte gelir.

Her kanalda olaylar seçilir (run.started, run.finished, schedule.failed); Yalnız sorunlarda bildir açıksa başarılı koşular ve başlangıçlar gönderilmez, eşik kırılan, hata veren ya da durdurulan koşular ve başlamayan zamanlanmış koşular gönderilir. Kanal belirli testlerle sınırlanabilir. Mesaj dili (Türkçe/İngilizce) Entegrasyonlar → Genel'dedir. schedule.failed JSON webhook'larına da gider; run.testId ve schedule alanlarıyla.

Tek oturum açma (OIDC, LDAP) 0.5.3+

Arayüzde Tek oturum açma (yönetici). Önce Entegrasyonlar sayfasında Spitfire'ın herkese açık adresini girin; yönlendirme adresi ondan kurulur.

OpenID Connect

Kimlik sağlayıcıda web uygulaması (yetkilendirme kodu) oluşturun ve yönlendirme adresini ekleyin:

https://spitfire.example.com/api/v1/auth/oidc/callback
  • Entra ID: issuer https://login.microsoftonline.com/<tenant-id>/v2.0; gruplar için uygulamanın token yapılandırmasında "groups" claim'ini açın (grup nesne kimlikleri gelir).
  • Okta: issuer https://<alan>.okta.com (ya da yetkilendirme sunucusu); gruplar için bir "groups" claim'i tanımlayın.
  • Keycloak: issuer https://<sunucu>/realms/<realm>; istemciye "Group Membership" eşleyicisi ekleyin (claim adı groups, tam yol kapalı).
  • Google: issuer https://accounts.google.com; Google grup göndermez, izin verilen alan adıyla sınırlayın.

Spitfire PKCE ve nonce kullanır, ID token imzasını sağlayıcının anahtarlarıyla doğrular; doğrulanmamış e-posta adresleri reddedilir. "Keşfi dene" ayarları kaydetmeden sağlayıcıyı bulur.

LDAP / Active Directory

Sunucu (ldaps://dc1.corp.local:636 ya da StartTLS ile ldap://), okuma yetkili bir hizmet hesabı ve kullanıcı arama kökü yeter. Varsayılan filtre uid, sAMAccountName ve mail ile eşleşir; kullanıcı normal giriş formuna dizin kullanıcı adını ya da e-postasını yazar. Parola yalnız dizine iletilir, Spitfire'da saklanmaz. Gruplar memberOf'tan okunur; olmayan dizinlerde grup arama kökü verin. "Dene" bir kullanıcıyla bağlanıp Spitfire'ın ne yapacağını (izin, rol) kaydetmeden gösterir.

Hesaplar, roller, gruplar

Hesaplar ilk girişte açılabilir (lisansın kullanıcı sınırı geçerlidir) ya da yönetici Kullanıcılar sayfasında giriş yöntemi OIDC/LDAP olan hesabı önceden açar. Yönetici grupları her girişte rolü belirler; üyelik eşitleme kullanıcıyı sağlayıcıdaki gruplarıyla aynı adı taşıyan Spitfire gruplarına ekler ve gruptan çıkınca çıkarır (elle eklenen üyeliklere dokunmaz). Aynı e-postalı parolalı hesap SSO kimliğine kendiliğinden bağlanmaz; yönetici hesabın giriş yöntemini değiştirir. Parolayla giriş: yalnız yöneticiler seçilince diğer herkes SSO ile girer, yönetici parolası acil durum girişi olarak kalır.

Güncelleme

Kurduğunuz komutu tekrar çalıştırın (Windows'ta irm … | iex). Yeni sürüm aynı klasöre açılır; anahtarlar (deploy/*/.env ya da spitfire-secrets) ve veriler korunur.

curl -fsSL https://spitfire.tr/install.sh | bash -s -- docker

Sürüm değişiyorsa kurulum önce veritabanını ~/spitfire/backups/*.dump olarak yedekler (son 5; pg_restore ile geri yüklenir). Yedek alınamazsa güncelleme yapılmaz; atlamak için --no-backup (Windows: -NoBackup) 0.5.5+.

Yeni sürüm çıktığında controller bunu günde bir kez spitfire.tr'den öğrenir; yöneticiler arayüzün üstünde sürüm notlarını ve bu kuruluma uygun komutu (klasör ya da namespace dahil) görür. Dışarıya yalnız sürüm numarası gider; internetsiz kurulumda SPITFIRE_UPDATE_CHECK=off. Tüm sürümler: sürüm notları 0.5.7+.

Güncelleme kötü giderse ~/spitfire/install.sh docker --rollback (Kubernetes: kubernetes --rollback; Windows: -Rollback) önce şimdiki veritabanını yedekler, sonra en yeni yedeği geri yükleyip o yedeği alan sürümle açar. O yedekten sonra yapılan değişiklikler geri gelmez; komutu yeniden çalıştırmak geri dönüşü geri alır 0.5.10+.

Kurulu sürüm, son kontrolün sonucu ve bu kuruluma uygun komut her zaman Lisans sayfasındaki Sürüm ve güncellemeler kartındadır; Şimdi kontrol et günlük kontrolü beklemez. Sürüm listesi imzalıdır: imzası tutmayan liste gösterilmez 0.5.8+.

Kurumsal proxy arkasında kurulum komutunu proxy tanımlıyken çalıştırın; HTTPS_PROXY, HTTP_PROXY ve NO_PROXY controller'a aktarılır (güncelleme kontrolü, webhook'lar, SSO). İç ağdaki SSO ya da webhook adreslerini NO_PROXY'ye ekleyin 0.5.8+.

export HTTPS_PROXY=http://proxy.firma.local:3128 NO_PROXY=.firma.local && curl -fsSL https://spitfire.tr/install.sh | bash -s -- docker

Docker imajı indirirken shell'in değil Docker servisinin proxy ayarını kullanır (Docker Desktop: Settings → Resources → Proxies; Linux: systemctl edit docker ile HTTPS_PROXY). Windows'ta önce $env:HTTPS_PROXY='http://proxy.firma.local:3128'.

Belirli bir sürüm ya da başka bir klasör:

curl -fsSL https://spitfire.tr/install.sh | SPITFIRE_VERSION=0.5.10 SPITFIRE_DIR=/opt/spitfire bash -s -- docker

Anahtarları yedekleyin: SPITFIRE_SECRET_KEY kaybolursa kayıtlı bağlantı parolaları okunamaz.

Kaldırma

~/spitfire/uninstall.sh docker

Verilerle birlikte: --purge. Kubernetes ve runner için kubernetes / runner.

Lisans

Spitfire lisanssız da çalışır (ücretsiz sürüm limitleriyle). Lisans anahtarını arayüzde Lisans sayfasına yapıştırın; anahtar çevrimdışı doğrulanır.