Configuration
Kirak keeps secrets and settings apart. Secrets (passwords, keys, tokens, connection strings that can hold a password) are read only from environment variables. Every other setting is read only from kirak.json, or from create_kirak_app() arguments. There is no silent environment fallback for a setting.
Configuration Precedence
Section titled “Configuration Precedence”create_kirak_app() / Kirak() arguments <- code-level settings, highest priority vkirak.json manifest <- every non-secret setting vRuntime built-in defaults <- lowest priority
Environment variables (.env / shell) <- secrets only; never override a settingkirak.local.json, when present, is merged over kirak.json first (see Per-environment values), so it sits at the kirak.json level of this list. .env files are loaded automatically by Kirak via python-dotenv at startup. If you upgrade a project that still sets a retired variable such as DB_HOST or KIRAK_BASE_URL, startup logs a warning that names the kirak.json key that replaces it.
create_kirak_app() Parameters
Section titled “create_kirak_app() Parameters”These parameters are passed directly to the factory and take precedence over kirak.json.
| Parameter | Type | Default | Description |
|---|---|---|---|
models_path |
str |
– | Required. Path to a models.json file or a directory of *.json files. |
title |
str |
"Kirak API" |
FastAPI application title. |
description |
str |
"API built with Kirak Runtime" |
FastAPI application description. |
version |
str |
"1.0.0" |
API version string. |
enable_cors |
bool |
False |
Enable CORS middleware. |
cors_origins |
list[str] |
[] |
Allowed CORS origins. |
modules |
list[str] |
[] |
Modules to enable: notifications, payments, ai, storage, scheduler, monitoring, vector. If not passed, falls back to kirak.json modules. |
kirak_prefix |
str |
"" |
URL prefix for all CRUD routes. |
auth_prefix |
str |
None (/auth) |
URL path of the auth routes; replaces /auth ("/api/auth" -> /api/auth/login). Links Kirak builds (emails, social redirect_uri) follow it. The Kirak client SDK calls the default /auth routes. |
module_prefixes |
dict |
{} |
Per-module URL prefix overrides, e.g. {"notifications": "/notif"}. |
middlewares |
list[tuple] |
[] |
Extra ASGI middleware as (MiddlewareClass, options_dict) pairs. |
on_startup |
callable |
None |
async (app) callback – runs before Kirak initialises. |
on_kirak_ready |
callable |
None |
async (kirak) callback – runs after connect(), before mount_routers(). Register hooks here. |
on_shutdown |
callable |
None |
async (app) callback – runs after Kirak disconnects. |
kirak.json Manifest
Section titled “kirak.json Manifest”Every Kirak project has a kirak.json, placed next to your models_path or in the project root (kirak new creates it). Kirak searches for it at startup and refuses to start without one. Invalid JSON or a schema violation prevents startup with a message naming the file and the key. Values that differ per environment go in an optional kirak.local.json next to it.
{ "version": "1", "title": "My API", "description": "Powered by Kirak", "project_name": "My App", "base_url": "https://api.example.com", "modules": ["notifications", "payments", "scheduler"], "database": { "type": "mysql", "host": "localhost", "name": "myapp" }, "cors": { "enabled": true, "origins": ["https://app.example.com", "https://admin.example.com"] }, "rate_limit": { "enabled": true, "default_max_requests": 100, "default_window_seconds": 60, "trusted_proxy_ips": [] }, "custom": { "feature_flag_new_checkout": true }}Only secrets live in .env. Every other setting, including the database host and the allowed CORS origins, is in kirak.json.
Per-environment values: kirak.local.json
Section titled “Per-environment values: kirak.local.json”kirak.json is committed and is the same in every environment. Some values are not: the database host on your laptop is localhost, in Docker it is db; base_url and the CORS origins change between staging and production. Put those in an optional kirak.local.json in the same directory as kirak.json.
{ "base_url": "https://api.example.com", "database": { "host": "db.internal" }, "cors": { "origins": ["https://app.example.com"] }}How it is applied. When Kirak loads kirak.json it looks for kirak.local.json beside it and merges the two before validating the result:
- Objects merge key by key, at any depth. Keys you leave out keep the value from
kirak.json. - Everything else is replaced as a whole: strings, numbers, booleans and lists. A
cors.originslist inkirak.local.jsonreplaces the list inkirak.json, it is not appended to it.
With this kirak.json:
{ "base_url": "http://localhost:8000", "database": { "host": "localhost", "name": "myapp", "user": "root" }, "cors": { "origins": ["http://localhost:3000"], "allow_credentials": true }}and the kirak.local.json above, Kirak runs with:
{ "base_url": "https://api.example.com", "database": { "host": "db.internal", "name": "myapp", "user": "root" }, "cors": { "origins": ["https://app.example.com"], "allow_credentials": true }}Rules
- It accepts exactly the keys
kirak.jsonaccepts, and the merged result is validated like any manifest. A key that is not allowed (a typo, or a secret such asdatabase.password) fails startup. Secrets stay in environment variables; see Configuration Precedence. - It is found only next to a
kirak.json. Akirak.local.jsonon its own is ignored, andkirak.jsonis still required. - Do not commit it. The
.gitignorethatkirak newcreates lists it. Commit the values every environment shares inkirak.json. - It is read once at startup. Restart the app after changing it.
kirak.manifestat runtime holds the merged values, sokirak.manifest.base_urlis the environment’s value.
Providing it per environment
| Environment | How |
|---|---|
| Local development | Create the file by hand next to kirak.json |
| Docker | Mount it read-only: - ./deploy/kirak.local.docker.json:/app/kirak.local.json:ro |
| Docker Compose 2.23.1+ | Define it inline with a top-level configs entry (content: |) and mount that at /app/kirak.local.json |
| Kubernetes | Mount a ConfigMap key as the file kirak.local.json in the app directory |
| CI | Write it in a build step before starting the app |
Errors
| Message | Cause |
|---|---|
Invalid JSON in kirak.local.json (<path>) |
The override file is not valid JSON, or is not a JSON object |
kirak.json validation failed (<path>) |
The merged result breaks the schema; the message names the offending key |
| Key | Type | Default | Description |
|---|---|---|---|
version |
string | "1" |
Manifest schema version. |
title |
string | "" |
API title (informational). |
description |
string | "" |
API description (informational). |
modules |
array | [] |
Modules to enable. Valid values: notifications, payments, ai, storage, scheduler, monitoring, vector. Used only when modules= is not passed to create_kirak_app(). |
cors.enabled |
bool | true |
Enable CORS middleware. |
cors.origins |
array of strings | [] |
Allowed origins, for example ["https://app.example.com"]. The old cors.origins_env key was removed; a kirak.json that still has it fails to load with a message pointing here. |
project_name |
string | "" |
Display name used in OTP SMS messages, as the authenticator-app issuer in MFA QR codes, and as the default app_name of SMS templates. |
base_url |
string | "" |
Public base URL of the app (for example https://api.example.com), without a trailing slash. Used to build links in verification and password reset emails and the social login callback URLs. Required for registration to succeed. |
docs.enabled |
bool | true |
Serve GET /docs, the app’s HTTP API in Markdown for AI agents; see API Docs Endpoint. false registers no route (404). Does not affect openapi.json. |
docs.path |
string | "/docs" |
Path of that document. |
docs.public |
bool | true |
Serve it without a credential. false requires a signed-in caller or an API key (401 otherwise). Does not affect openapi.json, which describes the same models and access rules: set openapi.public too. |
openapi.enabled |
bool | true |
Serve GET /openapi.json, with one set of CRUD paths per model. false registers no route (404). Does not affect /docs. |
openapi.public |
bool | true |
Serve it without a credential. false requires a signed-in caller or an API key (401 otherwise). Independent of docs.public. |
bulk_chunk_size |
int | 500 |
Records per chunk for bulk create, update, delete and destroy. Reduce it if you hit database packet-size limits. |
database.* |
object | see Database | Database connection settings. |
branding.* |
object | see Email Template Branding | Logo, contact details and colours of the built-in emails. |
cors.allow_credentials |
bool | true |
Allow cookies and credentials in CORS requests. |
cors.allow_methods |
array | ["*"] |
Allowed HTTP methods. |
cors.allow_headers |
array | ["*"] |
Allowed request headers. |
rate_limit.enabled |
bool | true |
Global kill switch – disables per-model CRUD rate limiting and the hardcoded auth endpoint limits when false. |
rate_limit.default_max_requests |
int | 100 |
Applied to any model with no rate_limit block of its own. |
rate_limit.default_window_seconds |
int | 60 |
Window for the default limit. |
rate_limit.trusted_proxy_ips |
array of strings | [] |
IPs allowed to set X-Forwarded-For/X-Real-IP for rate-limit IP resolution – see Rate Limiting. |
log_level |
string | "INFO" |
Level of the kirak logger: DEBUG, INFO, WARNING, ERROR or CRITICAL. |
log_max_size_mb |
int | 5 |
Size at which the shared log file kirak.log rotates, in megabytes. |
log_backup_count |
int | 1 |
Number of rotated log files kept. |
assets_path |
string | null (assets/) |
Project directory searched first for overrides of bundled assets such as email templates; see asset resolution. |
strict_access |
bool | false |
When true, startup fails with ConfigurationError if any model has a missing or invalid access block. Without it, such a model starts with a warning and denies every request. |
hook_timeout_seconds |
number | 5.0 |
Maximum seconds an async def hook may run before it is cancelled and skipped (minimum 0.1). Applies to the hooks of every module. Only kirak.json sets it: the KIRAK_HOOK_TIMEOUT environment variable is no longer read. |
log_path |
string | "logs" |
Directory of the shared log file kirak.log, relative to the working directory or absolute. Only kirak.json sets it: the LOG_PATH environment variable is no longer read. |
custom |
object | {} |
Arbitrary key/value pairs – accessible at runtime via kirak.manifest.custom. |
Access manifest values at runtime:
def on_kirak_ready(kirak): if kirak.manifest.custom.get("feature_flag_new_checkout"): # wire up new checkout hooks pass
# Check which modules were loaded print(kirak.manifest.modules) # ['notifications', 'payments']Database
Section titled “Database”The database block of kirak.json holds every database setting except the password. The password is a secret and is read from the DB_PASSWORD environment variable.
"database": { "type": "postgres", "host": "db.internal", "name": "myapp", "user": "app"}| Key | Default | Required | Description |
|---|---|---|---|
database.type |
mysql |
Database engine: mysql or postgres (postgresql is accepted). |
|
database.host |
localhost |
Database hostname or IP. | |
database.port |
3306 / 5432 |
Port. The default follows database.type: 3306 (MySQL), 5432 (PostgreSQL). |
|
database.user |
root |
Database user. | |
database.name |
– | Yes | Database name. Startup raises ConfigurationError if empty. |
database.pool_min |
1 |
Minimum pool connections (1-100). Must not exceed pool_max. |
|
database.pool_max |
10 |
Maximum pool connections (1-100). | |
database.pool_recycle_seconds |
3600 |
Seconds before idle connections are recycled. MySQL only. |
| Environment variable | Required | Description |
|---|---|---|
DB_PASSWORD |
Database password. Empty by default. |
The old DB_TYPE, DB_HOST, DB_PORT, DB_USER, DB_NAME, DB_POOL_MIN, DB_POOL_MAX and DB_POOL_RECYCLE variables are no longer read. If one is still set, startup logs a warning that names the kirak.json key that replaces it.
Switching from MySQL to PostgreSQL:
pip install "kirak[postgres]""database": { "type": "postgres", "name": "myapp" }No application code changes needed – the dialect layer handles all SQL differences transparently.
Authentication
Section titled “Authentication”All auth variables use the KIRAK_AUTH_ prefix.
JWT Tokens
Section titled “JWT Tokens”| Variable | Default | Required | Description |
|---|---|---|---|
KIRAK_AUTH_JWT_SECRET_KEY |
– | Yes | Access token signing key. Must be >= 32 bytes. Startup fails if unset or too short. |
KIRAK_AUTH_JWT_REFRESH_SECRET_KEY |
– | Refresh token signing key. Falls back to KIRAK_AUTH_JWT_SECRET_KEY if not set. Recommended to set separately in production. |
|
KIRAK_AUTH_JWT_OLD_SECRET_KEY |
– | Previous access token signing key. Set during key rotation to keep tokens signed with the old key valid until they expire. Once all old tokens have expired, remove this variable. | |
KIRAK_AUTH_JWT_REFRESH_OLD_SECRET_KEY |
– | Previous refresh token signing key. Mirrors KIRAK_AUTH_JWT_OLD_SECRET_KEY for refresh tokens. Falls back to KIRAK_AUTH_JWT_OLD_SECRET_KEY if not set. |
|
KIRAK_AUTH_API_KEY_SECRET |
KIRAK_AUTH_JWT_SECRET_KEY |
Keys the stored hash of API keys. Set it in production: without it API keys are hashed with the JWT secret, and rotating that secret invalidates every API key (Kirak logs a warning at startup while it is unset). Keys created before you set it keep working until the JWT secret changes; recreate them to move them onto this secret. |
Token lifetimes and the signing algorithm are kirak.json manifest settings under "auth", not environment variables:
| Setting | Default | Accepted values |
|---|---|---|
jwt_algorithm |
HS256 |
HS256, HS384, HS512 (asymmetric algorithms are rejected to prevent algorithm-confusion attacks) |
access_token_expire_hours |
1 |
any integer >= 1 |
access_token_expire_minutes |
unset | any integer >= 1. When set, it wins over access_token_expire_hours; use it for lifetimes under an hour (for example 5) |
refresh_token_expire_days |
14 |
any integer >= 1 |
Generate a secure key:
python -c "import secrets; print(secrets.token_hex(32))"Email Verification & Password Reset
Section titled “Email Verification & Password Reset”| Variable | Default | Required | Description |
|---|---|---|---|
KIRAK_AUTH_VERIFICATION_KEY |
– | Yes | Fernet key for signing email verification and password reset links. |
KIRAK_AUTH_ENCRYPTION_KEY |
derived from KIRAK_AUTH_JWT_SECRET_KEY |
AES-256-GCM key encrypting social-login token data (auth_social.extra_data) and MFA TOTP secrets (auth_mfa.totp_secret). Falls back to a SHA-256 derivation of the JWT secret with a startup warning if unset – set explicitly in production. Unrelated to KIRAK_AUTH_VERIFICATION_KEY (Fernet, used only for verification/reset links). |
Generate a Fernet key:
from cryptography.fernet import Fernetprint(Fernet.generate_key().decode())The links themselves are configured in kirak.json:
| Key | Default | Description |
|---|---|---|
base_url |
– | Required. Base URL of your application (e.g. https://api.example.com). Required to build verification and reset links, and for registration to succeed at all, even without email sending configured. |
auth.forgot_password_page_url |
{base_url}/auth/forgot-password (/auth is auth_prefix when set) |
Frontend URL for the password reset form. Included in password reset emails. |
Account Behaviour
Section titled “Account Behaviour”email_verification_required (default true) is also a kirak.json manifest setting under "auth", not an environment variable – set "email_verification_required": false in development to skip the verification step.
| kirak.json key | Default | Description |
|---|---|---|
project_name |
– | Display name used in OTP SMS messages and as the TOTP issuer name in MFA QR codes (e.g. "My App"). |
Email Template Branding
Section titled “Email Template Branding”The branding block of kirak.json controls the appearance of Kirak’s built-in email templates (verification, password reset, welcome, invoice, etc.). Values you pass in a template’s own parameters win over these defaults.
| Key | Default | Description |
|---|---|---|
branding.logo |
"" |
URL of your logo image, inserted into email headers. |
branding.support_email |
"" |
Support email address shown in email footers. |
branding.website_url |
"" |
Your website URL, used for footer links. |
branding.login_url |
"" |
Login page URL, linked in verification and reset emails. |
branding.primary_bg_color |
"#000000" |
Primary background color (hex). |
branding.secondary_bg_color |
"#E7054C" |
Accent/button background color (hex). |
branding.primary_text_color |
"#000000" |
Primary text color (hex). |
branding.secondary_text_color |
"#FFFFFF" |
Text color on accent backgrounds (hex). |
The LOGO, SUPPORT_EMAIL, WEBSITE_URL, LOGIN_URL and colour environment variables are no longer read.
Override any template entirely by placing a same-named .py file under assets/notifications/templates/email/ in your project (see asset resolution).
Password Security
Section titled “Password Security”These are kirak.json manifest settings under "auth", not environment variables:
| Key | Default | Description |
|---|---|---|
bcrypt_rounds |
13 |
bcrypt work factor. Higher = more secure, slower. Do not set below 12 in production. |
password_complexity |
true |
Minimum length is always 12 characters regardless of this flag. When true (default), also requires at least one uppercase letter, one lowercase letter, one digit, and one special character from `!@#$%^&*(),.?“:{} |
Cookie-Based Auth
Section titled “Cookie-Based Auth”Set both settings to enable an HttpOnly; Secure; SameSite=Lax access-token cookie alongside
the JWT response body. The cookie is read as a third credential (after Bearer, after API key),
so browsers that send only the cookie are authenticated without an Authorization header.
These are kirak.json manifest settings under "auth", not environment variables:
{ "auth": { "cookie_name": "kirak_token", "cookie_domain": ".example.com" } }| Key | Default | Description |
|---|---|---|
cookie_name |
– | Cookie name. When set, access tokens are written to an HttpOnly cookie on login, verify-OTP, refresh-token, and social callback responses, and read back on every authenticated request. |
cookie_domain |
– | Cookie domain. Use .yourdomain.com (note the leading dot) to share across subdomains. |
Social Login
Section titled “Social Login”Configure only the providers you use. Client IDs, key and team IDs and redirect URIs are settings in the auth.social block of kirak.json. Client secrets and the Apple private key are secrets and stay in the environment.
"auth": { "social_providers": ["google", "apple"], "social": { "google": { "client_id": "123456-abc.apps.googleusercontent.com" }, "apple": { "client_id": "com.example.app.service", "team_id": "ABCDE12345", "key_id": "K1L2M3N4" } }, "apple_web_callback_url": "https://app.example.com/auth/callback"}The redirect URI of every provider defaults to {base_url}/auth/{provider}/callback (/auth is auth_prefix when one is set). Set redirect_uri in a provider’s block only to override it.
| Provider | auth.social.<provider> keys |
Environment secrets |
|---|---|---|
google |
client_id, redirect_uri, audience (client ids a mobile sign-in ID token may be issued to; default [client_id]) |
KIRAK_AUTH_GOOGLE_CLIENT_SECRET |
github |
client_id, redirect_uri |
KIRAK_AUTH_GITHUB_CLIENT_SECRET |
apple |
client_id, team_id, key_id, redirect_uri, audience (as for google; add the iOS bundle id for mobile sign-in) |
KIRAK_AUTH_APPLE_PRIVATE_KEY |
facebook |
client_id, redirect_uri |
KIRAK_AUTH_FACEBOOK_CLIENT_SECRET |
instagram |
client_id, redirect_uri |
KIRAK_AUTH_INSTAGRAM_CLIENT_SECRET |
tiktok |
client_key, redirect_uri |
KIRAK_AUTH_TIKTOK_CLIENT_SECRET |
The catalog names google-oauth2 and apple-id in social_providers use the google and apple blocks.
Other settings:
| Setting | Where | Description |
|---|---|---|
auth.apple_web_callback_url |
kirak.json | Frontend URL for the post-Apple-callback redirect (web flows). |
KIRAK_AUTH_WEB_TOKEN_SECRET |
environment | Signing secret for short-lived Apple web-auth state tokens. Falls back to KIRAK_AUTH_JWT_SECRET_KEY if not set. Set a separate value in production to scope exposure. |
Providers that are not in the table (Discord, LinkedIn, …) take their client ID and secret through the social-core settings; see Social Auth.
The OAuth strategy takes its host and scheme from base_url, so KIRAK_AUTH_HOST and KIRAK_AUTH_HTTPS are no longer needed or read. Use an http:// base_url for local development without TLS.
The old KIRAK_AUTH_<PROVIDER>_CLIENT_ID, _CLIENT_KEY, _TEAM_ID, _KEY_ID, _REDIRECT_URI and KIRAK_AUTH_APPLE_WEB_AUTH_CALLBACK_URL variables, and the direct SOCIAL_AUTH_* variables, are no longer read.
All auth keys
Section titled “All auth keys”auth key |
Type | Description |
|---|---|---|
jwt_algorithm |
string | Token signing algorithm. Asymmetric algorithms are rejected. Default HS256. |
access_token_expire_hours |
integer | Access token lifetime in hours. Default 1. |
access_token_expire_minutes |
integer | Access token lifetime in minutes, for lifetimes under an hour. When set, wins over access_token_expire_hours. |
refresh_token_expire_days |
integer | Refresh token lifetime in days. Default 14. |
email_verification_required |
boolean | Require users to verify their email before signing in. Default true. |
cookie_name |
string | When set, access tokens are also written to an HttpOnly cookie of this name on login, OTP verification, refresh and social callbacks. |
cookie_domain |
string | Cookie domain. A leading dot (.example.com) shares it across subdomains. |
social_providers |
array | Social login providers to enable, by social-core name (e.g. google-oauth2, github, apple-id). |
social |
object | Non-secret settings per social provider (client IDs, redirect URIs, and any other setting the provider’s social-core backend reads, as a lowercase key, e.g. auth0: {“domain”: …}). Client secrets and the Apple private key are environment variables: KIRAK_AUTH_ |
forgot_password_page_url |
string | Frontend page with the password reset form, linked from reset emails. Default {base_url}/auth/forgot-password (/auth is auth_prefix when set). |
apple_web_callback_url |
string | Frontend URL the Apple web sign-in flow redirects to after its callback. |
bcrypt_rounds |
integer | bcrypt work factor for password hashes. Do not go below 12 in production. Default 13. |
password_complexity |
boolean | Require an uppercase letter, a lowercase letter, a digit and a special character. The minimum length of 12 always applies. Default true. |
Notifications
Section titled “Notifications”Requires pip install "kirak[notifications-ses]" for email (AWS SES), pip install "kirak[notifications-sns]" for SMS (AWS SNS), pip install "kirak[notifications-sendgrid]" for email (SendGrid), pip install "kirak[notifications-firebase]" for push (FCM), pip install "kirak[notifications-twilio]" for SMS (Twilio) and pip install "kirak[notifications-apn]" for push (Apple). SMTP, Mailgun, Postmark, SparkPost, Brevo, Resend, Vonage, Plivo, MessageBird, Africa’s Talking, Termii, FastSMS, Huawei, Expo, Slack, Discord, Telegram and webhooks need no extra install.
Each channel (email, sms, push, im, webhook) declares its provider instances and default in kirak.json under "notifications". Only credentials are environment variables (prefix KIRAK_NOTIFICATION_).
kirak.json settings
Section titled “kirak.json settings”{ "notifications": { "email_from_address": "no-reply@example.com", "email_from_name": "My App", "sms_from_number": null, "attachment_base_path": null, "email": { "default_provider": "ses", "providers": { "ses": { "type": "aws_ses", "aws_region": "us-east-1" } } }, "sms": { "default_provider": "sns", "providers": { "sns": { "type": "aws_sns", "aws_region": "us-east-1" } } }, "push": { "default_provider": "fcm", "providers": { "fcm": { "type": "firebase", "firebase_project_id": "my-project" } } }, "im": { "default_provider": "ops_slack", "providers": { "ops_slack": { "type": "slack" } } }, "webhook": { "default_provider": "billing", "providers": { "billing": { "type": "generic", "url": "https://billing.example.com/hooks" } } } }}notifications key |
Type | Description |
|---|---|---|
email_from_address |
string or null | Sender address, e.g. no-reply@example.com. |
email_from_name |
string or null | Sender display name. |
sms_from_number |
string or null | SMS sender number or name, used when a provider instance sets none. |
attachment_base_path |
string or null | Directory email attachment paths are resolved from. |
email |
object | Email providers (e.g. aws_ses, sendgrid, smtp). |
sms |
object | SMS providers (e.g. aws_sns, twilio). |
push |
object | Push providers (e.g. firebase, apn, huawei). |
im |
object | Instant messaging providers (e.g. slack, discord, telegram). |
webhook |
object | Outgoing webhook providers (e.g. generic). |
Each channel key (email, sms, push, im, webhook) is a provider set: default_provider (instance name, required when providers is non-empty) and providers (map of instance name to settings). Names are lowercase letters, digits and _, starting with a letter. Every entry needs type. A channel left out is unavailable. |
Email templates are not configured via a base-path setting – they resolve through asset resolution at a fixed location (assets/notifications/templates/email/ in your project, falling back to Kirak’s bundled templates).
Providers: settings and secrets
Section titled “Providers: settings and secrets”Settings go in the provider entry in kirak.json; secrets are environment variables, one set per provider instance: KIRAK_NOTIFICATION_<CHANNEL>_<INSTANCE>_<FIELD>, upper-cased. Credentials in kirak.json are rejected. AWS credentials (SES, SNS) are optional; boto3 uses its default credential chain when they are unset (set both keys or neither).
<INSTANCE> is the provider instance’s name in kirak.json, upper-cased: an instance
named main reads ..._MAIN_....
email / aws_ses (pip install "kirak[notifications-ses]") – Email through Amazon SES.
Credential check (check()): GetSendQuota (also: is the account in the sandbox).
| Name | Where | Required / default | Description |
|---|---|---|---|
aws_region |
kirak.json | AWS region, e.g. us-east-1. | |
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_ACCESS_KEY |
environment | AWS access key ID. Optional: boto3’s default credential chain is used when unset. | |
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_SECRET_KEY |
environment | AWS secret access key. Set together with the access key. |
email / sendgrid (pip install "kirak[notifications-sendgrid]") – Email through SendGrid.
Credential check (check()): GET /v3/scopes; mail.send must be granted.
| Name | Where | Required / default | Description |
|---|---|---|---|
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_API_KEY |
environment | required | SendGrid API key (starts with SG.). |
email / smtp (no extra install) – Email through any SMTP server.
Credential check (check()): Connect, STARTTLS as configured, LOGIN, QUIT; nothing is sent.
| Name | Where | Required / default | Description |
|---|---|---|---|
smtp_host |
kirak.json | required | SMTP server host. |
smtp_port |
kirak.json | default 587 |
SMTP server port. |
smtp_use_tls |
kirak.json | default True |
Use STARTTLS. |
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_USERNAME |
environment | SMTP username. Leave unset for a server without authentication. | |
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_PASSWORD |
environment | SMTP password. |
email / mailgun (no extra install) – Email through Mailgun.
Credential check (check()): GET /v3/domains/
| Name | Where | Required / default | Description |
|---|---|---|---|
domain |
kirak.json | required | Sending domain, e.g. mg.example.com. |
region |
kirak.json | default us |
Account region: us or eu. |
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_API_KEY |
environment | required | Mailgun API key. |
email / postmark (no extra install) – Email through Postmark.
Credential check (check()): GET /server.
| Name | Where | Required / default | Description |
|---|---|---|---|
message_stream |
kirak.json | default outbound |
Message stream to send through. |
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_SERVER_TOKEN |
environment | required | Postmark server API token. |
email / sparkpost (no extra install) – Email through SparkPost.
Credential check (check()): GET /api/v1/account; a send-only key cannot read it, so that result is unverified.
| Name | Where | Required / default | Description |
|---|---|---|---|
region |
kirak.json | default us |
Account region: us or eu. |
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_API_KEY |
environment | required | SparkPost API key with the Transmissions: Read/Write permission. |
email / brevo (no extra install) – Email through Brevo (formerly Sendinblue).
Credential check (check()): GET /v3/account.
| Name | Where | Required / default | Description |
|---|---|---|---|
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_API_KEY |
environment | required | Brevo API key (xkeysib-…). |
email / resend (no extra install) – Email through Resend.
Credential check (check()): GET /domains; a sending-only key is reported as valid.
| Name | Where | Required / default | Description |
|---|---|---|---|
KIRAK_NOTIFICATION_EMAIL_<INSTANCE>_API_KEY |
environment | required | Resend API key (re_…). |
sms / aws_sns (pip install "kirak[notifications-sns]") – SMS through Amazon SNS.
Credential check (check()): GetSMSSandboxAccountStatus.
| Name | Where | Required / default | Description |
|---|---|---|---|
aws_region |
kirak.json | AWS region, e.g. us-east-1. | |
KIRAK_NOTIFICATION_SMS_<INSTANCE>_ACCESS_KEY |
environment | AWS access key ID. Optional: boto3’s default credential chain is used when unset. | |
KIRAK_NOTIFICATION_SMS_<INSTANCE>_SECRET_KEY |
environment | AWS secret access key. Set together with the access key. |
sms / twilio (pip install "kirak[notifications-twilio]") – SMS through Twilio.
Credential check (check()): GET /2010-04-01/Accounts/
| Name | Where | Required / default | Description |
|---|---|---|---|
from_number |
kirak.json | Sender number. Default: notifications.sms_from_number. | |
messaging_service_sid |
kirak.json | Twilio Messaging Service to send from; wins over from_number. | |
KIRAK_NOTIFICATION_SMS_<INSTANCE>_ACCOUNT_SID |
environment | required | Twilio account SID. |
KIRAK_NOTIFICATION_SMS_<INSTANCE>_AUTH_TOKEN |
environment | required | Twilio auth token. |
sms / vonage (no extra install) – SMS through Vonage (formerly Nexmo).
Credential check (check()): GET /account/get-balance.
| Name | Where | Required / default | Description |
|---|---|---|---|
from_number |
kirak.json | Sender: a phone number, or an alphanumeric sender ID where the provider and country allow one. Default: notifications.sms_from_number. | |
KIRAK_NOTIFICATION_SMS_<INSTANCE>_API_KEY |
environment | required | Vonage API key. |
KIRAK_NOTIFICATION_SMS_<INSTANCE>_API_SECRET |
environment | required | Vonage API secret. |
sms / plivo (no extra install) – SMS through Plivo.
Credential check (check()): GET /v1/Account/<auth_id>/.
| Name | Where | Required / default | Description |
|---|---|---|---|
from_number |
kirak.json | Sender: a phone number, or an alphanumeric sender ID where the provider and country allow one. Default: notifications.sms_from_number. | |
KIRAK_NOTIFICATION_SMS_<INSTANCE>_AUTH_ID |
environment | required | Plivo Auth ID. |
KIRAK_NOTIFICATION_SMS_<INSTANCE>_AUTH_TOKEN |
environment | required | Plivo Auth Token. |
sms / messagebird (no extra install) – SMS through MessageBird (Bird).
Credential check (check()): GET /balance.
| Name | Where | Required / default | Description |
|---|---|---|---|
from_number |
kirak.json | Sender: a phone number, or an alphanumeric sender ID where the provider and country allow one. Default: notifications.sms_from_number. | |
KIRAK_NOTIFICATION_SMS_<INSTANCE>_ACCESS_KEY |
environment | required | MessageBird access key. |
sms / africastalking (no extra install) – SMS through Africa’s Talking.
Credential check (check()): GET /version1/user (the account balance); username sandbox is test mode.
| Name | Where | Required / default | Description |
|---|---|---|---|
username |
kirak.json | required | Africa’s Talking app username; sandbox uses the sandbox API. |
from_number |
kirak.json | Registered short code or alphanumeric sender ID. Default: notifications.sms_from_number, else Africa’s Talking’s shared sender. | |
KIRAK_NOTIFICATION_SMS_<INSTANCE>_API_KEY |
environment | required | Africa’s Talking API key. |
sms / termii (no extra install) – SMS through Termii.
Credential check (check()): GET /api/get-balance.
| Name | Where | Required / default | Description |
|---|---|---|---|
base_url |
kirak.json | default https://api.ng.termii.com |
Your account’s API base URL, shown on the Termii dashboard. |
channel |
kirak.json | default generic |
Route: generic (promotional) or dnd (transactional, e.g. OTPs; needs activation by Termii). |
from_number |
kirak.json | Sender: a phone number, or an alphanumeric sender ID where the provider and country allow one. Default: notifications.sms_from_number. | |
KIRAK_NOTIFICATION_SMS_<INSTANCE>_API_KEY |
environment | required | Termii API key. |
sms / fastsms (no extra install) – SMS through FastSMS (UK).
Credential check (check()): Action=CheckCredits.
| Name | Where | Required / default | Description |
|---|---|---|---|
from_number |
kirak.json | Sender: a phone number, or an alphanumeric sender ID where the provider and country allow one. Default: notifications.sms_from_number. | |
KIRAK_NOTIFICATION_SMS_<INSTANCE>_TOKEN |
environment | required | FastSMS API token (NetMessenger account settings). |
push / firebase (pip install "kirak[notifications-firebase]") – Push notifications through Firebase Cloud Messaging.
Credential check (check()): A dry-run send to an invalid device token; nothing is delivered.
| Name | Where | Required / default | Description |
|---|---|---|---|
firebase_credentials_path |
kirak.json | Path of the Firebase service account JSON file. | |
firebase_project_id |
kirak.json | Firebase project ID. |
push / apn (pip install "kirak[notifications-apn]") – Push notifications to Apple devices through APNs.
Credential check (check()): A push to an invalid device token; nothing is delivered.
| Name | Where | Required / default | Description |
|---|---|---|---|
apn_key_path |
kirak.json | required | Path of the .p8 signing key file. |
apn_key_id |
kirak.json | required | Key ID of the signing key. |
apn_team_id |
kirak.json | required | Apple developer team ID. |
apn_bundle_id |
kirak.json | required | App bundle ID (the APNs topic). |
apn_use_sandbox |
kirak.json | default False |
Send through the APNs sandbox (development builds). |
push / huawei (no extra install) – Push notifications to Huawei devices through Push Kit.
Credential check (check()): POST the OAuth token URL (client credentials).
| Name | Where | Required / default | Description |
|---|---|---|---|
app_id |
kirak.json | required | Huawei app ID. |
KIRAK_NOTIFICATION_PUSH_<INSTANCE>_CLIENT_SECRET |
environment | required | Huawei app client secret. |
push / expo (no extra install) – Push notifications to Expo apps through the Expo push service.
Credential check (check()): None: Expo has no endpoint that checks an access token without sending.
| Name | Where | Required / default | Description |
|---|---|---|---|
KIRAK_NOTIFICATION_PUSH_<INSTANCE>_ACCESS_TOKEN |
environment | Expo access token, needed only when push security is enabled for the project. |
im / slack (no extra install) – Messages to Slack channels.
Credential check (check()): POST auth.test; the token must have chat:write.
| Name | Where | Required / default | Description |
|---|---|---|---|
KIRAK_NOTIFICATION_IM_<INSTANCE>_BOT_TOKEN |
environment | required | Bot token. |
im / discord (no extra install) – Messages to Discord channels.
Credential check (check()): GET /users/@me.
| Name | Where | Required / default | Description |
|---|---|---|---|
KIRAK_NOTIFICATION_IM_<INSTANCE>_BOT_TOKEN |
environment | required | Bot token. |
im / telegram (no extra install) – Messages to Telegram chats.
Credential check (check()): getMe.
| Name | Where | Required / default | Description |
|---|---|---|---|
KIRAK_NOTIFICATION_IM_<INSTANCE>_BOT_TOKEN |
environment | required | Bot token. |
webhook / generic (no extra install) – Signed HTTP POST to your own systems.
Credential check (check()): None: a receiver can only be tested by sending to it; the url is checked.
| Name | Where | Required / default | Description |
|---|---|---|---|
url |
kirak.json | Destination URL. | |
allow_url_override |
kirak.json | default False |
Let a call pass its own destination URL. |
timeout |
kirak.json | default 10.0 |
Request timeout in seconds. |
KIRAK_NOTIFICATION_WEBHOOK_<INSTANCE>_SECRET_KEY |
environment | HMAC signing key; requests are unsigned when unset. |
Payments
Section titled “Payments”Requires pip install "kirak[payments-stripe]", pip install "kirak[payments-razorpay]", or pip install "kirak[payments-square]" depending on your gateway; PayPal, Paddle, Paystack, Flutterwave, Mercado Pago, Xendit, Airwallex, Omise and Telr need no extra.
Providers are declared in kirak.json under "payments" as named instances. Each instance has a type (stripe, razorpay, square, paypal, paddle, paystack, flutterwave, mercadopago, xendit, airwallex, omise, telr, stripe_connect, or a custom type) and a default_provider names the one used when a call passes no provider:
"payments": { "default_provider": "stripe", "providers": { "stripe": { "type": "stripe" }, "square": { "type": "square", "location_id": "L123", "environment": "sandbox" } }, "success_url": "/payment/success", "cancel_url": "/payment/cancel"}payments key |
Type | Description |
|---|---|---|
default_provider |
string | Instance name used when a call names no provider. Must be one of the instances under providers. |
providers |
object | Payment provider instances (types stripe, stripe_connect, razorpay, square, or a custom type), by instance name. |
success_url |
string or null | Redirect after a successful payment. Each provider instance can override it. |
cancel_url |
string or null | Redirect after a cancelled payment. Each provider instance can override it. |
require_auth |
boolean | Require a signed-in caller on the payment routes. false allows guest checkout. Default true. |
The currency is passed with each call ("currency": "USD"), not set in kirak.json; see Payments. |
Secrets are read from the environment, one set per instance: KIRAK_PAYMENT_<INSTANCE>_<FIELD>, upper-cased. Secrets in kirak.json are rejected. Each provider’s setup (key prefixes, webhook URL and signature header) is described on its own page under Payments, including which Stripe Connect webhook endpoint each secret verifies.
<INSTANCE> is the provider instance’s name in kirak.json, upper-cased: an instance
named main reads ..._MAIN_....
stripe (pip install "kirak[payments-stripe]") – Stripe Checkout, subscriptions, saved payment methods, off-session charges and disputes.
Credential check (check()): GET /v1/balance.
| Name | Where | Required / default | Description |
|---|---|---|---|
success_url |
kirak.json | default /payment/success |
Redirect after a successful payment. Overrides payments.success_url. |
cancel_url |
kirak.json | default /payment/cancel |
Redirect after a cancelled payment. Overrides payments.cancel_url. |
KIRAK_PAYMENT_<INSTANCE>_SECRET_KEY |
environment | required | Stripe secret API key (sk_live_… or sk_test_…). |
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SECRET |
environment | Webhook signing secret (whsec_…); without it every webhook is refused. |
stripe_connect (pip install "kirak[payments-stripe]") – Stripe Connect marketplace: merchant onboarding, checkout on behalf of merchants, platform fees.
Credential check (check()): GET /v1/account (the platform account).
| Name | Where | Required / default | Description |
|---|---|---|---|
success_url |
kirak.json | default /payment/success |
Redirect after a successful payment. Overrides payments.success_url. |
cancel_url |
kirak.json | default /payment/cancel |
Redirect after a cancelled payment. Overrides payments.cancel_url. |
refresh_url |
kirak.json | default /connect/onboard/refresh |
Onboarding URL Stripe sends a merchant back to when a link expired. |
return_url |
kirak.json | default /connect/onboard/return |
URL Stripe sends a merchant to after onboarding. |
KIRAK_PAYMENT_<INSTANCE>_SECRET_KEY |
environment | required | Stripe secret API key of the platform account. |
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SECRET |
environment | Signing secret of the connected-accounts webhook endpoint. | |
KIRAK_PAYMENT_<INSTANCE>_PLATFORM_WEBHOOK_SECRET |
environment | Signing secret of the platform-account webhook endpoint (checkout, refunds, saved methods). |
razorpay (pip install "kirak[payments-razorpay]") – Razorpay payments, subscriptions, saved payment methods (mandates) and disputes.
Credential check (check()): GET /v1/payments?count=1.
| Name | Where | Required / default | Description |
|---|---|---|---|
success_url |
kirak.json | default /payment/success |
Redirect after a successful payment. Overrides payments.success_url. |
cancel_url |
kirak.json | default /payment/cancel |
Redirect after a cancelled payment. Overrides payments.cancel_url. |
KIRAK_PAYMENT_<INSTANCE>_KEY_ID |
environment | required | Razorpay key ID (rzp_live_… or rzp_test_…). |
KIRAK_PAYMENT_<INSTANCE>_KEY_SECRET |
environment | required | Razorpay key secret. |
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SECRET |
environment | Webhook secret; needed to verify webhooks. |
square (pip install "kirak[payments-square]") – Square payments, subscriptions, saved cards and disputes.
Credential check (check()): GET /v2/locations/<location_id>.
| Name | Where | Required / default | Description |
|---|---|---|---|
location_id |
kirak.json | required | Square location that takes the payments. |
environment |
kirak.json | default sandbox |
“sandbox” or “production”. |
webhook_notification_url |
kirak.json | The exact public URL Square posts webhooks to; part of the signature check. | |
success_url |
kirak.json | default /payment/success |
Redirect after a successful payment. Overrides payments.success_url. |
cancel_url |
kirak.json | default /payment/cancel |
Redirect after a cancelled payment. Overrides payments.cancel_url. |
KIRAK_PAYMENT_<INSTANCE>_ACCESS_TOKEN |
environment | required | Square access token (production or sandbox). |
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SIGNATURE_KEY |
environment | Webhook signature key; needed to verify webhooks. |
paypal (no extra install) – PayPal Checkout: one-time payments, subscriptions, vaulted PayPal accounts, off-session charges and disputes (read-only).
Credential check (check()): POST /v1/oauth2/token; then GET the webhook named by webhook_id.
| Name | Where | Required / default | Description |
|---|---|---|---|
environment |
kirak.json | default sandbox |
“sandbox” or “live”. |
success_url |
kirak.json | default /payment/success |
Redirect after a successful payment. Overrides payments.success_url. |
cancel_url |
kirak.json | default /payment/cancel |
Redirect after a cancelled payment. Overrides payments.cancel_url. |
KIRAK_PAYMENT_<INSTANCE>_CLIENT_ID |
environment | required | PayPal REST app client ID. |
KIRAK_PAYMENT_<INSTANCE>_CLIENT_SECRET |
environment | required | PayPal REST app secret. |
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_ID |
environment | ID of the webhook registered in the app; needed to verify webhooks. |
paddle (no extra install) – Paddle Billing (merchant of record): one-time payments, subscriptions and one-time charges on a subscription.
Credential check (check()): GET /event-types.
| Name | Where | Required / default | Description |
|---|---|---|---|
environment |
kirak.json | default sandbox |
“sandbox” or “production”. |
default_tax_category |
kirak.json | default standard |
Tax category of the product created for a payment without price_id. |
checkout_url |
kirak.json | Approved page that loads Paddle.js; the account’s default payment link otherwise. | |
KIRAK_PAYMENT_<INSTANCE>_API_KEY |
environment | required | Paddle API key. |
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SECRET |
environment | Secret of the notification destination; needed to verify webhooks. |
paystack (no extra install) – Paystack: one-time payments, subscriptions, saved cards, off-session charges and disputes (read-only).
Credential check (check()): GET /balance.
| Name | Where | Required / default | Description |
|---|---|---|---|
environment |
kirak.json | default test |
“test” or “live”; must match the secret key. |
success_url |
kirak.json | default /payment/success |
Redirect after a successful payment. Overrides payments.success_url. |
KIRAK_PAYMENT_<INSTANCE>_SECRET_KEY |
environment | required | Paystack secret key (sk_test_… or sk_live_…); also verifies webhooks. |
flutterwave (no extra install) – Flutterwave (API v3): one-time payments, subscriptions, saved cards, off-session charges and disputes (read-only).
Credential check (check()): GET /v3/balances.
| Name | Where | Required / default | Description |
|---|---|---|---|
environment |
kirak.json | default test |
“test” or “live”; must match the secret key. |
country |
kirak.json | Two-letter country code of the account; needed for off-session charges. | |
success_url |
kirak.json | default /payment/success |
Redirect after a successful payment. Overrides payments.success_url. |
KIRAK_PAYMENT_<INSTANCE>_SECRET_KEY |
environment | required | Flutterwave secret key (FLWSECK_TEST-… or FLWSECK-…). |
KIRAK_PAYMENT_<INSTANCE>_SECRET_HASH |
environment | required | Secret hash set on the webhook; verifies webhooks. |
mercadopago (no extra install) – Mercado Pago: Checkout Pro payments, subscriptions (preapprovals) and disputes (read-only).
Credential check (check()): GET /users/me.
| Name | Where | Required / default | Description |
|---|---|---|---|
environment |
kirak.json | default sandbox |
“sandbox” or “production”. |
success_url |
kirak.json | default /payment/success |
Redirect after a successful payment. Overrides payments.success_url. |
KIRAK_PAYMENT_<INSTANCE>_ACCESS_TOKEN |
environment | required | Mercado Pago access token. |
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SECRET |
environment | required | Secret signature of the webhook; verifies webhooks. |
xendit (no extra install) – Xendit Invoices: one-time payments and refunds.
Credential check (check()): GET /balance.
| Name | Where | Required / default | Description |
|---|---|---|---|
environment |
kirak.json | default test |
“test” or “live”; must match the secret key. |
success_url |
kirak.json | default /payment/success |
Redirect after a successful payment. Overrides payments.success_url. |
KIRAK_PAYMENT_<INSTANCE>_SECRET_KEY |
environment | required | Xendit secret API key (xnd_development_… or xnd_production_…). |
KIRAK_PAYMENT_<INSTANCE>_CALLBACK_TOKEN |
environment | required | Callback verification token; verifies webhooks. |
airwallex (no extra install) – Airwallex Payment Links: one-time payments, refunds and disputes (read-only).
Credential check (check()): POST /api/v1/authentication/login.
| Name | Where | Required / default | Description |
|---|---|---|---|
environment |
kirak.json | default sandbox |
“sandbox” or “production”. |
KIRAK_PAYMENT_<INSTANCE>_CLIENT_ID |
environment | required | Airwallex API client ID. |
KIRAK_PAYMENT_<INSTANCE>_API_KEY |
environment | required | Airwallex API key. |
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SECRET |
environment | required | Secret of the webhook; verifies webhooks. |
omise (no extra install) – Omise (Opn Payments) Links: one-time payments, refunds and disputes (read-only).
Credential check (check()): GET /account.
| Name | Where | Required / default | Description |
|---|---|---|---|
environment |
kirak.json | default test |
“test” or “live”; must match the secret key. |
KIRAK_PAYMENT_<INSTANCE>_SECRET_KEY |
environment | required | Omise secret key (skey_test_… or skey_…). |
KIRAK_PAYMENT_<INSTANCE>_WEBHOOK_SECRET |
environment | Base64 webhook secret; without it each webhook is verified by reading its event back. |
telr (no extra install) – Telr Hosted Payment Page: one-time payments; refunds made in the Telr admin are recorded.
Credential check (check()): None: Telr has no read-only call; the offline checks run.
| Name | Where | Required / default | Description |
|---|---|---|---|
store_id |
kirak.json | required | Numeric Telr store ID. |
environment |
kirak.json | default test |
“test” or “live”. |
success_url |
kirak.json | required | Absolute URL Telr returns the buyer to after paying, declining or cancelling. |
KIRAK_PAYMENT_<INSTANCE>_AUTH_KEY |
environment | required | Authentication key of the Hosted Payment Page. |
KIRAK_PAYMENT_<INSTANCE>_ADVICE_SECRET |
environment | required | Secret key of the transaction advice; verifies webhooks. |
Storage
Section titled “Storage”Requires pip install "kirak[storage]" (image processing, and every S3-compatible type); the gcs and azure types need pip install "kirak[storage-gcs]" or "kirak[storage-azure]" instead, which include it. Providers are declared in kirak.json under "storage" as named instances; only credentials are environment variables (prefix KIRAK_STORAGE_).
kirak.json settings
Section titled “kirak.json settings”{ "storage": { "default_provider": "local", "providers": { "local": { "type": "local", "upload_dir": "assets/media" } }, "image_allowed_types": "jpg,jpeg,png,webp,gif", "image_max_size": "5mb", "image_compress_quality": 85, "image_max_width": 2000, "image_max_height": 2000, "file_allowed_types": "pdf,doc,docx,xls,xlsx,csv,txt,zip", "file_max_size": "50mb", "default_thumbnails": null, "thumbnail_mode": "sync" }}storage key |
Type | Description |
|---|---|---|
default_provider |
string | Instance name used when a call names no provider. Must be one of the instances under providers. |
providers |
object | Storage provider instances (types local, aws, wasabi, r2, spaces, cubbit, ovh, b2, gcs, azure, or a custom type), by instance name. |
image_allowed_types |
string | Allowed image extensions, comma-separated. Default “jpg,jpeg,png,webp,gif”. svg is refused: store vector files with upload_file. |
image_max_size |
string | Maximum image upload size, e.g. “5mb”. Default “5mb”. |
image_compress_quality |
integer | JPEG/WebP compression quality. Default 85. |
image_max_width |
integer | Maximum stored image width in pixels; larger images are scaled down. Default 2000. |
image_max_height |
integer | Maximum stored image height in pixels; larger images are scaled down. Default 2000. |
file_allowed_types |
string | Allowed non-image extensions, comma-separated. Default “pdf,doc,docx,xls,xlsx,csv,txt,zip”. |
file_max_size |
string | Maximum file upload size, e.g. “50mb”. Default “50mb”. |
default_thumbnails |
string or null | Thumbnails generated for every image upload, e.g. “sm:100x100,md:300x300”. Default none. |
thumbnail_mode |
string | sync makes thumbnails before responding; background responds first. Default sync. |
Every storage operation is also path-scoped under the caller’s user id (except for admin) – see Storage. |
Providers: settings and secrets
Section titled “Providers: settings and secrets”Settings go in the provider entry in kirak.json; secrets are environment variables, one set per instance: KIRAK_STORAGE_<INSTANCE>_<FIELD>, upper-cased. Credentials in kirak.json are rejected. aws and wasabi credentials are optional; boto3 uses its default credential chain when they are unset (set both keys or neither). The other S3-compatible types need both keys. gcs and azure credentials are optional too: without them the app’s Google Application Default Credentials or Azure identity is used. A local instance is served at /media/<instance name>; two local instances need different directories.
<INSTANCE> is the provider instance’s name in kirak.json, upper-cased: an instance
named main reads ..._MAIN_....
local (no extra install) – Files on the app’s own disk, served at /media/
Credential check (check()): upload_dir is (or can be created) readable and writable where the check runs.
| Name | Where | Required / default | Description |
|---|---|---|---|
upload_dir |
kirak.json | default assets/media |
Directory uploads are written to. Two local instances need different ones. |
aws (pip install "kirak[storage]") – Amazon S3, or any S3-compatible service through endpoint_url.
Credential check (check()): ListObjectsV2 (MaxKeys=1); with write, PutObject and DeleteObject of one object.
| Name | Where | Required / default | Description |
|---|---|---|---|
aws_bucket |
kirak.json | required | Bucket name. |
aws_region |
kirak.json | default us-east-1 |
Bucket region. |
endpoint_url |
kirak.json | Custom S3 endpoint; leave unset for AWS. | |
public_url |
kirak.json | Base URL of returned file URLs, e.g. a CDN or custom domain in front of the bucket. Unset: the bucket’s own URL. | |
acl |
kirak.json | Canned ACL set on each upload: private or public-read. Unset: none is sent, as buckets with ACLs disabled (the AWS default) require. | |
KIRAK_STORAGE_<INSTANCE>_ACCESS_KEY |
environment | Access key ID. Optional: boto3’s default credential chain is used when unset. | |
KIRAK_STORAGE_<INSTANCE>_SECRET_KEY |
environment | Secret access key. Set together with the access key. |
wasabi (pip install "kirak[storage]") – Wasabi object storage (S3-compatible).
Credential check (check()): ListObjectsV2 (MaxKeys=1); with write, PutObject and DeleteObject of one object.
| Name | Where | Required / default | Description |
|---|---|---|---|
aws_bucket |
kirak.json | required | Bucket name. |
aws_region |
kirak.json | default us-east-1 |
Bucket region. |
endpoint_url |
kirak.json | default https://s3.wasabisys.com |
Wasabi endpoint. |
public_url |
kirak.json | Base URL of returned file URLs, e.g. a CDN or custom domain in front of the bucket. Unset: the bucket’s own URL. | |
acl |
kirak.json | Canned ACL set on each upload: private or public-read. Unset: none is sent, as buckets with ACLs disabled (the AWS default) require. | |
KIRAK_STORAGE_<INSTANCE>_ACCESS_KEY |
environment | Access key ID. Optional: boto3’s default credential chain is used when unset. | |
KIRAK_STORAGE_<INSTANCE>_SECRET_KEY |
environment | Secret access key. Set together with the access key. |
r2 (pip install "kirak[storage]") – Cloudflare R2 (S3-compatible). Returned URLs are public only through public_url.
Credential check (check()): ListObjectsV2 (MaxKeys=1); with write, PutObject and DeleteObject of one object.
| Name | Where | Required / default | Description |
|---|---|---|---|
account_id |
kirak.json | required | Cloudflare account id (32 hex characters); sets the endpoint. |
aws_bucket |
kirak.json | required | Bucket name. |
jurisdiction |
kirak.json | default default |
Where the bucket’s data is kept: default, eu or fedramp. Must match the bucket. |
aws_region |
kirak.json | default auto |
Leave unset: R2 ignores it. |
endpoint_url |
kirak.json | Leave unset: built from account_id and jurisdiction. | |
public_url |
kirak.json | Base URL of returned file URLs: the bucket’s r2.dev subdomain or a custom domain bound to it. Unset: URLs point at the S3 endpoint, which is never public; use get_url with expires. | |
acl |
kirak.json | Leave unset: R2 has no object ACLs, so setting it is an error. | |
KIRAK_STORAGE_<INSTANCE>_ACCESS_KEY |
environment | required | Access key ID. |
KIRAK_STORAGE_<INSTANCE>_SECRET_KEY |
environment | required | Secret access key. |
spaces (pip install "kirak[storage]") – DigitalOcean Spaces (S3-compatible).
Credential check (check()): ListObjectsV2 (MaxKeys=1); with write, PutObject and DeleteObject of one object.
| Name | Where | Required / default | Description |
|---|---|---|---|
aws_bucket |
kirak.json | required | Space (bucket) name. |
aws_region |
kirak.json | required | Datacenter region of the Space, e.g. nyc3 or fra1; sets the endpoint. |
endpoint_url |
kirak.json | Leave unset: https://<aws_region>.digitaloceanspaces.com. | |
public_url |
kirak.json | Base URL of returned file URLs, e.g. the Spaces CDN https:// |
|
acl |
kirak.json | default public-read |
Canned ACL set on each upload: public-read (files readable by URL) or private. |
KIRAK_STORAGE_<INSTANCE>_ACCESS_KEY |
environment | required | Access key ID. |
KIRAK_STORAGE_<INSTANCE>_SECRET_KEY |
environment | required | Secret access key. |
cubbit (pip install "kirak[storage]") – Cubbit DS3, European geo-distributed object storage (S3-compatible).
Credential check (check()): ListObjectsV2 (MaxKeys=1); with write, PutObject and DeleteObject of one object.
| Name | Where | Required / default | Description |
|---|---|---|---|
aws_bucket |
kirak.json | required | Bucket name. |
aws_region |
kirak.json | default eu-west-1 |
Signing region. |
endpoint_url |
kirak.json | default https://s3.cubbit.eu |
Cubbit endpoint; https://s3. |
public_url |
kirak.json | Base URL of returned file URLs, e.g. a CDN or custom domain in front of the bucket. Unset: the bucket’s own URL. | |
acl |
kirak.json | Canned ACL set on each upload: private or public-read. Unset: none is sent, as buckets with ACLs disabled (the AWS default) require. | |
KIRAK_STORAGE_<INSTANCE>_ACCESS_KEY |
environment | required | Access key ID. |
KIRAK_STORAGE_<INSTANCE>_SECRET_KEY |
environment | required | Secret access key. |
ovh (pip install "kirak[storage]") – OVHcloud Object Storage (S3-compatible).
Credential check (check()): ListObjectsV2 (MaxKeys=1); with write, PutObject and DeleteObject of one object.
| Name | Where | Required / default | Description |
|---|---|---|---|
aws_bucket |
kirak.json | required | Bucket name. |
aws_region |
kirak.json | required | Region code in lower case, e.g. gra, sbg, de, uk or eu-west-par; sets the endpoint. |
endpoint_url |
kirak.json | Leave unset: https://s3.<aws_region>.io.cloud.ovh.net. | |
public_url |
kirak.json | Base URL of returned file URLs, e.g. a CDN or custom domain. Unset: https:// |
|
acl |
kirak.json | Canned ACL set on each upload: private or public-read. Unset: none is sent (files are private unless a bucket policy makes them public). | |
KIRAK_STORAGE_<INSTANCE>_ACCESS_KEY |
environment | required | Access key ID. |
KIRAK_STORAGE_<INSTANCE>_SECRET_KEY |
environment | required | Secret access key. |
b2 (pip install "kirak[storage]") – Backblaze B2 (S3-compatible).
Credential check (check()): ListObjectsV2 (MaxKeys=1); with write, PutObject and DeleteObject of one object.
| Name | Where | Required / default | Description |
|---|---|---|---|
aws_bucket |
kirak.json | required | Bucket name. |
aws_region |
kirak.json | required | Region of the bucket’s S3 endpoint, e.g. us-west-004; sets the endpoint. |
endpoint_url |
kirak.json | Leave unset: https://s3.<aws_region>.backblazeb2.com. | |
public_url |
kirak.json | Base URL of returned file URLs, e.g. a CDN or the bucket’s friendly URL https://f004.backblazeb2.com/file/ |
|
acl |
kirak.json | Leave unset: B2 sets ACLs per bucket, so setting it is an error. | |
KIRAK_STORAGE_<INSTANCE>_ACCESS_KEY |
environment | required | Application key ID (keyID). |
KIRAK_STORAGE_<INSTANCE>_SECRET_KEY |
environment | required | Application key (applicationKey). |
gcs (pip install "kirak[storage-gcs]") – Google Cloud Storage, with a service account key or Application Default Credentials.
Credential check (check()): objects.list (maxResults=1); with write, objects.insert and objects.delete of one object; under ADC with signing_service_account, IAM signBlob of one URL.
| Name | Where | Required / default | Description |
|---|---|---|---|
bucket |
kirak.json | required | Bucket name. |
project_id |
kirak.json | Project id. Unset: the key’s project, or the ADC project. | |
public_url |
kirak.json | Base URL of returned file URLs, e.g. a Cloud CDN or load balancer domain. Unset: https://storage.googleapis.com/ |
|
signing_service_account |
kirak.json | Service account email that signs URLs (get_url with expires) under Application Default Credentials; the app’s identity needs iam.serviceAccounts.signBlob on it. Not needed with credentials_json. | |
KIRAK_STORAGE_<INSTANCE>_CREDENTIALS_JSON |
environment | Service account key file contents (JSON). Optional: Application Default Credentials are used when unset. |
azure (pip install "kirak[storage-azure]") – Azure Blob Storage, with a connection string, an account key or the app’s Azure identity.
Credential check (check()): List Blobs (maxresults=1); with write, Put Blob and Delete Blob of one blob; under an Azure identity, Get User Delegation Key.
| Name | Where | Required / default | Description |
|---|---|---|---|
container |
kirak.json | required | Container name. |
account_name |
kirak.json | Storage account name. Required unless connection_string is set. | |
account_url |
kirak.json | Blob endpoint, for sovereign clouds or Azurite. Unset: https://<account_name>.blob.core.windows.net. | |
public_url |
kirak.json | Base URL of returned file URLs, e.g. an Azure Front Door or CDN domain. Unset: the blob’s own URL, readable only if the container allows anonymous blob access. | |
KIRAK_STORAGE_<INSTANCE>_CONNECTION_STRING |
environment | Storage account connection string. Optional: account_name with account_key, or the app’s Azure identity, is used when unset. | |
KIRAK_STORAGE_<INSTANCE>_ACCOUNT_KEY |
environment | Storage account access key, used with account_name. Optional: without it the app’s Azure identity (DefaultAzureCredential) is used. |
Scheduler
Section titled “Scheduler”The database provider requires no extra install – it uses your existing database. Redis and RabbitMQ providers require optional extras. Providers are declared in kirak.json under "scheduler" as named instances; only connection URLs are environment variables (prefix KIRAK_SCHEDULER_).
kirak.json settings
Section titled “kirak.json settings”{ "scheduler": { "default_provider": "db", "providers": { "db": { "type": "database" } }, "poll_interval": 5, "concurrency": 4, "default_queue": "default", "queues": ["emails"], "job_timeout": 3600, "max_retries": 3, "retry_backoff": 60 }}scheduler key |
Type | Description |
|---|---|---|
default_provider |
string | Instance name used when a call names no provider. Must be one of the instances under providers. |
providers |
object | Queue provider instances (types database, redis, rabbitmq, or a custom type), by instance name. At most one database entry. |
poll_interval |
integer | Seconds between queue polls (database and redis providers). Default 5. |
concurrency |
integer | Maximum jobs run in parallel per provider. Default 4. |
default_queue |
string | Queue used when enqueue() is given none. Always consumed. Default “default”. |
queues |
array | Extra queues to consume besides default_queue. Default []. |
job_timeout |
integer | Seconds a job may run before the worker stops and retries it. Default 3600. |
max_retries |
integer | Default maximum retry attempts per job. Default 3. |
retry_backoff |
integer | Base delay between retries in seconds, multiplied by the attempt number. Default 60. |
At most one database provider. A job still running 60 seconds past job_timeout is treated as orphaned by a crashed worker and put back in the queue. |
Providers: settings and secrets
Section titled “Providers: settings and secrets”Settings go in the provider entry in kirak.json; connection URLs are environment variables, one per instance: KIRAK_SCHEDULER_<INSTANCE>_URL, upper-cased. URLs in kirak.json are rejected.
<INSTANCE> is the provider instance’s name in kirak.json, upper-cased: an instance
named main reads ..._MAIN_....
database (no extra install) – Queue in the app’s own database. No extra install. At most one per project.
| Name | Where | Required / default | Description |
|---|---|---|---|
table |
kirak.json | default scheduler_jobs |
Deprecated. Must be scheduler_jobs if set; any other value fails at startup. |
redis (pip install "kirak[scheduler-redis]") – Queue in Redis (sorted sets).
Credential check (check()): Connect and PING.
| Name | Where | Required / default | Description |
|---|---|---|---|
redis_ssl |
kirak.json | default False |
Connect over TLS. |
KIRAK_SCHEDULER_<INSTANCE>_URL |
environment | Redis URL. Default redis://localhost:6379. |
rabbitmq (pip install "kirak[scheduler-rabbitmq]") – Queue in RabbitMQ.
Credential check (check()): Connect and open a channel.
| Name | Where | Required / default | Description |
|---|---|---|---|
KIRAK_SCHEDULER_<INSTANCE>_URL |
environment | AMQP URL. Default amqp://guest:guest@localhost/. |
Requires pip install "kirak[ai-openai]", pip install "kirak[ai-anthropic]", or pip install "kirak[ai-google]" depending on your provider. Models are "provider:model" strings: agents name theirs in the agent file, and default_model in kirak.json is the fallback. Embeddings are configured under vector, not here. API keys are not Kirak settings; each provider SDK reads its own standard environment variable.
kirak.json settings
Section titled “kirak.json settings”{ "ai": { "default_model": "openai:gpt-4o-mini", "conversation_ttl_seconds": 3600 }}ai key |
Type | Description |
|---|---|---|
default_model |
string | “provider:model” used when an agent or call names no model. |
conversation_ttl_seconds |
integer | Seconds a saved agent conversation is kept. Default 3600. |
compaction_token_threshold |
integer or null | Token count at which a long conversation is compacted. null turns compaction off. Default 150000. |
| How compaction works per provider is described in | ||
| AI Integration. For the calls that use | ||
| these settings, see AI Integration. |
Model providers and API keys
Section titled “Model providers and API keys”The API key variable is read by the provider’s SDK, not by Kirak.
| Provider | Model prefixes | Install | API key variable |
|---|---|---|---|
| openai | openai:, openai-responses: |
pip install "kirak[ai-openai]" |
OPENAI_API_KEY |
| anthropic | anthropic: |
pip install "kirak[ai-anthropic]" |
ANTHROPIC_API_KEY |
google-gla:, google: |
pip install "kirak[ai-google]" |
GOOGLE_API_KEY, GEMINI_API_KEY |
Vector
Section titled “Vector”Store and embedding providers for retrieval (RAG); see Vector. Two independent provider
sets, each declared like the other modules’ providers. Either may be left out (bring your own vectors and skip
embedding), but an enabled module needs at least one.
"vector": { "store": { "default_provider": "pine", "providers": { "pine": { "type": "pinecone", "cloud": "aws", "region": "us-east-1" }, "s3v": { "type": "s3_vectors", "bucket": "my-vector-bucket", "region": "us-east-1" } } }, "embedding": { "default_provider": "openai", "providers": { "openai": { "type": "openai", "model": "text-embedding-3-small" }, "google": { "type": "google", "model": "gemini-embedding-001" }, "local": { "type": "ollama", "model": "nomic-embed-text", "base_url": "http://localhost:11434" } } }}vector key |
Type | Description |
|---|---|---|
store |
object | Vector store providers (e.g. pinecone, s3_vectors). |
embedding |
object | Embedding providers (e.g. openai, google, ollama). |
Secrets are read from the environment, one set per instance: KIRAK_VECTOR_STORE_<INSTANCE>_<FIELD> and |
||
KIRAK_VECTOR_EMBEDDING_<INSTANCE>_<FIELD>, upper-cased. Secrets in kirak.json are rejected. AWS credentials for |
||
s3_vectors are optional: boto3’s default credential chain is used when unset (set both keys or neither). |
<INSTANCE> is the provider instance’s name in kirak.json, upper-cased: an instance
named main reads ..._MAIN_....
store / pinecone (no extra install) – Pinecone serverless indexes.
Credential check (check()): GET /indexes.
| Name | Where | Required / default | Description |
|---|---|---|---|
cloud |
kirak.json | default aws |
Cloud of new indexes. |
region |
kirak.json | default us-east-1 |
Region of new indexes. |
api_version |
kirak.json | default 2026-04 |
Pinecone API version. |
batch_size |
kirak.json | default 100 |
Vectors per upsert request (at most 1000). |
ready_timeout |
kirak.json | default 120 |
Seconds create_index waits for the index to be ready. |
max_retries |
kirak.json | default 3 |
Retries on rate limits and server errors. |
timeout |
kirak.json | default 30.0 |
Request timeout in seconds. |
KIRAK_VECTOR_STORE_<INSTANCE>_API_KEY |
environment | required | Pinecone API key. |
store / s3_vectors (pip install "kirak[vector-s3vectors]") – Amazon S3 Vectors indexes in an existing vector bucket.
Credential check (check()): GetVectorBucket on the configured bucket.
| Name | Where | Required / default | Description |
|---|---|---|---|
bucket |
kirak.json | required | Existing vector bucket. |
region |
kirak.json | required | Bucket region. |
non_filterable_metadata_keys |
kirak.json | Metadata keys stored but not usable in filters, for new indexes. | |
max_retries |
kirak.json | default 3 |
Retries on rate limits and server errors. |
KIRAK_VECTOR_STORE_<INSTANCE>_ACCESS_KEY_ID |
environment | AWS access key ID. Optional: boto3’s default credential chain is used when unset. | |
KIRAK_VECTOR_STORE_<INSTANCE>_SECRET_ACCESS_KEY |
environment | AWS secret access key. Set together with the access key ID. |
embedding / openai (no extra install) – OpenAI embeddings, or any OpenAI-compatible endpoint through base_url.
Credential check (check()): GET /models; the configured model must be listed.
| Name | Where | Required / default | Description |
|---|---|---|---|
model |
kirak.json | required | Embedding model name. |
base_url |
kirak.json | default https://api.openai.com/v1 |
API base URL. |
dimensions |
kirak.json | Output vector length, for models that can shorten it. | |
batch_size |
kirak.json | default 100 |
Texts per request (at most 2048). |
max_retries |
kirak.json | default 3 |
Retries on rate limits and server errors. |
timeout |
kirak.json | default 30.0 |
Request timeout in seconds. |
KIRAK_VECTOR_EMBEDDING_<INSTANCE>_API_KEY |
environment | required | OpenAI API key. |
embedding / google (no extra install) – Google Gemini embeddings.
Credential check (check()): GET /models/
| Name | Where | Required / default | Description |
|---|---|---|---|
model |
kirak.json | required | Embedding model name. |
dimensions |
kirak.json | Output vector length, for models that can shorten it. | |
batch_size |
kirak.json | default 100 |
Texts per request (at most 100). |
max_retries |
kirak.json | default 3 |
Retries on rate limits and server errors. |
timeout |
kirak.json | default 30.0 |
Request timeout in seconds. |
KIRAK_VECTOR_EMBEDDING_<INSTANCE>_API_KEY |
environment | required | Gemini API key. |
embedding / ollama (no extra install) – Embeddings from a local or self-hosted Ollama server.
Credential check (check()): GET /api/tags; the configured model must be pulled.
| Name | Where | Required / default | Description |
|---|---|---|---|
model |
kirak.json | required | Embedding model name. |
base_url |
kirak.json | default http://localhost:11434 |
Ollama server URL. |
batch_size |
kirak.json | default 100 |
Texts per request. |
max_retries |
kirak.json | default 3 |
Retries on rate limits and server errors. |
timeout |
kirak.json | default 30.0 |
Request timeout in seconds. |
Requires pip install "kirak[redis]".
| Variable | Description |
|---|---|
KIRAK_REDIS_URL |
Redis connection URL. When set, three DB-backed auth utilities are transparently replaced with Redis equivalents: rate limiting (sliding-window sorted set), token blacklist (per-key TTL), and OTP storage (per-key TTL). When not set, the database is used for all three. |
URL formats:
KIRAK_REDIS_URL=redis://localhost:6379 # no authKIRAK_REDIS_URL=redis://:password@host:6379 # with passwordKIRAK_REDIS_URL=rediss://host:6380 # TLS (note: rediss://)What changes:
| Feature | Without Redis | With Redis |
|---|---|---|
| Rate limiting (CRUD and auth endpoints) | DB fixed-window (kirak_rate_limits table) |
Redis sliding-window (more accurate, auto-expires) |
| Token blacklist | DB row (auth_token_blacklist table) |
Redis key + per-token TTL (auto-cleaned) |
| OTP storage | DB row (auth_otp table) |
Redis key + OTP expiry TTL (auto-cleaned) |
Redis utilities fail open: if Redis becomes unreachable, the request is allowed through rather than returning an error.
Runtime Behaviour
Section titled “Runtime Behaviour”The hook timeout, the log directory and the bulk chunk size are hook_timeout_seconds, log_path and bulk_chunk_size in kirak.json; the environment variables KIRAK_HOOK_TIMEOUT, LOG_PATH and KIRAK_BULK_CHUNK_SIZE are no longer read. bulk_chunk_size (default 500) is the maximum number of records per chunk for bulk create, update, delete, and destroy operations; reduce it if you hit database packet-size limits.
MCP Servers
Section titled “MCP Servers”Requires pip install "kirak[mcp]" (Python 3.10+). Enable with "modules": ["mcp"] in
kirak.json; there are no other kirak.json settings and no environment variables. Each
server is a JSON file in mcp/, described by .kirak/mcp.schema.json (kirak schema):
name, description, instructions, access, rate_limit_per_minute and a tools map
keyed by ref ("orders.fetch": {}). See MCP Servers.
Project Metadata
Section titled “Project Metadata”base_url and project_name are settings in kirak.json, not environment variables. base_url (for example https://api.example.com) is used to build links in auth emails (verification, password reset) and social login callbacks.
Environment Variables Kirak Reads
Section titled “Environment Variables Kirak Reads”Besides the provider secrets listed per module above. kirak env lists the ones a project needs, given its kirak.json, and whether each is set.
| Variable | Read by | Required | Secret | Purpose |
|---|---|---|---|---|
DB_PASSWORD |
core | yes | Database password; every other database setting is in kirak.json “database”. | |
KIRAK_REDIS_URL |
core | yes | Redis URL. When set, rate limiting, the token blacklist, OTP storage and model caching use Redis instead of the database. | |
KIRAK_AUTH_JWT_SECRET_KEY |
auth | yes | yes | Signs access tokens (at least 32 bytes). Also the fallback of the other auth secrets. |
KIRAK_AUTH_JWT_REFRESH_SECRET_KEY |
auth | yes | Signs refresh tokens. Default: KIRAK_AUTH_JWT_SECRET_KEY; set a separate one in production. | |
KIRAK_AUTH_JWT_OLD_SECRET_KEY |
auth | yes | Previous access-token key, during a key rotation, so tokens it signed stay valid until they expire. | |
KIRAK_AUTH_JWT_REFRESH_OLD_SECRET_KEY |
auth | yes | Previous refresh-token key, during a key rotation. Default: KIRAK_AUTH_JWT_OLD_SECRET_KEY. | |
KIRAK_AUTH_VERIFICATION_KEY |
auth | yes | yes | Fernet key signing email verification and password reset links. |
KIRAK_AUTH_ENCRYPTION_KEY |
auth | yes | Key encrypting social login tokens and MFA secrets. Default: derived from KIRAK_AUTH_JWT_SECRET_KEY, with a warning; set it in production. | |
KIRAK_AUTH_WEB_TOKEN_SECRET |
auth | yes | Signs short-lived Apple web sign-in state tokens. Default: KIRAK_AUTH_JWT_SECRET_KEY. | |
KIRAK_AUTH_API_KEY_SECRET |
auth | yes | Keys the stored hash of API keys, so rotating KIRAK_AUTH_JWT_SECRET_KEY does not invalidate them. Default: KIRAK_AUTH_JWT_SECRET_KEY; set it in production. Keys created before it was set keep working until the JWT secret changes. | |
KIRAK_MONITORING_INGESTION_KEY |
monitoring | yes | Bearer token required on every /monitoring/* endpoint except /monitoring/ping. Unset: those endpoints answer 503. | |
KIRAK_MONITORING_LOG_SHIP_SECRET |
monitoring | yes | Bearer token sent with the log batches posted to monitoring.log_ship_url. |
Complete .env Template
Section titled “Complete .env Template”# Secrets only. Database host and name, base URL, CORS origins, branding and# social client IDs are in kirak.json.
# -- Database ------------------------------------------------------DB_PASSWORD=
# -- Auth (required) -----------------------------------------------KIRAK_AUTH_JWT_SECRET_KEY=replace-with-32-byte-or-longer-secretKIRAK_AUTH_JWT_REFRESH_SECRET_KEY=another-32-byte-or-longer-secretKIRAK_AUTH_VERIFICATION_KEY=your-fernet-key-hereKIRAK_AUTH_ENCRYPTION_KEY=your-hex-key-here# token lifetimes, bcrypt_rounds and password_complexity are kirak.json "auth" settings, not env vars
# -- Social auth secrets -- set only the providers you use ----------# (client IDs and redirect URIs are kirak.json -> auth.social)# KIRAK_AUTH_GOOGLE_CLIENT_SECRET=# KIRAK_AUTH_GITHUB_CLIENT_SECRET=
# -- Notifications (credentials only -- provider/host/sender are kirak.json) --# KIRAK_NOTIFICATION_EMAIL_AWS_SES_ACCESS_KEY= # instance named "aws_ses"# KIRAK_NOTIFICATION_EMAIL_AWS_SES_SECRET_KEY=
# -- Payments --------------------------------------------------------# KIRAK_PAYMENT_STRIPE_SECRET_KEY=sk_live_...# KIRAK_PAYMENT_STRIPE_WEBHOOK_SECRET=whsec_...
# -- Storage (credentials only -- backend/dir are kirak.json) --------# KIRAK_STORAGE_MAIN_ACCESS_KEY= # instance named "main" (aws, wasabi, r2, spaces, cubbit, ovh, b2)# KIRAK_STORAGE_MAIN_SECRET_KEY=# KIRAK_STORAGE_GCS_CREDENTIALS_JSON= # instance named "gcs" (unset: Application Default Credentials)# KIRAK_STORAGE_BLOBS_CONNECTION_STRING= # instance named "blobs" (azure), or ..._ACCOUNT_KEY
# -- Scheduler (connection only -- providers/concurrency are kirak.json) --# KIRAK_SCHEDULER_REDIS_URL=redis://localhost:6379
# -- AI (API keys only -- provider/model are kirak.json) -------------# OPENAI_API_KEY=sk-...
# -- Vector (credentials only -- providers/models are kirak.json) ----# KIRAK_VECTOR_STORE_PINE_API_KEY= # store instance named "pine"# KIRAK_VECTOR_EMBEDDING_OPENAI_API_KEY= # embedding instance named "openai"
# -- Redis (optional -- enables sliding-window rate limit, etc.) ----# KIRAK_REDIS_URL=redis://localhost:6379// kirak.json -- non-secret settings for the modules above{ "modules": ["notifications", "payments", "storage", "scheduler", "ai"], "notifications": { "email_from_address": "no-reply@example.com", "email": { "default_provider": "ses", "providers": { "ses": { "type": "aws_ses" } } } }, "storage": { "default_provider": "local", "providers": { "local": { "type": "local", "upload_dir": "assets/media" } } }, "scheduler": { "default_provider": "db", "providers": { "db": { "type": "database" } }, "concurrency": 4 }, "ai": { "default_model": "openai:gpt-4o-mini" }}