Secret Management
Preview Feature
Secret management is currently a preview feature. You are seeing an early version of this functionality, which may change in future updates as we continue to improve the experience.
Codesphere provides a Secret Management system integrated with OpenBao, an open-source security vault. This ensures that sensitive data, such as API keys, database credentials, and certificates, are stored with industry-standard encryption and injected into your services only when needed.
Overview
Unlike standard environment variables, secrets are stored in a vault shipped with a Codesphere instance. This provides several advantages:
- Encryption at Rest: All values are encrypted before being persisted.
- Granular Access: Only services explicitly referencing a secret can access its value.
- Automatic Cleanup: Secrets are bound to the lifecycle of the workspace.
info
Currently only admins of a Codesphere installation have direct access to the vault.
Referencing Secrets
Secrets are managed within the Landscape Config Editor. To define a secret, you must use a specific templating syntax regardless of whether you are using the UI or the YAML configuration.
Template Syntax: ${{ vault.secretKeyOfBao }}
- UI Configuration
- YAML Configuration
To add a secret to a service using the visual editor:
- Open the Landscape Config Editor in your workspace.
- Select the service you wish to configure and open the Edit Service fly-in sheet.
- Navigate to the Values tab.
- Add a new entry using the templating syntax:
- Key: The Environment Variable name the service will use (e.g.,
SECRET_KEY). - Value: The template referencing the vault key (
${{ vault.secretFoo }}).
- Key: The Environment Variable name the service will use (e.g.,
Configuring environment variables using vault templates in the service values tab.
For direct configuration, secrets are defined in the env section of your ci.yml profile. Codesphere parses these templates during the sync process and injects the corresponding OpenBao entries into the service environment.
schemaVersion: v0.2
prepare:
steps: []
test:
steps: []
run:
secret-demo:
steps:
- command: echo $SECRET_KEY
plan: 8
replicas: 1
network:
ports:
- port: 3000
isPublic: false
paths: []
env:
SECRET_KEY: ${{ vault.secretFoo }}
PLAIN_ENV: foo
Advanced Environment Templates
Beyond vault secrets, Codesphere supports dynamic templates to reference system-level IDs or existing workspace environment variables. These are particularly useful for making your configuration portable or remapping variables.
| Template | Description |
|---|---|
${{ workspace.id }} | Resolves to the ID of the Workspace containing the landscape. |
${{ workspace.devDomain }} | Resolves to the Dev Domain of the Workspace containing the landscape. |
${{ team.id }} | Resolves to the ID of the team owning the workspace. |
${{ workspace.env['KEY'] }} | Resolves to a global workspace environment variable. |
Use Case: Variable Remapping
The ${{ workspace.env[...] }} template allows you to map global variables to specific service requirements.
For example, if a backend service expects an environment variable named PG_USER, but your database credentials are saved globally as BACKEND_PG_USER to avoid naming collisions with other databases, you can map them like this:
env:
PG_USER: ${{ workspace.env['BACKEND_PG_USER'] }}
Syncing and Persistence
After defining the secret references, you must sync the Landscape Profile within the Execution Manager.
The Sync Process
When the selected ci.yml contains new secret references during a landscape synchronization, the user is responsible for providing the actual secret values. The process follows these steps:
- User Prompt: A modal appears prompting you to provide the secret entries defined in your configuration.
- Input: You must enter the secret's real value at least once to initialize the entry in the vault.
- Persistence: Once submitted, these values are persisted in the OpenBao instance.
- Injection: The sync proceeds, and the landscape accesses the vault keys to inject them into the respective services.
The secret input modal triggered during the landscape sync process.
warning
Landscape synchronizations will fail if a service defined in the CI profile cannot access the secret entry it references. Ensure that all secrets are set up correctly during the first deployment of a Landscape.
Updating Secrets
While a dedicated user interface (UI) for the secrets vault is currently unavailable, secrets can be managed during landscape synchronization. When syncing a landscape, you can choose to deploy using existing secrets or update them before proceeding. The process follows these steps:
- User Prompt: A modal appears prompting you to select how to deploy the landscape: with existing secrets or change secrets before deploying.
- Input: Select change secrets before deploying. Provide the new real secret value. This will overwrite the value in the vault after clicking the confirm button. Note: You can undo any change to the secret or view the real value while in the editing process.
- Persistence: Once submitted, these values are persisted in the OpenBao instance.
- Injection: The sync proceeds, and the landscape accesses the vault keys to inject them into the respective services.
The secret input modal triggered during the landscape sync process.
Shared Vaults
By default, every workspace gets its own isolated vault partition, and the secret values it references must be initialized during the first landscape sync (see The Sync Process). A shared vault removes that manual step for secrets that are common across a team.
A shared vault is a dedicated partition inside the cluster vault that lives at the team level rather than the workspace level. Once created, it can be shared among any number of workspaces within the same team. The main advantages are:
- Zero-setup access: Workspaces assigned to a shared vault can reference its secrets immediately — without anyone entering values during workspace creation or landscape sync.
- Single source of truth: Common credentials (for example, shared database connection details) are stored once and reused everywhere, instead of being duplicated into each workspace.
- Centralized rotation: Updating a value in the shared vault propagates to every workspace that uses it on the next deployment.
info
Shared vaults are scoped to a team. Listing them requires team read access, while creating, deleting, or modifying them requires team write access.
How a Workspace Resolves Shared Secrets
The templating syntax for referencing a secret does not change — you still use ${{ vault.secretKey }} in your service configuration (see Referencing Secrets). What changes is which vault the reference resolves against:
- If a workspace is assigned a shared vault, all
${{ vault.* }}references in its landscape resolve against that shared partition. - If no shared vault is assigned, references resolve against the workspace's own partition (the default behavior).
This means a workspace pointed at a shared vault can deploy a landscape that consumes shared secrets without any per-workspace initialization beforehand.
warning
A workspace reads secrets from either its own vault or the assigned shared vault — the two are not merged. When you switch a workspace to a shared vault, make sure every ${{ vault.* }} key referenced by its landscape exists in that shared vault, otherwise the next sync will fail.
Assigning a Shared Vault to a Workspace
Shared vaults are selected per workspace through the Secrets Vault dropdown. The dropdown lists every shared vault available in the team plus the default Workspace (default) option, which keeps the workspace on its own isolated partition.
- On Workspace Creation
- On an Existing Workspace
When creating a workspace, expand Advanced Options in the second step of the dialog and pick a vault from the Secrets Vault dropdown. Leaving it on Workspace (default) keeps the workspace isolated.
Selecting a shared vault under Advanced Options in the Create Workspace dialog.
You can change the vault of an existing workspace from the General tab of the workspace settings. The change takes effect on the next landscape sync.
Changing the Secrets Vault of an existing workspace from the settings General tab.
info
The Secrets Vault selector is only shown when secret management is enabled for your installation.
Managing Secrets via the Public API
The Codesphere Public API exposes a full set of vault endpoints, allowing you to manage and auto-generate workspace secrets programmatically — for example, in a CI/CD pipeline or an internal developer platform. Authentication and general API usage are covered in the Public API documentation.
All vault endpoints follow this base path:
/vault/teams/{teamId}/workspaces/{workspaceId}
Store secrets
POST /vault/teams/{teamId}/workspaces/{workspaceId}
Writes one or more secret key-value pairs to the vault for a given workspace. Returns a map of each key to its revision identifier, which combines a version number and a timestamp.
Request body:
{
"DATABASE_PASSWORD": "supersecretpassword",
"API_KEY": "123456789"
}
Response:
{
"DATABASE_PASSWORD": "1__2026-03-05T10:14:48.490756937Z",
"API_KEY": "1__2026-03-05T10:14:48.490756937Z"
}
List secret keys
GET /vault/teams/{teamId}/workspaces/{workspaceId}/keys
Returns the list of secret keys stored for a workspace. Values are never exposed through this endpoint.
Response:
["DATABASE_PASSWORD", "API_KEY"]
Delete secrets
DELETE /vault/teams/{teamId}/workspaces/{workspaceId}
Permanently removes the specified secrets from the vault.
Request body:
["DATABASE_PASSWORD", "API_KEY"]
Auto-generate secrets
POST /vault/teams/{teamId}/workspaces/{workspaceId}/generate
Generates cryptographically random secret values and stores them directly in the vault — no plaintext value ever needs to leave your pipeline. The shape of each generated value is controlled by a password policy.
Password policy fields:
| Field | Type | Description |
|---|---|---|
length | number | Total length of the generated secret. |
rules | array | One or more charset rules applied during generation. |
rules[].charset | string | The set of characters to draw from. |
rules[].minChars | number | Minimum number of characters from this charset. |
Request body:
{
"DATABASE_PASSWORD": {
"length": 16,
"rules": [
{
"charset": "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
"minChars": 16
}
]
},
"API_KEY": {
"length": 32,
"rules": [
{
"charset": "0123456789abcdef",
"minChars": 32
}
]
}
}
Response — the generated values and their revision identifiers:
{
"DATABASE_PASSWORD": {
"value": "aB3kR7mX...",
"revision": "1__2026-03-05T10:14:48.490756937Z"
},
"API_KEY": {
"value": "1a2b3c4d...",
"revision": "1__2026-03-05T10:14:48.490756937Z"
}
}
Use case: zero-knowledge bootstrapping
The generate endpoint is ideal for initial workspace provisioning — you can create strong, unique secrets for every new environment without ever handling the raw values yourself. Reference the vault keys in your ci.yml using ${{ vault.secretKey }} and the secrets are injected at deploy time.
Shared vault endpoints
The Public API also exposes endpoints for managing shared vaults — team-level vaults that can be reused across workspaces. These let you provision a shared vault and its secrets programmatically, for example when bootstrapping a new team environment.
Shared vault endpoints are scoped to the team rather than a single workspace and follow this base path:
/vault/teams/{teamId}/shared
The secret value semantics — revision identifiers, write/list/delete behavior — are identical to the workspace endpoints described above. Listing requires team read access; creating, deleting, and modifying require team write access.
List shared vaults
GET /vault/teams/{teamId}/shared
Returns the names of all shared vaults belonging to the team.
Response:
["production-secrets", "staging-secrets"]
Create a shared vault
POST /vault/teams/{teamId}/shared
Creates a new, empty shared vault for the team. Secrets are added separately with the store endpoint below.
Request body:
{
"name": "production-secrets"
}
Delete a shared vault
DELETE /vault/teams/{teamId}/shared/{vaultName}
Permanently deletes a shared vault and all secrets stored in it. Any workspace still assigned to this vault will fail to resolve its secrets on the next sync.
Store secrets in a shared vault
POST /vault/teams/{teamId}/shared/{vaultName}/secrets
Writes one or more secret key-value pairs to the named shared vault. Returns a map of each key to its revision identifier (a version number combined with a timestamp).
Request body:
{
"DATABASE_PASSWORD": "supersecretpassword",
"API_KEY": "123456789"
}
Response:
{
"DATABASE_PASSWORD": "1__2026-03-05T10:14:48.490756937Z",
"API_KEY": "1__2026-03-05T10:14:48.490756937Z"
}
List secret keys in a shared vault
GET /vault/teams/{teamId}/shared/{vaultName}/keys
Returns the list of secret keys stored in the named shared vault. Values are never exposed through this endpoint.
Response:
["DATABASE_PASSWORD", "API_KEY"]
Delete secrets from a shared vault
DELETE /vault/teams/{teamId}/shared/{vaultName}/secrets
Removes one or more named secrets from the shared vault. Deleting every key does not remove the vault itself — use the Delete a shared vault endpoint for that.
Request body:
["DATABASE_PASSWORD", "API_KEY"]
Security and Access Control
Codesphere enforces strict isolation for secret access:
- Reference-Based Access: A service can only retrieve a secret if it is explicitly defined in its configuration.
- Landscape Isolation: Secrets are managed at the landscape level, ensuring that different deployment environments remain separated.
Lifecycle and Cleanup
To maintain a clean security posture, Codesphere automatically manages the lifecycle of your secrets. When a Workspace is deleted:
- All associated secret entries in the vault related to that workspace and its services are identified.
- The system performs a permanent cleanup of all related keys.
- No sensitive data remains available after the workspace is removed.
Shared vaults follow a different lifecycle: because they are owned by the team and shared across workspaces, they are not removed when an individual workspace is deleted. A shared vault and its secrets persist until it is explicitly deleted — either through the Public API or by an installation admin.