Skip to content

Configuration

oikapi is configured via config.yaml or environment variables with the OIKAPI_ prefix.

server:
port: 8080
metrics_port: 9090 # internal port for /metrics, /livez, /readyz
request_timeout: "30s"
shutdown_timeout: "30s"
allowed_origins: # CORS origins; wildcards ("*") are rejected — list origins explicitly
- "https://app.example.com"
cors:
max_age: 300 # seconds preflight results are cached
base_url: "" # external URL used in invite/reset email links
security:
session:
backend: "memory" # memory, valkey, postgres (auto-selects valkey when enabled)
lifetime: "168h" # max session lifetime (7 days)
idle_timeout: "8h" # logout after inactivity
cookie_name: "session"
cookie_same_site: "Lax" # Lax (default), Strict, None — see the warning below
bcrypt_cost: 12 # 10-14 recommended

Multi-factor authentication (TOTP) is also configurable under security.mfa.

log:
level: "info" # trace, debug, info, warn, error
pretty: false # true for human-readable (dev), false for JSON (prod)
no_color: false
cache:
invalidation:
method: "auto" # local, pubsub, auto (pubsub uses ValKey for multi-instance)
file_storage:
provider: "local" # local, s3 (AWS S3 or any S3-compatible store), or seaweedfs
local:
base_path: "./uploads"
s3:
endpoint: "" # for SeaweedFS or other S3-compatible stores
region: "us-east-1"
bucket_name: "oikapi-files"
access_key_id: ""
secret_access_key: ""
use_ssl: true

Exported .oikapp packages are stored separately under package_storage (same structure).

jobs:
enabled: true
workers: 4
scheduler_enabled: true
scheduler_interval: "60s" # how often the scheduler sweeps for due scheduled rules

Auth rate limiting (login, registration, password reset) is always active regardless of rate_limiting.enabled. The enabled flag only gates general API rate limiting.

rate_limiting:
enabled: true
backend: "auto" # auto, local, valkey
auth:
login_per_minute: 10
register_per_minute: 3
password_reset_per_hour: 5

The general per-IP API request limit is no longer a config.yaml key. It is now the runtime setting rate_limiting.api_requests_per_minute (default 600; 0 disables general API limiting) — see Runtime settings.

Controls the fetch() function available in business rules.

http_client:
enabled: false
max_timeout: "10s"
max_response_size: 1048576 # 1MB
allow_private_ips: false # SSRF protection
system_blocked_domains: []
follow_redirects: false
max_redirects: 0

A number of values that used to be config.yaml keys are now runtime settings, stored per-instance in the database and editable without a restart. They are read through the settings registry and take effect immediately.

Each setting resolves in this precedence: an OIKAPI_FLAG_<KEY> environment override (dots uppercased to underscores, e.g. security.registration.modeOIKAPI_FLAG_SECURITY_REGISTRATION_MODE) beats the stored value, which beats the built-in default.

Manage them via the admin API (admin session required):

Terminal window
oi api /api/settings # list all settings
oi api /api/settings/security.registration.mode # read one
oi api PATCH /api/settings/security.registration.mode '{"value":"invite_only"}'

Registration (security.registration.*)

KeyDefaultNotes
security.registration.modeopenopen, disabled, domain_allowlist, invite_only
security.registration.allowed_domains[]used when mode is domain_allowlist
security.registration.require_email_verifyfalse

Account lockout (security.lockout.*)

KeyDefault
security.lockout.max_attempts5
security.lockout.window_minutes15
security.lockout.duration_minutes15
security.lockout.escalation_factor2.0

Token lifetimes (security.tokens.*)

KeyDefaultNotes
security.tokens.password_reset_expiry_hours1whole hours
security.tokens.email_verify_expiry_hours24whole hours

API rate limiting

KeyDefaultNotes
rate_limiting.api_requests_per_minute600per-IP general API limit; 0 disables

(Auth rate limiting — login, registration, password reset — stays under rate_limiting.auth in config.yaml and is always active.)

Every config key can be set via environment variable with the OIKAPI_ prefix and underscores for nesting:

Terminal window
OIKAPI_SERVER_PORT=8080
OIKAPI_SECURITY_SESSION_LIFETIME=168h
OIKAPI_LOG_LEVEL=info
OIKAPI_DB_USER_PASSWORD=secret # OIKAPI_DB_USER_PASSWORD -> db.user.password

Arrays use comma-separated values:

Terminal window
OIKAPI_SERVER_ALLOWED_ORIGINS=https://a.example.com,https://b.example.com