Configuration
Configuration reference for Kestra.
Almost everything in Kestra is configurable. This page covers key options such as data sources, logging, security, and AI.
Kestra reads configuration from YAML. Provide it as an environment variable, a file, or inline in Docker Compose (see installation options). The configuration holds deployment-specific options and is divided into sections that map to system components:
datasources:
postgres:
url: jdbc:postgresql://postgres:5432/kestra
driver-class-name: org.postgresql.Driver
username: kestra
password: k3str4
kestra:
server:
basic-auth:
username: "[email protected]" # must be a valid email address
password: kestra
# Do not authenticate these URLs (some Micronaut defaults are open by default for security reasons)
open-urls:
- "/api/v1/main/executions/webhook/"
repository:
type: postgres
storage:
type: local
local:
base-path: "/app/storage"
queue:
type: postgres
tasks:
tmp-dir:
path: "/tmp/kestra-wd/tmp"
url: "http://localhost:8080/"
Environment variables override file-based config. Convert keys by replacing special characters with _
:
Configuration value | Resulting properties |
---|---|
MYAPP_MYSTUFF | myapp.mystuff , myapp-mystuff |
MY_APP_MY_STUFF | my.app.my.stuff , my.app.my-stuff , my-app.my.stuff , my-app.my-stuff , etc. |
Example: replace a config file entry
datasources:
postgres:
username: kestra
with an environment variable:
DATASOURCES_POSTGRES_USERNAME=kestra
For camelCase keys, use -
:
kestra:
storage:
s3:
access-key: myKey
becomes:
KESTRA_STORAGE_S3_ACCESS-KEY=myKey
Setup
Configure three core components during initial setup:
- Internal storage
- Queue
- Repository
Internal storage configuration
The default local storage writes to the host filesystem and suits only local testing (no resiliency). Configure another type by setting kestra.storage.type
and installing the corresponding storage plugin. Example for Google Cloud Storage:
kestra:
storage:
type: gcs
Queue configuration
Queues must be compatible with the repository type. Defaults depend on your architecture and installation.
Available types:
- In-memory (with in-memory repository) — for local testing
- Database (JDBC) — H2, MySQL, PostgreSQL
- Kafka (with Elasticsearch repository; Enterprise Edition)
Enable the PostgreSQL queue:
kestra:
queue:
type: postgres
Repository configuration
Repositories must match the queue type:
- In-memory — for local testing only; lacks resiliency/scalability and some features
- Database — H2, MySQL, or PostgreSQL
- Elasticsearch — with Kafka queue (Enterprise Edition)
Enable PostgreSQL repository:
kestra:
repository:
type: postgres
See database and Elasticsearch for details.
Database
Queue and repository
Set kestra.queue.type
and kestra.repository.type
to your database:
kestra:
queue:
type: postgres
repository:
type: postgres
Supported: PostgreSQL, H2, MySQL.
Use H2 for local development. For production, use PostgreSQL (or MySQL if PostgreSQL isn’t an option).
See software requirements for minimum versions.
For PostgreSQL performance issues, consider random_page_cost=1.1
to improve index usage on queue queries. You can also set kestra.queue.postgres.disable-seq-scan=true
to force index usage on polling.
Datasources
After setting repository/queue types, configure datasources
. Kestra uses HikariCP; all Hikari options can be set here.
Connection pool size
Each Kestra instance opens up to maximum-pool-size
connections (default 10), with minimum-idle
(default 10).
- Standalone server: ~10 connections
- Split components: ~40 (10 per component)
- Split components with 3 replicas: ~120
Defaults generally suffice.
Datasources
HikariCP properties:
Property | Type | Description |
---|---|---|
url | String | JDBC connection string |
catalog | String | Default catalog |
schema | String | Default schema |
username | String | Default username |
password | String | Default password |
transaction-isolation | String | Default isolation level |
pool-name | String | Pool name |
connection-init-sql | String | SQL run on new connections |
connection-test-query | String | Validation query |
connection-timeout | Long | Max wait for a connection (ms) |
idle-timeout | Long | Max idle time (ms) |
minimum-idle | Long | Minimum idle connections (defaults to maximum-pool-size ) |
initialization-fail-timeout | Long | Initialization failure timeout |
leak-detection-threshold | Long | Leak detection threshold (ms) |
maximum-pool-size | Int | Pool size (default 10) |
max-lifetime | Long | Max connection lifetime (ms) |
validation-timeout | Long | Max validation time (ms) |
Defaults:
transaction-isolation: default
pool-name: HikariPool-<Generated>
connection-init-sql: null
connection-test-query: null
connection-timeout: 30000
idle-timeout: 600000
minimum-idle: 10
initialization-fail-timeout: 1
leak-detection-threshold: 0
maximum-pool-size: 10
max-lifetime: 1800000
validation-timeout: 5000
JDBC queues
Kestra’s JDBC queues long-poll the queues
table. Lower intervals reduce latency but increase DB load.
kestra.jdbc.queues.poll-size
kestra.jdbc.queues.min-poll-interval
kestra.jdbc.queues.max-poll-interval
kestra.jdbc.queues.poll-switch-interval
Defaults:
kestra:
jdbc:
queues:
poll-size: 100
min-poll-interval: 25ms
max-poll-interval: 1000ms
poll-switch-interval: 5s
JDBC cleaner
Cleans queues
periodically:
kestra:
jdbc:
cleaner:
initial-delay: 1h
fixed-delay: 1h
retention: 7d
initial-delay
: when to startfixed-delay
: how oftenretention
: oldest entries to keep
Protecting against large messages
Experimental (>= 0.19).
Reject oversize messages to protect memory:
kestra:
jdbc:
queues:
message-protection:
enabled: true
limit: 1048576 # 1 MiB
Telemetry
Anonymous usage reporting is enabled by default; see details.
Disable:
kestra:
anonymous-usage-report:
enabled: false
Adjust timings:
kestra:
anonymous-usage-report:
initial-delay: 5m
fixed-delay: 1h
UI usage:
kestra:
ui-anonymous-usage-report:
enabled: false
Elasticsearch
Enterprise Edition only.
Minimal config:
kestra:
elasticsearch:
client:
http-hosts: "http://localhost:9200"
repository:
type: elasticsearch
With basic auth:
kestra:
elasticsearch:
client:
http-hosts:
- "http://node-1:9200"
- "http://node-2:9200"
- "http://node-3:9200"
basic-auth:
username: "<your-user>"
password: "<your-password>"
repository:
type: elasticsearch
Trust all SSL certificates
Useful for dev/self-signed certs:
kestra:
elasticsearch:
client:
http-hosts: "https://localhost:9200"
trust-all-ssl: true
Indices prefix
Change index prefix (default kestra_
):
kestra:
elasticsearch:
defaults:
indice-prefix: "uat_kestra"
Indices split
Split large indices by periodicity (DAILY
, WEEKLY
, MONTHLY
, YEARLY
):
kestra:
elasticsearch:
indices:
executions:
alias: daily
logs:
alias: daily
metrics:
alias: daily
Index rotation
Enables aliases and rotating indices (name-periodicity-1
). Move existing indices (e.g., kestra_logs
→ kestra_logs-1
) before switching. Purge only safe historical indices (logs, metrics, executions). Switching periodicity is safe; aliases match name-*
.
EE Java security
Opt in to EE Java security for filesystem and class restrictions:
kestra:
ee:
java-security:
enabled: true
forbidden-paths:
- /etc/
authorized-class-prefix:
- io.kestra.plugin.core
- io.kestra.plugin.gcp
- Forbidden paths: disallow read/write on listed paths.
- Authorized class prefix: classes allowed to create threads.
- Forbidden class prefix: classes blocked from creating threads:
kestra:
ee:
java-security:
enabled: true
forbidden-class-prefix:
- io.kestra.plugin.scripts
EE license
Provide a valid EE license:
kestra:
ee:
license:
id: <LICENSE ID>
fingerprint: <LICENSE FINGERPRINT>
key: |
<LICENSE KEY>
The license is set up using three configuration properties: id
, fingerprint
, and key
.
kestra.ee.license.id
: license identifier.kestra.ee.license.fingerprint
: license authentication. This is required for using Versioned Plugins.kestra.ee.license.key
: license key.
Kestra validates the license on startup.
EE sidebar configuration
Right sidebar: custom links
kestra:
ee:
right-sidebar:
custom-links:
internal-docs:
title: "Internal Docs"
url: "https://kestra.io/docs/"
support-portal:
title: "Support portal"
url: "https://kestra.io/support/"
The right-sidebar syntax changed after 0.24.0; update older configs.
Left sidebar: disable menus
kestra:
ee:
left-sidebar:
disabled-menus:
- "Blueprints/Flow Blueprints"
- "Blueprints/Dashboard Blueprints"
- "Blueprints/App Blueprints"
Multi-tenancy
Removed in 0.23. See the 0.23 migration guide.
Enable (pre-0.23):
kestra:
ee:
tenants:
enabled: true
Default tenant
Removed in 0.23. See the 0.23 migration guide.
Disable the default tenant when multi-tenancy is on:
kestra:
ee:
tenants:
enabled: true
default-tenant: false
Encryption
Kestra 0.15.0+ supports encryption of sensitive data (inputs/outputs) at rest. Provide a base64-encoded 32-character key:
kestra:
encryption:
secret-key: BASE64_ENCODED_STRING_OF_32_CHARCTERS
Generate with OpenSSL:
openssl rand -base64 32
Or with Bash:
random_string=$(LC_ALL=C tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 32)
echo "$random_string" | base64
Docker Compose example:
kestra:
image: kestra/kestra:latest
environment:
KESTRA_CONFIGURATION: |
kestra:
encryption:
secret-key: NWRhUDc5TERWY2QyMDhSSHhfeWYzbjJpNE5vb3M5NnY=
Use SECRET
input/output types:
id: my_secret_flow
namespace: company.team
inputs:
- id: secret
type: SECRET
tasks:
- id: mytask
type: io.kestra.plugin.core.log.Log
message: task that needs the secret to connect to an external system
outputs:
- id: secret_output
type: SECRET
value: "{{ inputs.secret }}"
Without kestra.encryption.secret-key
, SECRET
types throw:Illegal argument: Unable to use a SECRET input as encryption is not configured
.
Endpoints
Secure Micronaut endpoints with basic auth:
endpoints:
all:
basic-auth:
username: your-user
password: your-password
Change management port:
endpoints:
all:
port: 8084
Environment
Display an environment badge in the UI:
kestra:
environment:
name: Production
color: "#FCB37C"
You can also set this via the UI Settings page.
JVM
Set JVM options with JAVA_OPTS
:
export JAVA_OPTS="-user.timezone=Europe/Paris"
Proxy example (see Java docs):
JAVA_OPTS=-Dhttp.proxyHost=10.0.0.100 -Dhttp.proxyPort=8800
Timezone
Kestra uses the system timezone by default. Change with user.timezone
. Affects scheduling and log display.
Memory
Kestra defaults to -XX:MaxRAMPercentage=50.0
. Alternatively, set a fixed heap with -Xmx
, e.g., -Xmx1g
.
Indexer
Controls bulk indexing from Kafka to Elasticsearch:
kestra:
indexer:
batch-size: 500
batch-duration: PT1S
Larger values reduce load but delay UI updates.
Kafka
You can set up your Kafka connection using the kestra.kafka
configuration. Enterprise Edition only.
Client properties
Minimal:
kestra:
kafka:
client:
properties:
bootstrap.servers: "localhost:9092"
queue:
type: kafka
With SSL:
kestra:
kafka:
client:
properties:
bootstrap.servers: "host:port"
security.protocol: "SSL"
ssl.endpoint.identification.algorithm: ""
ssl.key.password: "<your-password>"
ssl.keystore.location: "/etc/ssl/private/keystore.p12"
ssl.keystore.password: "<your-password>"
ssl.keystore.type: "PKCS12"
ssl.truststore.location: "/etc/ssl/private/truststore.jks"
ssl.truststore.password: "<your-password>"
queue:
type: kafka
kestra.kafka.client.properties
accepts any Kafka property (see Kafka docs).
Topics
Defaults can be tuned:
kestra.kafka.defaults.topic.partitions
(default 16)kestra.kafka.defaults.topic.replication-factor
(default 1)
The number of topic's partitions limits the number of concurrently processing server instances consuming that particular topic. For example, using 16 partitions for every topic limits the effective number of instances to 16 executor servers, 16 worker servers, etc.
Set replication factor per your cluster. For 3 brokers, use 3 for HA.
Consumer, producer, and stream defaults
You can change the default properties of the Kafka client used by Kestra using the kestra.kafka.defaults.[consumer|producer|stream].properties
configuration. These allow you to change any available properties.
kestra:
kafka:
defaults:
consumer:
properties:
isolation.level: "read_committed"
auto.offset.reset: "earliest"
enable.auto.commit: "false"
producer:
properties:
acks: "all"
compression.type: "lz4"
max.request.size: "10485760"
stream:
properties:
processing.guarantee: "exactly_once"
replication.factor: "${kestra.kafka.defaults.topic.replication-factor}"
acks: "all"
compression.type: "lz4"
max.request.size: "10485760"
state.dir: "/tmp/kafka-streams"
Topic names and properties
Rename topics or set per-topic properties via kestra.kafka.defaults.topics
. See defaults in the project’s application.yml
.
kestra.kafka.defaults.topics.{{topic}}.name
: Change the name of the topic.kestra.kafka.defaults.topics.{{topic}}.properties
: Change the default properties used during topic automatic creation.
Consumer prefix
Change consumer group prefix (default kestra
) for multi-instance clusters:
kestra:
kafka:
defaults:
consumer-prefix: "uat_kestra"
Topic prefix
Change topic prefix (default kestra_
):
kestra:
kafka:
defaults:
topic-prefix: "uat_kestra"
Client loggers
Enable message logging for debugging:
kestra:
kafka:
client:
loggers:
- level: INFO
type: PRODUCER
topic-regexp: "kestra_(executions|workertaskresult)"
key-regexp: .*parallel.*
value-regexp: .*parallel.*
Heavy performance impact; use sparingly.
Kafka Streams state directory
kestra.kafka.stream.properties.state-dir
sets local state. Default: /tmp/kafka-streams
. Persisting reduces startup time. Purge before upgrades if needed.
Topic retention
Set on a per-topic basis:
kestra:
kafka:
topics:
execution:
properties:
retention.ms: "86400000"
Protecting against large messages
This is an Experimental feature.
Store oversize messages in internal storage to avoid failures:
kestra:
kafka:
message-protection:
enabled: true
Listeners
Deprecated and disabled since 0.11.0. Re-enable if needed:
kestra:
listeners:
enabled: true
Logger
Server log
Adjust log levels:
logger:
levels:
io.kestra.core.runners: TRACE
org.opensearch.client.RestClient: DEBUG
org.apache.http: DEBUG
org.apache.http.wire: DEBUG
org.apache.kafka: DEBUG
io.netty.handler.logging: TRACE
Disable flow execution logs in server logs:
logger:
levels:
flow: 'OFF'
Disable logs for a specific flow:
logger:
levels:
flow.hello-world: 'OFF'
Execution-related loggers:
execution
: flow start/endtask
: task run start/endtrigger
: trigger evaluation start/end
Disable globally:
logger:
levels:
execution: 'OFF'
task: 'OFF'
trigger: 'OFF'
Or per flow:
logger:
levels:
execution.hello-world: 'OFF'
task.hello-world: 'OFF'
trigger.hello-world: 'OFF'
Access log configuration
micronaut:
server:
netty:
access-logger:
enabled: true
logger-name: io.kestra.webserver.access
log-format: "[Date: {}] [Duration: {} ms] [Method: {}] [Url: {}] [Status: {}] [Length: {}] [Ip: {}] [Port: {}]"
exclusions:
- /ui/.+
- /health
- /prometheus
Log format
Kestra uses Logback. Customize via a logback.xml
on the classpath and set:
JAVA_OPTS="-Dlogback.configurationFile=file:/path/to/logback.xml"
GCP example
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<include resource="logback/base.xml" />
<include resource="logback/gcp.xml" />
<root level="WARN">
<appender-ref ref="CONSOLE_JSON_OUT" />
<appender-ref ref="CONSOLE_JSON_ERR" />
</root>
</configuration>
ECS format example
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
<include resource="logback/base.xml" />
<include resource="logback/ecs.xml" />
<root level="WARN">
<appender-ref ref="CONSOLE_ECS_OUT" />
<appender-ref ref="CONSOLE_ECS_ERR" />
</root>
</configuration>
Metrics
Set a global prefix:
kestra:
metrics:
prefix: kestra
Micronaut
Kestra runs on Micronaut. See the Micronaut guide for all options. Highlights:
Configure port
micronaut:
server:
port: 8086
Configure SSL
This guide will help you configure SSL with Micronaut.
Example (passwords via env vars):
micronaut:
security:
x509:
enabled: true
ssl:
enabled: true
server:
ssl:
client-authentication: need
key-store:
path: classpath:ssl/keystore.p12
password: ${KEYSTORE_PASSWORD}
type: PKCS12
trust-store:
path: classpath:ssl/truststore.jks
password: ${TRUSTSTORE_PASSWORD}
type: JKS
Timeout and max upload size
micronaut:
server:
max-request-size: 10GB
multipart:
max-file-size: 10GB
disk: true
read-idle-timeout: 60m
write-idle-timeout: 60m
idle-timeout: 60m
netty:
max-chunk-size: 10MB
Changing base path
If behind a reverse proxy, you can change the base path of the application with the following configuration:
micronaut:
server:
context-path: "kestra-prd"
Changing host resolution
If behind a reverse proxy, you can change host resolution (http/https/domain name) providing the header sent by your reverse proxy:
micronaut:
server:
host-resolution:
host-header: Host
protocol-header: X-Forwarded-Proto
Configuring CORS
micronaut:
server:
cors:
enabled: true
For finer control, see the CORS docs.
Configure local flow synchronization
micronaut:
io:
watch:
enabled: true
paths:
- /path/to/your/flows
See the local flow sync guide.
Plugins
Installing plugins
Install from Maven repositories with:
kestra plugins install io.kestra.plugin:plugin-script-python:LATEST
By default Kestra uses Maven Central; add more repositories if needed.
Adding custom Maven repositories
kestra:
plugins:
repositories:
central:
url: https://repo.maven.apache.org/maven2/
google-artifact-registry:
url: https://${GCP_REGISTRY_LOCATION}-maven.pkg.dev/${GCP_PROJECT_ID}/${GCP_REPOSITORY}
basic-auth:
username: oauth2accesstoken
password: ${GCP_OAUTH_ACCESS_TOKEN}
Installing EE plugins
kestra:
plugins:
repositories:
kestra-io:
url: https://registry.kestra.io/maven
basic-auth:
username: ${kestra.ee.license.id:}
password: ${kestra.ee.license.fingerprint:}
Plugin defaults
Apply global defaults that flows can override:
kestra:
plugins:
defaults:
- type: io.kestra.plugin.core.log.Log
values:
level: ERROR
Defaults are evaluated by the Executor and propagated to all components. Keep a single, unified kestra.plugins.defaults
across servers; workers do not render templates themselves.
For finer control, use flow-level pluginDefaults
.
See Plugin defaults.
Forced plugin defaults
Force non-overridable values:
kestra:
plugins:
defaults:
- type: io.kestra.plugin.scripts.shell.Commands
forced: true
values:
containerImage: ubuntu:latest
taskRunner:
type: io.kestra.plugin.scripts.runner.docker.Docker
Enable or disable features
Some plugin features can be enabled globally:
kestra:
plugins:
configurations:
- type: io.kestra.plugin.core.flow.Subflow
values:
outputs:
enabled: true
- type: io.kestra.plugin.core.flow.Flow
values:
outputs:
enabled: true
Set default values
Set defaults for features not exposed in flow properties, e.g., default missed schedule recovery:
kestra:
plugins:
configurations:
- type: io.kestra.plugin.core.trigger.Schedule
values:
recoverMissedSchedules: NONE # ALL | NONE | LAST
Override in a flow:
triggers:
- id: schedule
type: io.kestra.plugin.core.trigger.Schedule
cron: "*/15 * * * *"
recoverMissedSchedules: LAST
Volume enabled for Docker task runner
Disabled by default; enable if needed:
kestra:
plugins:
configurations:
- type: io.kestra.plugin.scripts.runner.docker.Docker
values:
volumeEnabled: true
Allowed plugins
Enterprise Edition (>= 0.19).
Restrict plugins via include/exclude regex:
kestra:
plugins:
security:
includes:
- io.kestra.*
excludes:
- io.kestra.plugin.core.debug.Echo
Plugin management
(>= 0.22.0)
kestra:
plugins:
management:
enabled: true
remote-storage-enabled: true
custom-plugins-enabled: true
local-repository-path: /tmp/kestra/plugins-repository
auto-reload-enabled: true
auto-reload-interval: 60s
default-version: LATEST
remote-storage-enabled
: store managed plugins in internal storageauto-reload-enabled
/auto-reload-interval
: periodic refreshdefault-version
:latest
,current
,oldest
,none
, or a specific version
Retries
APIs for storage and secret managers can fail transiently. Configure global retries:
kestra.retries.attempts
(default5
)kestra.retries.delay
(default1s
)kestra.retries.max-delay
(defaultundefined
)kestra.retries.multiplier
(default2.0
)
These retries cover internal storage and secret managers, not tasks.
To set task-level retries globally, use plugin defaults:
- type: io.kestra
retry:
type: constant
interval: PT5M
maxDuration: PT1H
maxAttempts: 3
warningOnRetry: true
Secret managers
Configure a secrets backend via kestra.secret
. To isolate from specific services, use kestra.secret.isolation
.
kestra:
secret:
type: azure-key-vault
azure-key-vault:
client-secret:
tenant-id: "id"
client-id: "id"
client-secret: "secret"
isolation: # >= 0.22
enabled: true
denied-services:
- EXECUTOR
If configured in the UI, top-level keys are implied. Example UI screenshot:
AWS Secrets Manager
Ensure permissions: CreateSecret
, DeleteSecret
, DescribeSecret
, GetSecretValue
, ListSecrets
, PutSecretValue
, RestoreSecret
, TagResource
, UpdateSecret
.
kestra:
secret:
type: aws-secret-manager
aws-secret-manager:
access-key-id: mysuperaccesskey
secret-key-id: mysupersecret-key
session-token: mysupersessiontoken
region: us-east-1
Azure Key Vault
Grant the service principal (client-id
) permissions: "Get","List","Set","Delete","Recover","Backup","Restore","Purge"
.
kestra:
secret:
type: azure-key-vault
azure-key-vault:
client-secret:
tenant-id: "id"
client-id: "id"
client-secret: "secret"
Elasticsearch
Secrets are additionally encrypted with AES. Provide a 32-char minimum key:
kestra:
secret:
type: elasticsearch
elasticsearch:
secret: "a-secure-32-character-minimum-key"
Google Secret Manager
Grant roles/secretmanager.admin
. Paste the service account JSON or use GOOGLE_APPLICATION_CREDENTIALS
.
kestra:
secret:
type: google-secret-manager
google-secret-manager:
project: gcp-project-id
service-account: |
<service-account JSON>
HashiCorp Vault (KV v2)
Supported auth methods: Userpass, Token, AppRole.
kestra:
secret:
type: vault
vault:
address: "http://localhost:8200"
password:
user: john
password: foo
cache:
enabled: true
maximum-size: 1000
expire-after-write: 60s
kestra:
secret:
type: vault
vault:
address: "http://localhost:8200"
token:
token: your-secret-token
kestra:
secret:
type: vault
vault:
address: "http://localhost:8200"
app-role:
path: approle
role-id: your-role-id
secret-id: your-secret-id
JDBC
kestra:
secret:
type: jdbc
jdbc:
secret: "your-secret-key"
Secret tags
kestra:
secret:
<secret-type>:
tags:
application: kestra-production
Secret cache
kestra:
secret:
cache:
enabled: true
maximum-size: 1000
expire-after-write: 60s
Security
Using the kestra.security
configuration, you can set up multiple security features of Kestra.
Super-admin
The Super-admin has the highest privileges.
kestra:
security:
super-admin:
username: your_username
password: ${KESTRA_SUPERADMIN_PASSWORD}
tenant-admin-access:
- <optional>
Never store clear-text passwords in config. Use environment variables.
Default role
Assign a default role to new users (not service accounts):
kestra:
security:
default-role:
name: default
description: "Default role"
permissions:
FLOW: ["CREATE", "READ", "UPDATE", "DELETE"]
With multi-tenancy, restrict to one tenant:
kestra:
security:
default-role:
name: default
description: "Default role"
permissions:
FLOW: ["CREATE", "READ", "UPDATE", "DELETE"]
tenant-id: staging
Place this under kestra.security
, not micronaut.security
.
Invitation expiration
Default is 7 days. Change with:
kestra:
security:
invitations:
expire-after: P30D
Basic authentication password rules
Enforce password complexity:
kestra:
security:
basic-auth:
password-regexp: "<regexp-rule>"
Server
HTTP basic authentication
Protect an open-source instance with basic auth:
kestra:
server:
basic-auth:
enabled: true
username: admin
password: kestra
For multi-user auth (SSO, RBAC), see the Enterprise authentication page.
Delete configuration files
Delete configuration files after startup to prevent tasks from reading secrets:
kestra:
configurations:
delete-files-on-start: true
Server liveness & heartbeats
Kestra servers send heartbeats for liveness.
kestra.server.liveness.enabled
(Boolean, default true
)
kestra.server.liveness.interval
(Duration, default 5s
)
kestra.server.liveness.timeout
(Duration, default 45s
)
Must match across all Executors.
kestra.server.liveness.initial-delay
(Duration, default 45s
)
Must match across all Executors.
kestra.server.liveness.heartbeat-interval
(Duration, default 3s
)
Must be strictly less than timeout
.
Recommended (JDBC / OSS):
kestra:
server:
liveness:
enabled: true
interval: 5s
timeout: 45s
initial-delay: 45s
heartbeat-interval: 3s
Recommended (Kafka / EE):
kestra:
server:
liveness:
timeout: 1m
initial-delay: 1m
Worker liveness in Kafka mode is handled by Kafka’s protocol guarantees.
Prior to 0.16.0
Workers only; Executors marked workers unhealthy by heartbeat thresholds.
Heartbeat frequency
Workers send heartbeats every kestra.heartbeat.frequency
(default 10s
).
Heartbeat missed
Executors consider a worker DEAD
after kestra.heartbeat.heartbeat-missed
intervals (default 3
).
Worker task restart strategy (>= 0.16.0)
kestra.server.worker-task-restart-strategy
: NEVER
| IMMEDIATELY
| AFTER_TERMINATION_GRACE_PERIOD
(default).
Termination grace period
Upon SIGTERM
, servers try to stop gracefully. Default:
kestra:
server:
termination-grace-period: 5m
Internal storage
Default local storage (not for production):
kestra:
storage:
type: local
local:
base-path: /tmp/kestra/storage/
Other backends:
Isolate storage to specific services (>= 0.22):
kestra:
storage:
type: gcs
isolation:
enabled: true
denied-services:
- EXECUTOR
Screenshot example:
S3
Install plugin:
./kestra plugins install io.kestra.storage:storage-s3:LATEST
Configure:
kestra:
storage:
type: s3
s3:
endpoint: "<your-s3-endpoint>" # only for self-hosted S3
access-key: "<your-aws-access-key-id>"
secret-key: "<your-aws-secret-access-key>"
region: "<your-aws-region>"
bucket: "<your-s3-bucket-name>"
force-path-style: "<true|false>"
For EC2/EKS with IAM roles, omit keys:
kestra:
storage:
type: s3
s3:
region: "<your-aws-region>"
bucket: "<your-s3-bucket-name>"
More options in the S3 plugin source.
Assume role (STS)
kestra:
storage:
type: s3
s3:
region: "<your-aws-region>"
bucket: "<your-s3-bucket-name>"
sts-role-arn: "<role-arn>"
sts-role-external-id: "<optional>"
sts-role-session-name: "<optional>"
sts-role-session-duration: "<optional>"
sts-endpoint-override: "<optional>"
MinIO
Install plugin and set endpoint/port:
kestra:
storage:
type: minio
minio:
endpoint: my.domain.com
port: 9000
secure: false
access-key: ${AWS_ACCESS_KEY_ID}
secret-key: ${AWS_SECRET_ACCESS_KEY}
region: "default"
bucket: my-bucket
part-size: 5MB
If MinIO is configured with MINIO_DOMAIN
, use virtual host syntax via kestra.storage.minio.vhost: true
. Keep endpoint
as base domain (my.domain.com
), not bucket.domain
.
Azure
Install plugin:
./kestra plugins install io.kestra.storage:storage-azure:LATEST
Configure one of the auth methods:
kestra:
storage:
type: azure
azure:
endpoint: "https://unittestkt.blob.core.windows.net"
container: storage
connection-string: "<connection-string>"
shared-key-account-name: "<name>"
shared-key-account-access-key: "<access-key>"
sas-token: "<sas-token>"
Disable Hierarchical namespace on the container (not supported).
GCS
Install plugin:
./kestra plugins install io.kestra.storage:storage-gcs:LATEST
Configure:
kestra:
storage:
type: gcs
gcs:
bucket: "<bucket>"
project-id: "<project-id>"
service-account: "<JSON or use default credentials>"
If not set, default credentials are used (GKE/GCE). Alternatively, set GOOGLE_APPLICATION_CREDENTIALS
. You can find more details in the GCP documentation.
System flows
Reserve system
for background workflows. Change the namespace name:
kestra:
system-flows:
namespace: system
Tasks
Temporary storage
Change the temporary directory used during task processing:
kestra:
tasks:
tmp-dir:
path: /home/kestra/tmp
Match volume mounts:
volumes:
- kestra-data:/app/storage
- /var/run/docker.sock:/var/run/docker.sock
- /home/kestra:/home/kestra
Tutorial flows
Disable in production:
kestra:
tutorial-flows:
enabled: false
Enabling templates
Templates are deprecated and disabled by default since 0.11.0. Re-enable:
kestra:
templates:
enabled: true
Kestra URL
Some notifications require kestra.url
to link back to the UI/API. Use the full URI without /ui
or /api
:
kestra:
url: https://www.my-host.com/kestra/
Variables
Environment variables prefix
Expose environment variables to flows. By default, Kestra reads variables starting with ENV_
and exposes them as {{ envs.name }}
(lowercase, without prefix).
kestra:
variables:
env-vars-prefix: ENV_
Docker Compose example:
kestra:
image: kestra/kestra:latest
environment:
ENV_MY_VARIABLE: extra variable value
ENV_NEW_VARIABLE: new variable value
KESTRA_CONFIGURATION:
kestra:
variables:
env-vars-prefix: "ENV_"
ENV_MY_VARIABLE
→ {{ envs.my_variable }}
.
Global variables
Define globals accessible in all flows:
kestra:
variables:
globals:
host: pg.db.prod
Camel case becomes hyphenated.
Recursive rendering
Restore pre-0.14.0 behavior (defaults to false
):
kestra:
variables:
recursive-rendering: true
Template cache
Template rendering is CPU-intensive; keep caching enabled by default. Disable if required:
kestra:
variables:
cache-enabled: false
Set cache size:
kestra:
variables:
cache-size: 1000
Webserver
Google Analytics ID
kestra:
webserver:
google-analytics: UA-12345678-1
Append HTML tags to the application
Inject CSS/JS into the web UI:
kestra:
webserver:
html-head: |
<style type="text/css">
.v-sidebar-menu .logo:after {
background: var(--danger);
display: block;
content: "Local";
position: relative;
text-transform: uppercase;
bottom: -65px;
text-align: center;
color: var(--white-always);
}
</style>
Configuring a mail server
(EE) Used for invitations and password resets:
kestra:
ee:
mail-service:
host: host.smtp.io
port: 587
username: user
password: password
from: [email protected]
from-name: Kestra
auth: true
starttls-enable: true
Store execution data in internal storage
Available on:
>=0.23Enterprise EditionCloudStore workflow inputs/outputs in internal storage (per tenant/namespace) for isolation:
kestra:
ee:
execution-data:
internal-storage:
enabled: true
Enforce globally:
kestra:
ee:
execution-data:
internal-storage:
force-globally: true
Currently, outputs are not auto-fetched from internal storage in the UI; preview or download them instead.
Configure per namespace/tenant via the UI.
Add custom links to Kestra UI (EE)
Add sidebar links:
kestra:
ee:
custom-links:
link1:
title: "Internal Documentation"
url: "https://kestra.io/docs/"
link2:
title: "Internal Support Portal"
url: "https://kestra.io/support/"
Allowed file paths
To use the universal file access protocol, bind-mount the host directory and allow it in config:
kestra:
image: kestra/kestra:latest
volumes:
- /Users/yourdir/scripts:/scripts
environment:
KESTRA_CONFIGURATION: |
kestra:
local-files:
allowed-paths:
- /scripts
Disable local file preview (default true
) with kestra.local-files.enable-preview: false
.
AI Copilot
Enable Copilot in the flow editor:
kestra:
ai:
type: gemini
gemini:
model-name: gemini-2.5-flash
api-key: YOUR_GEMINI_API_KEY
Optional parameters:
temperature
,top-p
,top-k
,max-output-tokens
log-requests
,log-responses
base-url
Enterprise Edition supports multiple providers (Bedrock, Anthropic, Azure OpenAI, DeepSeek, Gemini, Vertex AI, Mistral, OpenAI, and Ollama). See AI Copilot.
Was this page helpful?