PlanyDocs
Account and platform

Secrets

One place for your credentials — database passwords, API keys, licence files — read by your game servers and sandboxes at launch.

A secret holds a credential: a database password, an API key, an RCON password, a licence file. Your game servers and sandboxes reference it by name and read the value when they start, so the value never sits in a config file, a launch command or your Terraform variables in plain sight — and rotating it once reaches everything that uses it.

Values go in and do not come out. Creating, rotating and attaching a secret never show you the value; reading one back is a separate permission that most people on a project do not need.

Secrets and versions

projects/{project}/locations/{location}/secrets/{secret}
projects/{project}/locations/{location}/secrets/{secret}/versions/{version}

A secret is the name, a description and who may use it. It holds no value itself. A version is one value, and cannot be changed once added. Versions are numbered 1, 2, 3… and a number is never reused.

A reference to a secret without a version means the latest enabled version. That is what makes rotation work: add a new version and everything that references the secret picks it up the next time it starts, with nothing to edit.

A secret belongs to one project and one region, like the workloads that read it. A value can be up to 64 KiB.

Creating a secret

Security → Secrets → New secret → name it, say what it is for, paste the value → Create secret

--value also works, but puts the value in your shell history; prefer --from-file or --stdin.

What you can read about a secret without its value:

FieldTells you
latest_versionThe version a reference without a number gets.
payload_fingerprintA short hash of the current value. Two secrets with the same fingerprint hold the same value — so "did I paste the same key into both?" has an answer without anybody looking.
last_access_timeWhen a workload or a person last read it. A secret nothing has read in months is the one worth revoking.
managed_bySet when Plany stored the secret on your behalf.

Rotating

Rotating is adding a new version. By default the version it replaces is disabled in the same step, so there is never a moment with no working value and never a forgotten old one left live.

Security → Secrets → open the secret → Rotate → paste the new value

--keep-previous leaves the old version enabled while you check nothing breaks; then disable it yourself.

A running game server or sandbox instance keeps the value it read when it started. The new one reaches it on its next start.

Managing versions

StateMeaning
STATE_ENABLEDCan be read.
STATE_DISABLEDKept, but refused to every reader. Can be enabled again.
STATE_DESTROYEDThe value is gone for good. The version's number, size and fingerprint are kept as a record that it existed.
Shell
plany secrets versions db-password # newest first
plany secrets versions disable db-password 3
plany secrets versions enable db-password 3
plany secrets versions destroy db-password 3 # irreversible

Using a secret in a game server

Attach a secret to a game server as an environment variable. The name is yours to choose — upper case, digits and underscores:

Servers → New server (or a server's settings) → Secrets → choose the secret and the variable name

The variable can also be used in the game's config files and launch command as ${VAR}, so an RCON password is one attachment and a line in server.properties:

properties
rcon.password=${RCON_PASSWORD}

Add a path after a colon — --secret LICENCE_KEY=licence:licence.key, or file_path — and the value is also written to that file, relative to the game's directory, readable only by the game. For the credentials a game reads from a file rather than a variable: a licence, a TLS key, a service account JSON. The file is written fresh on every start, so a rotation never leaves a stale copy behind.

A server that cannot read one of its secrets refuses to start and says which, rather than starting without it and failing quietly later.

A value used as an environment variable must be text. A binary value — a key file, say — goes in a file instead.

See Game servers for the rest of a server's settings.

Using a secret in a sandbox

A sandbox takes secrets the same way, as environment variables and, optionally, files at an absolute path inside the container:

plany sandbox sandboxes deploy api --secret DATABASE_URL=database-url \
--secret TLS_KEY=tls-key:/etc/api/tls.key
plany sandbox sandboxes deploy api --remove-secret TLS_KEY

Changing a sandbox's secrets deploys a new revision. See Deploying a sandbox.

Who can read a value

Reading about a secret and reading its value are different permissions.

RoleSee and manage secretsRead a value
roles/account.viewer, roles/project.viewerSee themNo
roles/project.editorCreate, rotate, attach, disable, destroyNo
roles/project.owner, roles/account.admin, roles/account.ownerEverythingYes
roles/secretmanager.accessorNothingYes, on the one secret it is granted on

An editor never needs to see a value. Attaching a secret to a server is a reference by name; the server reads the value itself, as its own identity, when it starts. So the people who run a project can configure and rotate credentials without ever holding them.

roles/secretmanager.accessor is what a workload holds. When you attach a secret, Plany grants it to that game server's or sandbox's identity on that secret alone — it can read the value it was given, and cannot even list what else is in the project. If the workload runs as a service account of your own, grant it yourself, on the secret:

Terraform
resource "plany_secret_iam_member" "backend_reads_database_url" {
secret = plany_secret.database_url.name
role = "roles/secretmanager.accessor"
member = plany_service_account.backend.name
}

When a person who can read values needs one:

Security → Secrets → open the secret → Reveal on a version → Reveal

Every read updates the secret's last_access_time.

Deleting a secret

Deleting a secret removes it and every version it holds. While a game server or a sandbox still uses it, the delete is refused and names what is using it — detach it there first. plany secrets delete --force deletes it anyway.

A secret Plany stored on your behalf cannot be deleted directly; delete the resource that created it.

Pricing and limits

Price$0.05 a secret a month, charged by the hour
Free10 secrets, every month
Secrets Plany stores for youFree, and not counted
Limit50 secrets per project and region on Hobby, 500 on Pro — ask for more

The price is per secret, not per version or per read: rotate as often as you like.