---
title: Secrets
description: 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

| Type | Use case |
|------|----------|
| `env` | Injected as an environment variable |
| `file` | Mounted as a file in the container |
| `registry` | Docker registry credentials |
| `tls` | TLS certificate and private key |

## Setting a secret

```go
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

```go
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):

```go
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:

```go
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:

```go
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.
