Skip to main content
Ory Kratos is configured using a YAML file, environment variables, or command-line flags. This guide covers the complete configuration structure.

Configuration file

Kratos looks for configuration in these locations (in order):
  1. --config / -c flag: kratos serve -c /path/to/config.yml
  2. $HOME/.kratos.yaml
  3. $PWD/kratos.yaml

Basic configuration

Minimal production configuration:
version: v0.13.0

dsn: postgres://kratos:secret@postgres:5432/kratos?sslmode=require

serve:
  public:
    base_url: https://auth.example.com/
    cors:
      enabled: true
      allowed_origins:
        - https://example.com
  admin:
    base_url: https://admin.example.com/

selfservice:
  default_browser_return_url: https://example.com/
  allowed_return_urls:
    - https://example.com
    - https://app.example.com
  
  flows:
    login:
      ui_url: https://example.com/auth/login
      lifespan: 10m
    
    registration:
      ui_url: https://example.com/auth/register
      lifespan: 10m
      after:
        default_browser_return_url: https://example.com/dashboard
    
    recovery:
      enabled: true
      ui_url: https://example.com/auth/recovery
      lifespan: 10m
    
    verification:
      enabled: true
      ui_url: https://example.com/auth/verification
      lifespan: 10m
    
    settings:
      ui_url: https://example.com/auth/settings
      lifespan: 10m
      privileged_session_max_age: 15m

identity:
  default_schema_id: default
  schemas:
    - id: default
      url: file:///etc/config/identity.schema.json

secrets:
  cookie:
    - your-32-character-secret-here
  cipher:
    - your-32-character-secret-here

cookies:
  domain: example.com
  path: /
  same_site: Lax

Core configuration sections

Database (DSN)

dsn
string
required
Database connection string. See Database setup for details.
dsn: postgres://user:password@host:5432/kratos?sslmode=require

Server configuration

Public API server configuration:
serve:
  public:
    base_url: https://auth.example.com/
    host: 0.0.0.0
    port: 4433
    cors:
      enabled: true
      allowed_origins:
        - https://example.com
      allowed_methods:
        - POST
        - GET
        - PUT
        - PATCH
        - DELETE
      allowed_headers:
        - Authorization
        - Content-Type
      exposed_headers:
        - Content-Type
      allow_credentials: true
      max_age: 300
Admin API server configuration:
serve:
  admin:
    base_url: https://admin.example.com/
    host: 0.0.0.0
    port: 4434
    # Typically no CORS needed for admin API

Self-service flows

selfservice:
  flows:
    login:
      ui_url: https://example.com/auth/login
      lifespan: 10m
      after:
        default_browser_return_url: https://example.com/dashboard
        password:
          hooks:
            - hook: require_verified_address
            - hook: revoke_active_sessions
selfservice:
  flows:
    registration:
      ui_url: https://example.com/auth/register
      lifespan: 10m
      after:
        default_browser_return_url: https://example.com/welcome
        password:
          hooks:
            - hook: session
            - hook: show_verification_ui
selfservice:
  flows:
    recovery:
      enabled: true
      ui_url: https://example.com/auth/recovery
      lifespan: 10m
      use: code  # or 'link'
      notify_unknown_recipients: false
selfservice:
  flows:
    verification:
      enabled: true
      ui_url: https://example.com/auth/verification
      lifespan: 10m
      use: code  # or 'link'
      notify_unknown_recipients: false
selfservice:
  flows:
    settings:
      ui_url: https://example.com/auth/settings
      lifespan: 10m
      privileged_session_max_age: 15m
      required_aal: aal1  # or 'highest_available', 'aal2'

Authentication methods

selfservice:
  methods:
    password:
      enabled: true
      config:
        haveibeenpwned_enabled: true
        identifier_similarity_check_enabled: true
        min_password_length: 8
        max_breaches: 0
selfservice:
  methods:
    oidc:
      enabled: true
      config:
        providers:
          - id: google
            provider: google
            client_id: your-client-id
            client_secret: your-client-secret
            mapper_url: file:///etc/config/oidc.google.jsonnet
            scope:
              - email
              - profile
selfservice:
  methods:
    webauthn:
      enabled: true
      config:
        rp:
          display_name: My Application
          id: example.com
          origins:
            - https://example.com
            - https://app.example.com
        passwordless: true
selfservice:
  methods:
    totp:
      enabled: true
      config:
        issuer: MyApp

Identity schemas

identity:
  default_schema_id: default
  schemas:
    - id: default
      url: file:///etc/config/identity.default.schema.json
    - id: customer
      url: file:///etc/config/identity.customer.schema.json
    - id: employee
      url: base64://eyJpZCI6Imh0dHA...

Sessions

session:
  lifespan: 24h
  earliest_possible_extend: 1h
  whoami:
    required_aal: aal1
  cookie:
    name: ory_session
    persistent: true
    same_site: Lax

Secrets

Secrets must be at least 32 characters long. Use cryptographically secure random strings.
secrets:
  default:
    - your-32-character-secret-here
    - old-secret-for-rotation
  cookie:
    - your-32-character-cookie-secret
  cipher:
    - your-32-character-cipher-secret
Generate secure secrets:
openssl rand -base64 32

Cookies

cookies:
  domain: example.com
  path: /
  same_site: Lax  # Strict, Lax, or None
  secure: true

Hashers

hashers:
  algorithm: bcrypt
  bcrypt:
    cost: 12
  argon2:
    memory: 131072
    iterations: 3
    parallelism: 4
    salt_length: 16
    key_length: 32

Courier (email/SMS)

courier:
  smtp:
    connection_uri: smtps://username:[email protected]:465/
    from_address: [email protected]
    from_name: My Application
  
  templates:
    recovery:
      valid:
        email:
          subject: Recover access to your account
          body:
            plaintext: file:///etc/config/templates/recovery.plaintext.gotmpl
            html: file:///etc/config/templates/recovery.html.gotmpl

Logging

log:
  level: info  # trace, debug, info, warn, error, fatal, panic
  format: json  # json or text
  leak_sensitive_values: false

Environment variables

All configuration options can be set via environment variables using uppercase and underscores:
# Database
export DSN="postgres://user:pass@host/db"

# Server
export SERVE_PUBLIC_BASE_URL="https://auth.example.com"
export SERVE_PUBLIC_PORT="4433"
export SERVE_ADMIN_BASE_URL="https://admin.example.com"
export SERVE_ADMIN_PORT="4434"

# Secrets
export SECRETS_COOKIE="your-32-character-secret"
export SECRETS_CIPHER="your-32-character-secret"

# Logging
export LOG_LEVEL="info"
export LOG_FORMAT="json"

Configuration validation

Validate your configuration:
kratos serve -c /path/to/config.yml --config-only

Next steps

Run migrations

Set up your database schema

Security best practices

Harden your deployment

Build docs developers (and LLMs) love