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.Costs
Nebius AI Cloud only charges for running a Managed Kubernetes cluster. For more details, see Managed Kubernetes pricing and SecretStash pricing.Prerequisites
- Install and configure the Nebius AI Cloud CLI.
- Check that your project ID is saved in the Nebius AI Cloud CLI profile configuration:
- Make sure you are in a group that has the
adminrole within your tenant or project; for example, the defaultadminsgroup. You can check this in the Administration → IAM section of the web console. - Create a Managed Kubernetes cluster with at least one node group and connect to it using kubectl.
- Install Helm.
- Create a secret in SecretStash. The examples use a secret with the
passwordkey.
Steps
Run all commands in the same terminal session. Some commands save values, such as resource IDs, to environment variables. Thekubectl 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 themysterybox.payload-viewer role for the secret.
-
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. -
Create a service account and save its ID to an environment variable:
-
Create a custom group for the service account and save the group ID to an environment variable:
-
Grant the
mysterybox.payload-viewerrole for the secret to the group:To grant access to all secrets in the project, specify the project ID in--resource-idinstead of the secret ID. -
Add the service account to the group:
Install ESO
-
Add the ESO Helm repository:
-
Install ESO 2.10.0 or later with its custom resource definitions:
-
Make sure that the ESO Pods are running:
All Pods should have the
Runningstatus.
Create a namespace
-
Specify a name for the namespace and save it to an environment variable:
The
kubectlcommands 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. -
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.
- Workload identity (recommended)
- Service account credentials
-
Create the
mysterybox-readerServiceAccount together with a Role and a RoleBinding. ESO requests tokens for this ServiceAccount through the Kubernetes TokenRequest API, and the Role and RoleBinding allow this:In the RoleBinding,external-secretsis the name and namespace of the ESO controller’s ServiceAccount when you install ESO as shown above. If you installed ESO with a different Helm release name or namespace, get the ServiceAccount name by runningkubectl get serviceaccounts -n <ESO_namespace>. -
Get the ID of your Managed Kubernetes cluster:
-
Create federated credentials. They let a workload outside Nebius AI Cloud, here the
mysterybox-readerServiceAccount in your cluster, get access tokens of a Nebius AI Cloud service account. To create them, run the following command:The command contains the following parameters:--parent-id: ID of the project.--subject-id: ID of the Nebius AI Cloud service account whose access tokens the ServiceAccount gets. The command takes the ID from theSA_IDvariable.--oidc-provider-issuer-url: URL of the cluster’s OpenID Connect (OIDC) issuer. Replace<cluster_ID>with the ID that you got in the previous step. For more details, see Using an OIDC public endpoint in Managed Kubernetes clusters.--federated-subject-id: Kubernetes ServiceAccount in thesystem:serviceaccount:<namespace>:<ServiceAccount_name>format. The command uses themysterybox-readerServiceAccount in the namespace from theK8S_NAMESPACEvariable.
-
Create the SecretStore. The command passes the service account ID from the
SA_IDvariable toiamServiceAccountID: -
Make sure that the SecretStore is valid:
In the output, the
STATUScolumn should showValid. To validate the SecretStore, ESO gets an access token for the service account, so this status also confirms that the federated credentials and the RoleBinding work. Don’t proceed until the SecretStore has theValidstatus. If it doesn’t, see Troubleshooting.
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.-
Create the ExternalSecret. The command passes the secret ID from the
SECRET_IDvariable tokey:WithdataFrom.extract, every key of the secret payload becomes a key in the Kubernetes Secret. To sync only some keys, replacedataFromwithdataand add an entry withpropertyfor each key:If you don’t specifyproperty, ESO writes the whole payload as JSON to the Kubernetes Secret key. -
Make sure that ESO has synced the secret:
The result looks like the following:If the status isn’t
SecretSynced, see Troubleshooting. -
Check the keys of the Kubernetes Secret:
The output contains the keys of the secret payload with base64-encoded values.
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:
version to each entry:
version in the ExternalSecret and apply it again.
Troubleshooting
If the ExternalSecret doesn’t have theSecretSynced status, get the details of the error:
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.namematches the SecretStore name. -
The SecretStore isn’t valid with workload identity federation: Make sure that the issuer URL and the
system:serviceaccount:<namespace>:mysterybox-readersubject 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 themysterybox-sa-credentialsKubernetes 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.
- If the events contain
-
Access is denied: Make sure that the service account is in a group with the
mysterybox.payload-viewerrole 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
propertymust 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_IDandSECRET_IDagain, then delete and recreate the affected resources.