Skip to content
Deployment
Skill

/setup-secret

Secret access wiring and manifest authoring. Use when a workload needs to read a secret, the user asks to create a secret or generate secret YAML, configure a pull secret, or fix a deployment paused on a secret reference.

From plugin
ai-plugin
1132 skills2 agents2 commands1 MCP

Claude Code

$ npx -y skills add controlplane-com/ai-plugin --skill setup-secret --agent claude-code

SKILL.md

setup-secret.SKILL.md
name: setup-secret
description: Secret access wiring and manifest authoring. Use when a workload needs to read a secret, the user asks to create a secret or generate secret YAML, configure a pull secret, or fix a deployment paused on a secret reference.

Secret Access Setup

A workload reads a secret only when three things are in place. Miss one and the value is silently absent, or the deployment pauses on the unresolved reference.

| Step | What must be true | Without it | |---|---|---| | **Identity** | an identity linked to the workload (`spec.identityLink`) | the workload reads nothing | | **Policy** | a policy granting that identity `reveal` on the secret | the reference resolves to empty | | **Reference** | `cpln://secret/NAME` or `cpln://secret/NAME.KEY` in env or a volume | nothing to read |

`reveal`, not `view`: `view` shows metadata only. This is the most common mistake.

Creating and rotating

`mcp__cpln__create_secret` creates secrets without a value passing through the chat, and `mcp__cpln__rotate_secret` rotates them; their descriptions cover both paths. Values Control Plane generates and values the user enters belong in separate secrets. Confirm a secret exists (`get_resource`, kind "secret") before anything references it.

Wiring access

  • **`deploy_app`** wires all three steps for the references in its env, and refuses a referenced secret that does not exist before it builds or writes anything.
  • **`grant_workload_secret_access`** (`gvc`, `workloadName`, `secretName`) creates the identity if missing (default `{gvc}-{workloadName}`), creates or updates a `reveal` policy (default `{gvc}-{workloadName}-secrets-policy`), links the identity, and redeploys a workload already waiting on the secret. Before writing anything it checks that the secret exists and that an existing policy of that name targets secrets. It does not add the reference. The workload must exist first: create it (its deployment pauses on the reference), then grant, and it resumes.
  • The platform checks access once per deployed version. A version it refused stays refused after the policy changes, until a new version deploys, so the tool grants before it links and redeploys a workload still waiting.
  • **By hand**, only when the tool cannot: `create_identity`, then `create_policy` with target kind `secret` and a `reveal` binding for the identity (`access-control` skill), then `update_workload` to set `spec.identityLink` last.
  • **Revoking:** `grant_workload_secret_access` with `remove: true` takes the secret out of that policy (deleting the policy once it targets nothing) and keeps the identity; it refuses, changing nothing, a policy that also binds another principal or grants by `target: all` or a query. Also drop the `cpln://secret/` reference with `update_workload`: a deploy that still references a revoked secret fails, and running replicas keep the value until they are replaced.
  • Identities are GVC-scoped: one per workload, shareable within a GVC, never across GVCs.

References

| Type | Keys | Example | |---|---|---| | opaque | `payload` | `cpln://secret/api-key.payload` | | userpass | `username`, `password` | `cpln://secret/creds.password` | | tls | `key`, `cert`, `chain` | `cpln://secret/web-tls.cert` | | keypair | `secretKey`, `publicKey`, `passphrase` | `cpln://secret/deploy-key.secretKey` | | dictionary | user-defined | `cpln://secret/cfg.DB_HOST` | | aws / ecr | `accessKey`, `secretKey`, `roleArn`, `externalId` | `cpln://secret/aws.accessKey` |

Inject as an env var or a volume (`{ uri: "cpln://secret/NAME", path: "/secrets/x" }`). Secret mounts are read-only, at most 15 volumes per container, and `/dev`, `/dev/log`, `/tmp`, `/var`, and `/var/log` are rejected. A workload reads a secret when it starts, so a value changed any way other than `rotate_secret` needs a redeploy.

