Ctrl Plane

Secrets

Store, version, and inject secrets into instances with pluggable vault backends.

The secrets subsystem manages sensitive configuration that shouldn't be stored in plain text alongside application code. Secrets are scoped to instances and can be injected as environment variables or files.

Secret types

TypeUse case
envInjected as an environment variable
fileMounted as a file in the container
registryDocker registry credentials
tlsTLS certificate and private key

Setting a secret

secret, err := cp.Secrets.Set(ctx, secrets.SetRequest{
    InstanceID: instanceID,
    Key:        "DATABASE_URL",
    Value:      []byte("postgres://user:pass@db:5432/myapp"),
    Type:       secrets.TypeEnv,
})

If the key already exists, a new version is created. The old version is retained.

Retrieving a secret

secret, err := cp.Secrets.Get(ctx, instanceID, "DATABASE_URL")
// secret.Value contains the raw bytes
// secret.Version is the current version number

Listing secrets

List all secrets for an instance (values are not included for safety):

secretList, err := cp.Secrets.List(ctx, instanceID)
for _, s := range secretList {
    fmt.Printf("%s (v%d, type=%s)\n", s.Key, s.Version, s.Type)
}

Injecting secrets

Resolve all env-type secrets for an instance into a key-value map for container startup:

envVars, err := cp.Secrets.Inject(ctx, instanceID)
// envVars is map[string]string{"DATABASE_URL": "postgres://..."}

The deployment subsystem calls Inject automatically when deploying or restarting an instance.

Vault interface

By default, secrets are stored in the database alongside other entities. For production use, you can plug in an external vault:

type Vault interface {
    Store(ctx context.Context, key string, value []byte) error
    Retrieve(ctx context.Context, key string) ([]byte, error)
    Delete(ctx context.Context, key string) error
    Rotate(ctx context.Context, key string) error
}

Implement this interface to integrate with HashiCorp Vault, AWS Secrets Manager, GCP Secret Manager, or any other backend.

Security notes

  • Secret Value fields are tagged json:"-" and are never included in API responses or JSON serialization.
  • The List endpoint returns metadata (key, type, version) but never the value itself.
  • Get returns the value only to authenticated callers with the correct tenant scope.

On this page