Skip to main content

Create and read a secret

Available

Deployed and supported. The fields and commands described here are stable within version v1alpha1.

A secret is an encrypted value, stored in your tenant under a name, that your applications consume as an environment variable. This guide shows how to create one with sng secret set, read it back with sng secret get, and inspect the inventory with list and describe.

Prerequisites​

  • The sng CLI installed and authenticated: sng sso login.
  • A session on your tenant: sng tenant use mon-tenant.
  • The right to write secrets: the managed policy readwrite (or admin) is enough. With read-only access (readonly), you can list, describe and read, but not write. See Identity and access.

1. Create a secret with a generated value​

Without a provided value, sng secret set draws a random 16-character value (letters, digits, punctuation) and stores it.

sng secret set db-password
secret "db-password" saved with a generated 16-character value (sng secret get db-password)

Adjust the shape of the generated value:

# 32 characters, letters and digits only
sng secret set api-key --length 32 --contains letters,numbers

# no symbols, without characters that are awkward in a URL
sng secret set smtp-password --no-symbols --exclude-chars '@:/'

Two ways to choose the character classes, mutually exclusive:

  • positively with --contains: letter, number, symbol, lower, upper (accepted aliases: letters, alpha, digit, digits, numbers, symbols, punctuation, lowercase, uppercase);
  • by subtraction with --no-lowercase, --no-uppercase, --no-numbers, --no-symbols.

By default (--require-each-type), the value contains at least one character of each selected class; --length must therefore be at least equal to the number of classes.

2. Create a secret with a value you provide​

The recommended method is the file: the value goes neither through the shell history nor through the process list.

printf '%s' 'S3cr3t-value' > /tmp/db-password
sng secret set db-password --from-file /tmp/db-password
rm /tmp/db-password
secret "db-password" saved

The file content is taken as is, including the final newline: use printf rather than echo.

For a secret with several keys (for example all the parameters of a connection), pass --data as many times as needed:

sng secret set shop-api \
--data DATABASE_URL=postgres://shop:pass@db:5432/shop \
--data SMTP_HOST=smtp.example.net \
--data SMTP_PASSWORD=xyz

--value also exists, but the value then appears in your shell history: keep it for tests.

Where does the value go?

A secret set without --data is stored under a single key named value. This is the key you then reference from an App: { secret: db-password, key: value }. With --data, the keys are the ones you gave. See Inject a secret into an App.

3. Read a secret back​

sng secret get db-password
{
"value": "S3cr3t-value"
}

Extract a single key (raw output, no JSON):

sng secret get shop-api --key SMTP_PASSWORD
xyz

Write to a protected file rather than to the screen:

sng secret get db-password --key value --out-file ./db-password
wrote ./db-password (mode 0600)

The message goes to standard error; the file is created with permissions 0600.

Read an earlier version with --version-id: see Versions and restore.

4. List and describe​

sng secret list
NAME KEYS UPDATED
api-key 2026-10-07T09:12:41Z
db-password 2026-10-07T09:10:03Z
shop-api 2026-10-07T09:15:27Z

The KEYS column is empty in this version: the list does not load the keys. Use describe to know them.

sng secret describe shop-api
{
"name": "shop-api",
"keys": ["DATABASE_URL", "SMTP_HOST", "SMTP_PASSWORD"],
"updated_at": "2026-10-07T09:15:27Z",
"version_id": "1",
"version_stages": { "current": "1" },
"bindings": { "…": "…" }
}

describe never returns the value. It returns the keys, the current version and, if a rotation is armed, rotation_enabled, rotation_days and next_rotation_date. The bindings block is a legacy: ignore it and use the { secret, key } form of Apps.

Verification​

sng secret describe db-password --json | grep version_id

A version "1" confirms the first write; each subsequent set increments it.

If it doesn't work​

MessageCauseFix
forbidden (no policy of this tenant allows it: see sng tenant policy list)Your session does not have the right to write or read secretsAsk an administrator for readwrite (or a targeted policy)
secret not foundMisspelled name, or deleted secretsng secret list
Name rejectedUppercase letter, / or .. in the nameSee the naming rules below
get returns a value with an extra newlineThe source file was written with echoSet the value again with printf

Going further​

  • Secret name: lowercase letters, digits, ., _, -, 128 characters at most, without / or ... The name is also the one your Apps reference: choose it like a stable identifier (db-password, not db-password-v2).
  • Update: running sng secret set NAME again on an existing name creates a new version; the old one remains readable with --version-id.
  • Scheduled rotation: set accepts --rotation N to ask the platform to renew the value every N days. A set without --rotation does not touch an already armed rotation. See Rotation.
  • Permissions and API: set maps to PUT /v1/secrets/{name} (IAM action ssm:write), get to GET /v1/secrets/{name}/value (ssm:read), list and describe to GET /v1/secrets and GET /v1/secrets/{name} (ssm:list, ssm:describe). Every read of a value is logged (name and version, never the value).
  • Machine output: --json on set, list, versions returns the API objects as is.

See also​