Signing keys
Sign every release with your own Ed25519 key. Generate, enroll, back up, rotate and revoke keys, and sign offline.
Every release on Depot is signed by the studio that made it. You hold an Ed25519 private key, Depot holds only the public half, and the launcher refuses any build whose signature doesn't check out against a key it trusts.
This means Depot itself can't publish a build in your name. If Depot's servers or storage were ever compromised, an attacker could stop downloads, but couldn't make a player's launcher install different files.
Generate a key
depot keys generateThis creates a key file at ~/.config/depot/keys/default.json, readable only by you, and prints its path and public key. Use --out to write it somewhere else:
depot keys generate --out ~/.config/depot/keys/my-studio.jsondepot keys generate refuses to overwrite an existing file. --force replaces it, and the old key is gone for good.
Where the private key lives
The private key stays in that file on your machine. No command sends it to Depot: depot keys enroll uploads only the public key, and depot push signs on your machine and uploads only the signature.
Back up the key file somewhere safe, such as a password manager. If you lose it, you can't sign new releases with it, and players who trust only that key won't accept releases signed by a new one. See Rotate a key.
Enroll it for a game
depot keys enroll --game my-game
depot keys enroll --game my-game --key ~/.config/depot/keys/my-studio.jsonEnrolling uploads the public key, and Depot gives it a key id (key_…). The CLI writes that id into the key file, so later pushes know which key id to sign with. One key file can be enrolled for many games.
Enrolling needs the signingKey:manage permission, which only owners and admins have. Whoever can enroll a key can publish builds, so keep this with the people who run the studio.
List a game's keys and their states:
depot keys list --game my-gameThis list is public: it's what launchers read to decide which keys to trust.
How players' launchers trust keys
- First install. When a player installs your game for the first time on a machine, the launcher trusts the game's keys that are active at that moment.
- Later keys. Keys you enroll after that aren't trusted by that installation. A release signed only with a newer key is refused there. A player using the CLI can accept new keys on purpose with
--trust-new-keys. - Revoked keys. A revoked key is dropped on the launcher's next check, and releases it signed are refused.
This is deliberate. If Depot's control plane were compromised, it couldn't enroll its own key and push builds to your existing players.
Rotate a key
There's no single rotate command. Rotation is: enroll a new key, push with it, then revoke the old one.
depot keys generate --out ~/.config/depot/keys/2027.json
depot keys enroll --game my-game --key ~/.config/depot/keys/2027.json
depot push --game my-game --platform windows-x64 --release 1.4.0 \
--input build/windows/ --key ~/.config/depot/keys/2027.json --channel stable
depot keys revoke --game my-game --key-id key_0123456789abcdef0123456789abcdefPlayers who installed before you enrolled the new key don't trust it. To keep rotation possible for them, enroll a second key before you launch and keep its private half offline. Players who install while both keys are active trust both, so you can switch to the backup key later without breaking their updates.
Revoke a key
depot keys revoke --game my-game --key-id key_0123456789abcdef0123456789abcdefRevoke a key as soon as you think its private half has leaked. Revoking takes effect right away:
- Depot refuses new releases signed with it.
- Launchers drop it on their next check and refuse every release it signed, including releases already on your channels.
Installed games keep working, because revocation stops downloads, not play. But players can't install, update or repair from a release signed only by the revoked key. Push the current build again, signed with a key they still trust, and move your channels to it.
Revoking needs signingKey:manage.
Sign offline
depot push signs for you with the local key file. If you drive the publishing API yourself, you can sign a release descriptor on a separate machine that holds the key, for example one that's never online:
depot sign --descriptor descriptor.json --key-id key_0123456789abcdef0123456789abcdef
depot sign --descriptor descriptor.json --key-id key_0123456789abcdef0123456789abcdef \
--key /path/to/key.jsonIt prints the descriptor and its signature as JSON:
{
"descriptor": { "schema": "depot.release/v1", "...": "..." },
"signature": { "key_id": "key_0123456789abcdef0123456789abcdef", "algorithm": "ed25519", "value": "…" }
}Send both to the upload session's finalize step (POST /v1/organizations/{org}/games/{id}/uploads/{sid}/finalize).
What gets signed
The descriptor is a small JSON object that pins everything about a release:
{
"schema": "depot.release/v1",
"game_id": "game_…",
"platform": "linux-x64",
"release_name": "1.2.0",
"sequence": 7,
"package": "base",
"protection": { "mode": "aes-256-gcm", "domain_id": "pd_…", "key_version": 1, "key_check": "c353…" },
"manifest": { "hash": "<sha256>", "size": 12345 },
"index": { "hash": "<sha256>", "size": 67890 },
"packs": [{ "hash": "<pack id>", "size": 134217728 }],
"created_at": "2026-11-01T12:00:00Z"
}The signature is Ed25519 over the bytes DEPOT-RELEASE-v1 followed by a zero byte, then the descriptor as RFC 8785 canonical JSON. Because the descriptor pins the hashes of the manifest, the index and every pack, the signature covers every byte of the build. It also pins the sequence number, so an old release can't be passed off as a new one, and the content key's check value, so a player's launcher can tell that the key it was given is the one you signed for.