Pull secrets need no identity or policy

To pull from a private registry, add a secret of type `docker`, `ecr`, or `gcp` to the GVC's `spec.pullSecretLinks`, and every workload in that GVC can pull. The user enters the registry credentials through the Console link from `create_secret`.

Manifests for CLI and GitOps users

Users who keep secrets as code may want a manifest instead of the Console link. Write it with UPPERCASE placeholders, then tell them to fill it in locally, apply it with `cpln apply -f secret.yaml --org ORG` or the Console's cpln apply button, keep the filled file out of git, and delete it after. Never ask for the real value, and never apply the file yourself.

`data` has a fixed shape per type. The trap: for `docker`, `gcp`, and `azure-sdk`, `data` is one JSON string, never a YAML mapping.

kind: secret
name: my-registry
type: docker
data: >-
  {"auths":{"REGISTRY_HOST":{"username":"USERNAME","password":"PASSWORD"}}}

| `type` | `data` | Validation | |---|---|---| | `opaque` | `{payload, encoding?}` | `payload` valid base64 when `encoding: base64` (default `plain`) | | `dictionary` | object of string values | keys match `[-._a-zA-Z0-9]+` | | `userpass` | `{username, password, encoding?}` | none | | `tls` | `{cert, key?, chain?}` | `cert` and `key` valid PEM | | `keypair` | `{secretKey, publicKey?, passphrase?}` | `secretKey` a valid PEM private key | | `aws` | `{accessKey, secretKey, roleArn?, externalId?}` | `accessKey` starts with `AKIA`, `roleArn` with `arn:` | | `ecr` | aws fields plus `repos` (1 to 20) | each `ACCOUNT_ID.dkr.ecr.REGION.amazonaws.com[/REPO]` | | `azure-connector` | `{url, code}` | `url` is https | | `nats-account` | `{accountId, privateKey}` | `accountId` a public nkey (`A…`), `privateKey` a seed (`SA…`) | | `docker` | **JSON string** | parses with an `auths` object keyed by registry host | | `gcp` | **JSON string** | a full service-account key: `type`, `project_id`, `private_key_id`, `private_key`, `client_email`, `client_id`, `auth_uri`, `token_uri`, `auth_provider_x509_cert_url`, `client_x509_cert_url` | | `azure-sdk` | **JSON string** | `subscription

Read more
@controlplane-com
Ships withai-plugin

Run containerized workloads across AWS, GCP, Azure, OCI, and your own hardware under one API.

1132 skills2 agents1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
11
Star history of controlplane-com/ai-plugin on GitHub, a chart by star-history.com

Other skills on ai-plugin.

cpln

cpln

Writes cpln CLI commands and workflows for Control Plane. Use when the user asks about cpln login, cpln apply, cpln workload, CLI…

create-app

create-app

Writes, builds, and deploys an app the user asks for in the chat, with no repository and no image yet. Use when the user asks to…

More skills from other plugins.

configuring-horizon

configuring-horizon

Use this skill whenever the user mentions Horizon by name in a Laravel context. Covers the full Horizon lifecycle: installing…

coolify9d66k
@coollabsio@coollabsioInstall Skill
vercel-cli

vercel-cli

Guides deployment, configuration, and troubleshooting with the Vercel CLI. Use when operating Vercel projects or resources…

vercel11d16k
@vercel@vercelInstall Skill
skypilot

skypilot

Use when launching cloud VMs, Kubernetes pods, or Slurm jobs for GPU/TPU/CPU workloads, training or fine-tuning models on cloud…

skypilottoday11k
@skypilot-org@skypilot-orgInstall Skill
pinme

pinme

Use this skill when the user mentions "pinme", or needs to upload files, store to IPFS, create/publish/deploy websites or…

pinme8w3.8k
@glitternetwork@glitternetworkInstall Skill

Questions about setup-secret.

Which coding agents can use setup-secret?
setup-secret installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.