> ## Documentation Index
> Fetch the complete documentation index at: https://docs.diyanet.pro/llms.txt
> Use this file to discover all available pages before exploring further.

# Ortamlar — Dev / Stage / Prod

> Ortam başına Keycloak, realm isimlendirme, BaseUrl vs PublicBaseUrl ve .env değişkenleri

Her ortamın (dev / stage / prod) kendi Keycloak instance'ı ve kendi realm çiftleri vardır.
Realm isimleri ortam suffix'i ile tekrarlanır.

| Ortam | Vatandaş Realm                 | Personel Realm                | Keycloak                                            |
| ----- | ------------------------------ | ----------------------------- | --------------------------------------------------- |
| dev   | `diyanet-vatandas-dev-realm`   | `diyanet-yonetim-dev-realm`   | container (`localhost:8080`), otomatik provisioning |
| stage | `diyanet-vatandas-stage-realm` | `diyanet-yonetim-stage-realm` | harici / paylaşımlı                                 |
| prod  | `diyanet-vatandas-prod-realm`  | `diyanet-yonetim-prod-realm`  | harici (müşteri)                                    |

## Dev

* Keycloak bir Docker container'ıdır (`docker-compose.override.yml`, `keycloak26`).
* API açılışta `KeycloakProvisioning` ile realm/client/rol/kullanıcı/mapper'ı otomatik kurar
  (`Enabled: true`, `RunOnce: true`).
* `RequireHttpsMetadata: false` — HTTP yeterlidir.
* Tarayıcı ve API aynı `localhost:8080`'i gördüğü için `BaseUrl == PublicBaseUrl`.

## Stage / Prod

* Keycloak genelde müşterinin **harici** instance'ıdır (`https://auth.diyanet.gov.tr`).
* Provisioning kapatılır (`Enabled: false`); realm bir kez kurulup yönetilir.
* `RequireHttpsMetadata: true` olmalı.
* Realm/URL değerleri `.env` üzerinden gelir.

```bash theme={null}
# .env.stage / .env.prod (kritik Keycloak değişkenleri)
KEYCLOAK_BASE_URL=https://auth.diyanet.gov.tr       # API → Keycloak (internal/external)
KEYCLOAK_EXTERNAL_URL=https://auth.diyanet.gov.tr   # tarayıcının gördüğü URL
```

## BaseUrl vs PublicBaseUrl

Bu ayrım çift-realm doğrulamanın kalbidir (`KeycloakSchemeOptions`):

| Alan            | Anlam                                                                                                                                                             |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `BaseUrl`       | API'nin Keycloak'a ulaştığı URL. Docker dev'de iç ağ hostname'i olabilir (`http://diyanet-keycloak:8080`). JWKS metadata fetch ve `Authority` buradan hesaplanır. |
| `PublicBaseUrl` | Tarayıcının gördüğü URL. Token'ın `iss` claim'i bunu taşır. Boşsa `BaseUrl` ile aynı kabul edilir.                                                                |

```text theme={null}
Authority     = {BaseUrl}/realms/{Realm}            → JWKS / metadata (API tarafı)
Issuer        = Authority
PublicIssuer  = {PublicBaseUrl}/realms/{Realm}      → token "iss" (browser tarafı)
```

Issuer doğrulaması her ikisini de kabul eder:

```csharp theme={null}
var validIssuers = scheme.Issuer == scheme.PublicIssuer
    ? new[] { scheme.Issuer }
    : new[] { scheme.Issuer, scheme.PublicIssuer };
```

<Warning>
  Docker dev'de API container'ı Keycloak'a `diyanet-keycloak:8080` üzerinden ulaşır ama token'ın
  `iss`'i `localhost:8080`'dir. `PublicBaseUrl` set edilmezse issuer mismatch → her token 401 alır.
  Bu yüzden `BaseUrl` ile `PublicBaseUrl` farklıysa **ikisini de** doğru girin.
</Warning>

## Hetzner paylaşımlı Keycloak

Hetzner çoklu-proje kurulumunda (`docker-compose.platform.yml` / `.shared-infra.yml`) Keycloak
platform seviyesinde **paylaşımlıdır**: birden fazla proje aynı Keycloak instance'ını kullanır,
her proje kendi realm çiftiyle izole olur. Bu durumda:

* `KEYCLOAK_BASE_URL` paylaşımlı Keycloak'ı işaret eder.
* Realm isimleri proje + ortam ile ayrışır (`ProjectKeycloakId` template sembolü).
* Provisioning genelde kapalıdır; realm'ler bir kez platform kurulumunda hazırlanır.

## Ortam doğrulama

API açılışında console'a hangi URL'lerin kullanıldığı yazılır
(`BuildingBlocks.Keycloak/DependencyInjection.cs`):

```text theme={null}
[Keycloak JWT] Vatandas Authority    = http://localhost:8080/realms/diyanet-vatandas-dev-realm
[Keycloak JWT] Vatandas PublicIssuer = http://localhost:8080/realms/diyanet-vatandas-dev-realm
[Keycloak JWT] Personel Authority    = http://localhost:8080/realms/diyanet-yonetim-dev-realm
[Keycloak JWT] Vatandas metadata REACHABLE ✓ (.../.well-known/openid-configuration)
```

`UNREACHABLE` görürseniz `BaseUrl` API'den erişilebilir değildir (bkz.
[Sorun Giderme](/keycloak/troubleshooting)).

## İlgili

<CardGroup cols={2}>
  <Card title="Provisioning" href="/keycloak/provisioning">
    Hangi ortamda otomatik kurulum açık.
  </Card>

  <Card title="Sorun Giderme" href="/keycloak/troubleshooting">
    Issuer mismatch ve metadata erişim hataları.
  </Card>

  <Card title="Authentication" href="/security/authentication">
    Issuer / audience doğrulama detayları.
  </Card>

  <Card title="Realm Yapısı" href="/keycloak/realm-structure">
    Realm ve rol yapısı.
  </Card>
</CardGroup>
