Configure Isolated Namespaces with Secrets and Plugin Defaults

For the complete documentation index, see llms.txt. For a full content snapshot, see llms-full.txt. Append .md to any kestra.io/docs/* URL for plain Markdown.

Available on:Enterprise EditionCloud

Namespaces provide an additional layer of isolation for secrets, variables, and plugin defaults within a tenant.

Namespace management — secure configuration

Kestra is a multi-tenant platform. Each tenant can have multiple Namespaces, and each Namespace provides additional isolation and security.

Namespaces provide:

  • Logical isolation of resources on top of instance- or tenant-level isolation
  • Fine-grained access control for secrets, variables, and task configurations

Namespaces are particularly useful in environments with many users, teams, projects, and applications.

Namespace-level features

The Namespace page allows you to configure secrets, plugin defaults, and variables that can be used within any flow in that Namespace.

It allows your organization to centrally manage your secrets, variables, and task configuration while providing fine-grained access-control to those resources.

Since Kestra supports everything as code and from the UI, you can manage Namespaces from the UI or programmatically (e.g., via our Terraform provider).

Secrets

Secrets are managed from the Secrets tab on the namespace page. Each secret has a key and value; action buttons on each row edit or delete it. Secrets are referenced in flows using "{{ secret('KEY_NAME') }}".

For APIs that issue short-lived access tokens (e.g., OAuth2), a Credential built on these secrets provides a token via {{ credential('your_credential_key') }}.

Example usage in a flow:

id: query-mysql
namespace: company.team
tasks:
- id: query
type: io.kestra.plugin.jdbc.mysql.Query
url: jdbc:mysql://localhost:3306/test
username: root
password: "{{ secret('MYSQL_PASSWORD') }}"
sql: select * from employees
fetchOne: true

When building new flows in a Namespace, Namespace secrets are accessible from the Secrets tab. Open the tab to view all available Namespace secret key names.

Policies

Policies can be defined at the Namespace level to inject, restrict, or validate configuration for all flows in the Namespace. Policies are managed from the Policies tab on the namespace page.

Policies can reference secrets and variables defined in the same Namespace.

For example, a namespace-scoped Policy can inject database credentials into every MySQL task so flows don’t need to declare them individually:

id: mysql-credentials
description: "Inject MySQL credentials for all MySQL tasks in this namespace."
enforcement: ACTIVE
rules:
- type: io.kestra.plugin.ee.rules.Add
on: PLUGIN
where:
- field: type
operator: STARTS_WITH
value: io.kestra.plugin.jdbc.mysql
values:
url: jdbc:mysql://localhost:3306/test
username: root
password: "{{ secret('MYSQL_PASSWORD') }}"

With this Policy applied, flows in the Namespace need no credentials on the task:

id: query-mysql
namespace: company.team
tasks:
- id: query
type: io.kestra.plugin.jdbc.mysql.Query
sql: select * from employees
fetchOne: true

Namespace-level Policies are inherited by child Namespaces. A Policy created in a parent Namespace applies to all flows in the parent and every child Namespace under it. See Policies for the full DSL reference, enforcement modes, and inheritance behavior.

Default service account for SDK plugins

Namespaces can now provide default authentication credentials that SDK-based plugins use to run tasks such as List all Namespaces. This allows tasks relying on the Kestra SDK to call the API without hard-coding credentials inside the flow.

On the Namespace Edit page, open the Default authentication section and choose either:

  • API token (recommended), or
  • Basic auth (username/password)

Variables

Variables defined at the Namespace level can be used in any flow defined under the same Namespace using the syntax: {{ namespace.variable_name }}.

Variables are managed from the Variables tab on the namespace page.

Example flow using a namespace variable:

id: query-mysql
namespace: company.team
tasks:
- id: query
type: io.kestra.plugin.jdbc.mysql.Query
url: jdbc:mysql://localhost:3306/test
username: "{{ namespace.mysql_user }}"
sql: select * from employees
fetchOne: true

When building new flows in a Namespace, Namespace variables are accessible from the Variables tab.

Creating Namespaces

From the UI

The video below shows how to create a namespace and add:

  • several new secrets
  • a nested Namespace variable that references one of these secrets
  • a list of plugin defaults helping to use those pre-configured secrets and variables in all the tasks from the AWS and Git plugins.

From Terraform

The following example reproduces those steps in Terraform.

To create a Namespace from Terraform, use the kestra_namespace resource.

Configure your Terraform backend and add Kestra as a required provider:

terraform {
backend "s3" {
bucket = "kestraio"
key = "terraform.tfstate"
region = "us-east-1"
}
required_providers {
kestra = {
source = "kestra-io/kestra"
version = "~>0.14"
}
}
}
provider "kestra" {
url = var.kestra_host
username = var.kestra_user
password = var.kestra_password
tenant_id = var.kestra_tenant_id # only if you are using multi-tenancy
}

Add a main.tf file to your Terraform project:

resource "kestra_namespace" "marketing" {
namespace_id = "marketing"
description = "Namespace for the marketing team"
}

The only required property is the namespace_id, which is the name of the Namespace. The description and all other properties are optional.

Adding variables and plugin defaults to a Namespace Terraform resource

Variables and plugin defaults are added directly to the Namespace resource by pointing to YAML configuration files.

Create the variables_marketing.yml file:

github:
token: "{{ secret('GITHUB_TOKEN') }}"

Then, create another file for plugin_defaults_marketing.yml:

- type: io.kestra.plugin.aws
values:
accessKeyId: "{{ secret('AWS_ACCESS_KEY_ID') }}"
region: us-east-1
secretKeyId: "{{ secret('AWS_SECRET_ACCESS_KEY') }}"
- type: io.kestra.plugin.git
values:
password: "{{ render(namespace.github.token) }}"
username: your-github-username

Finally, reference those files in your Namespace resource definition:

resource "kestra_namespace" "marketing" {
namespace_id = "marketing"
description = "Namespace for the marketing team"
variables = file("variables_marketing.yml")
plugin_defaults = file("plugin_defaults_marketing.yml")
}

Adding secrets to a Namespace using Terraform

The kestra_namespace_secret resource adds secrets programmatically to a namespace. Example adding multiple secrets to the marketing namespace:

resource "kestra_namespace_secret" "github_token" {
namespace = "marketing"
secret_key = "GITHUB_TOKEN"
secret_value = var.github_token
}
resource "kestra_namespace_secret" "aws_access_key_id" {
namespace = "marketing"
secret_key = "AWS_ACCESS_KEY_ID"
secret_value = var.aws_access_key_id
}
resource "kestra_namespace_secret" "aws_secret_access_key" {
namespace = "marketing"
secret_key = "AWS_SECRET_ACCESS_KEY"
secret_value = var.aws_secret_access_key
}

Variables used in Terraform are declared in variables.tf:

variable "github_token" {
type = string
sensitive = true
}
variable "aws_access_key_id" {
type = string
sensitive = true
}
variable "aws_secret_access_key" {
type = string
sensitive = true
}
variable "kestra_user" {
type = string
sensitive = true
}
variable "kestra_password" {
type = string
sensitive = true
}
variable "kestra_host" {
type = string
sensitive = false
default = "http://your_kestra_host:8080" # Change this to your Kestra host URL
}
variable "kestra_tenant_id" {
type = string
sensitive = false
default = "kestra-tech"
}

And add your secrets to the terraform.tfvars file:

github_token = "your-github-token"
aws_access_key_id = "your-aws-access-key-id"
aws_secret_access_key = "your-aws-secret-access-key"
kestra_user = "your-kestra-user"
kestra_password = "your-kestra-password"

Allowed Namespaces

The allowedNamespaces setting controls which namespaces can access a namespace’s flows and resources. Configure it on the Edit tab of any namespace.

By default, all namespaces are allowed. To restrict access, select specific namespaces — access automatically extends to each selected namespace’s children.

Was this page helpful?