Files
unshackle/docs/reference/configuration/vaults.md
T
imSp4rky dc169f81e1 fix(vaults): stop querying sibling KIDs and skip unavailable vaults
The server CDM stub names only the manifest's KIDs; sibling keys stay content keys. API and HTTP vaults retry a 429, and a vault that is down or still rate limited costs one timeout per run.
2026-10-16 14:49:37 -06:00

3.2 KiB

Key vaults

The full guide is at Vaults. Two keys configure them.

key_vaults

  • Type: list[dict]  ·  Default: []

An ordered list of key-vault backends. unshackle queries them in order and reuses the content keys instead of licensing them again. Each entry needs a type (the backend module name) and a name, plus backend-specific keys.

type Purpose Required keys Notes
SQLite Local SQLite database name, path Loaded critically; a failure aborts the run.
MySQL Remote MySQL database name, host, database, username Extra keys (e.g. password, port) forwarded to pymysql. connect_timeout defaults to vault_timeout.
API RESTful JSON API name, uri, token Optional headers map is sent with every request. Honours vault_timeout.
HTTP HTTP API with modes name, host, one of password/api_key, and username in query mode api_mode: query (default), json, decrypt_labs. Honours vault_timeout.
key_vaults:
  - type: SQLite
    name: Local
    path: ~/.unshackle/keys.db
  - type: MySQL
    name: Team
    host: db.example.com
    database: keys
    username: unshackle
    password: hunter2
    no_push: false

!!! note "Per-entry options" - no_push: true makes a vault read-only (unshackle fetches content keys from it but never writes to it). - A vault of type: API whose name contains decrypt_labs auto-fills its token from decrypt_labs_api_key when not set inline. Vault type values are case-sensitive module names. - unshackle treats an all-zero content key (32 zeros) as "no key" everywhere and never stores it.

!!! note "Bad content keys" A content key from a vault is proven by short FFmpeg decodes of the decrypted output, with windows inside the fragments of each KID in a fragmented MP4. A content key that fails the decode is written to the bad_keys table of every SQLite vault with the name of the vault that supplied it, and every vault lookup skips a flagged pair from then on. A SQLite vault also refuses to store a flagged pair again. Only the SQLite backend stores flags; an API vault that supplied the pair gets a report. A serve instance with server_cdm flags a pair the same way when a remote client reports it, so a server whose key_vaults hold no SQLite entry cannot remember a bad content key.

vault_timeout

  • Type: float  ·  Default: 10.0

Timeout in seconds for vault operations. Injected automatically into any backend whose constructor accepts a timeout parameter (a per-vault timeout still wins). The MySQL backend uses it as the default connect_timeout.

The API and HTTP backends send a request again up to 3 times when the vault answers 429 Too Many Requests. They wait the Retry-After time, but never longer than this timeout. A connection failure or a timeout is not tried again. The run does not use a vault again after a connection failure, a timeout, or a 429 that continues after the retries, so a vault that is down costs one timeout per run.