Skip to main content
MysteryBox is now called SecretStash. The Nebius AI Cloud CLI, API and Terraform provider still use the mysterybox service identifier. Keep using mysterybox in scripts and manifests.
Applications in a Managed Service for Kubernetes cluster often read credentials, such as API keys or passwords, from Kubernetes Secrets. Instead of creating these Secrets manually or storing their values in manifests and CI/CD pipelines, you can keep the values in SecretStash and sync them with the cluster by using External Secrets Operator (ESO). ESO reads a SecretStash secret, writes its payload to a Kubernetes Secret and updates it when you add a new primary version in SecretStash. In this tutorial, you will grant a service account access to a secret, install ESO, set up authentication for ESO and sync the secret with your cluster.

Costs

Nebius AI Cloud only charges for running a Managed Kubernetes cluster. For more details, see Managed Kubernetes pricing and SecretStash pricing.

Prerequisites

  1. Install and configure the Nebius AI Cloud CLI.
  2. Check that your project ID is saved in the Nebius AI Cloud CLI profile configuration:
  3. Make sure you are in a group that has the admin role within your tenant or project; for example, the default admins group. You can check this in the Administration → IAM section of the web console.
  4. Create a Managed Kubernetes cluster with at least one node group and connect to it using kubectl.
  5. Install Helm.
  6. Create a secret in SecretStash. The examples use a secret with the password key.

Steps

Run all commands in the same terminal session. Some commands save values, such as resource IDs, to environment variables. The kubectl commands that you run later read these variables and pass their values to the Kubernetes manifests, so you don’t need to copy the values manually.

Grant a Nebius AI Cloud service account access to the secret

ESO reads the secret on behalf of a Nebius AI Cloud service account. This service account needs the mysterybox.payload-viewer role for the secret.
Creating a secret or a version of a secret does not automatically grant you access to view payloads in that secret or version. The editor role is enough to create a secret or a version, but viewing payloads requires the mysterybox.payload-viewer role, which is a sub-role of admin but not editor.
  1. Get the ID of the secret and save it to an environment variable:
    Make sure that the variable isn’t empty: run echo $SECRET_ID. If the output is empty, check the secret name and the project ID.
  2. Create a service account and save its ID to an environment variable:
  3. Create a custom group for the service account and save the group ID to an environment variable:
  4. Grant the mysterybox.payload-viewer role for the secret to the group:
    To grant access to all secrets in the project, specify the project ID in --resource-id instead of the secret ID.
  5. Add the service account to the group:

Install ESO

  1. Add the ESO Helm repository:
  2. Install ESO 2.10.0 or later with its custom resource definitions:
  3. Make sure that the ESO Pods are running:
    All Pods should have the Running status.

Create a namespace

  1. Specify a name for the namespace and save it to an environment variable:
    The kubectl commands that you run later create the Kubernetes resources in this namespace, including the Kubernetes Secret with the synced values. Pods can only use Secrets from their own namespace. If the workloads that need the secret already run in a namespace, specify its name and skip the next step.
  2. Create the namespace:

Set up authentication and connect ESO to SecretStash

ESO can authenticate in SecretStash using one of the following methods:
  • Workload identity federation (recommended): ESO exchanges a short-lived token of a Kubernetes ServiceAccount for an access token of the Nebius AI Cloud service account. You don’t need to store long-lived credentials in the cluster.
  • Service account credentials: ESO uses an authorized key of the Nebius AI Cloud service account. You store the key in a Kubernetes Secret.
For either method, you create a SecretStore: a Kubernetes custom resource that ESO adds to your cluster. A SecretStore tells ESO how to authenticate in SecretStash. For more details, see the ESO documentation. Set up one of the authentication methods and create a SecretStore for it:

Sync the secret with the cluster

An ExternalSecret is another ESO custom resource. It tells ESO which SecretStash secret to read and which Kubernetes Secret to write it to. For more details, see the ESO documentation.
  1. Create the ExternalSecret. The command passes the secret ID from the SECRET_ID variable to key:
    With dataFrom.extract, every key of the secret payload becomes a key in the Kubernetes Secret. To sync only some keys, replace dataFrom with data and add an entry with property for each key:
    If you don’t specify property, ESO writes the whole payload as JSON to the Kubernetes Secret key.
  2. Make sure that ESO has synced the secret:
    The result looks like the following:
    If the status isn’t SecretSynced, see Troubleshooting.
  3. Check the keys of the Kubernetes Secret:
    The output contains the keys of the secret payload with base64-encoded values.
Your workloads can now use the app-credentials Kubernetes Secret, for example, as environment variables or a mounted volume. By default, ESO syncs the primary version of the secret. When you make another version primary, ESO updates the Kubernetes Secret within the interval set in refreshInterval. To sync a specific version instead, add version: <version_ID> under remoteRef or extract. To get the version ID, list the versions of the secret. For example, to pin the version in the ExternalSecret that you created:
If you sync only some keys, add version to each entry:
When a version is pinned, ESO doesn’t pick up a new primary version until you change version in the ExternalSecret and apply it again.

Troubleshooting

If the ExternalSecret doesn’t have the SecretSynced status, get the details of the error:
Check the Events section of the output and the following possible causes:
  • Nothing is reconciled: Make sure that the ESO Pods are running and the ESO custom resource definitions are installed:
  • The SecretStore isn’t found: Make sure that the SecretStore and the ExternalSecret are in the same namespace and that secretStoreRef.name matches the SecretStore name.
  • The SecretStore isn’t valid with workload identity federation: Make sure that the issuer URL and the system:serviceaccount:<namespace>:mysterybox-reader subject in the federated credentials match your cluster and ServiceAccount, and that the RoleBinding refers to the ESO controller’s ServiceAccount.
  • The SecretStore isn’t valid with service account credentials: Get the details by running kubectl describe secretstore mysterybox -n $K8S_NAMESPACE.
    • If the events contain Public Key not exists, expired or deactivated, the authorized key has expired or been deleted. Delete the old credentials file, generate new credentials and recreate the mysterybox-sa-credentials Kubernetes Secret. ESO caches access tokens, so the SecretStore can stay valid for several hours after the key stops working.
    • If the events contain invalid subject credentials: malformed JSON, delete the credentials file, generate the credentials again and recreate the Kubernetes Secret.
  • Access is denied: Make sure that the service account is in a group with the mysterybox.payload-viewer role for the secret or its project.
  • The payload is empty or has unexpected keys: Check the payload of the secret:
    Keys that you specify in property must match the keys of the payload.
  • A Kubernetes resource has an empty namespace or ID: If you opened a new terminal session when configuring the sync of secrets, the environment variables aren’t set. Set K8S_NAMESPACE, SA_ID and SECRET_ID again, then delete and recreate the affected resources.