Skip to main content
The entire destination URL is a secret, including its path and query. This matters for Discord because the webhook token is part of the URL. All custom header values are also secret.

Write-only credentials

You enter secrets when creating a destination. After saving, neither list nor save responses return them, and the editor clears its secret inputs. The UI shows only whether a URL or headers are configured. Editing non-secret fields with blank secret inputs preserves the saved credentials. Enter a new URL or headers object to replace saved values. Clear saved headers removes all headers; an API update with "headers": {} does the same. Delete a destination to remove its current stored configuration. Deletion does not revoke its token at the external service or securely erase old copies of the encrypted file. Only admins can list, save, test, or delete integrations. A scoped automation token needs manage permission and an admin account. API responses use Cache-Control: no-store. Secrets aren’t placed in browser storage, ordinary settings payloads, or the settings database by the new integration feature.

Encryption on disk

Each app writes an authenticated AES-256-GCM encrypted file at:
By default, it generates its own random encryption key at /config/integrations/key on the first save. Integration files use owner-only permissions where supported. Native installs use the integrations folder beneath that app’s configuration directory; protect it with filesystem permissions or Windows ACLs. Keeping the default key alongside the ciphertext protects against exposure of the ciphertext alone. Someone who obtains both can decrypt it. Container and host administrators, a compromised app process, and trusted scripts with filesystem access can read the key. This is separate from the Scout key used to encrypt backup snapshots. For stronger separation, supply INTEGRATIONS_KEY_FILE pointing to a mounted key. It must contain exactly 64 hexadecimal characters, with optional surrounding whitespace. The app never creates or overwrites an external key.

Mount an external key with Compose

Generate a separate key for each app on the deployment host:
Add this to the existing app service and the top level of its Compose file. For Scout use the scout service name; for Station use station:
Recreate the service after updating Compose. Supply the key before the first integration is saved. To move an existing installation to an external key, securely copy its existing /config/integrations/key into the mounted file and configure that path. Generating a different key does not rotate existing ciphertext. Compose mounts file secrets into the service; it doesn’t encrypt the source file on the host. Keep the file private, outside source control, and outside selected Scout backup jobs. See Docker’s secret guide for deployment details. In Kubernetes, adapt the Scout example to mount your operator-managed Secret and set INTEGRATIONS_KEY_FILE; do not put a usable secret in manifests committed to Git.

Backup and recovery

Preserve destinations.enc and the matching key. Losing the key makes the saved destinations unreadable. Startup fails if existing ciphertext cannot be decrypted; it doesn’t replace a missing key with a new one. With an external key, back that key up separately under your own secret-management process. Scout’s configuration and Scout key remain included when that folder is part of a backup job. This also includes the default integration key, so protect those encrypted snapshots and the Scout key needed to restore them. Integration secrets are not runtime directories and are not automatically excluded. To recover, restore the encrypted file and its matching key, then restart the app. If the key is irretrievably lost, stop the app, retain the old integration files privately if needed, remove or move the integrations folder out of the config directory, and reconfigure destinations with new external-service credentials. This affects integration settings, not backup snapshots.

Secrets used by custom scripts

Prefer the built-in HTTP delivery for notifications: it controls credential handling and error output. For a script that needs its own secret, mount a read-only file outside /hook-scripts, and have the script read that file. Uploaded scripts and configured commands can be viewed through authenticated APIs, so don’t embed tokens there. The hook runner discards standard output and standard error and logs only timeout or failure outcomes. A script can still write secrets to files or send them over the network, and it inherits the app environment. Run only trusted scripts. Avoid shell tracing and HTTP debug output, and keep any script-managed logs private. With curl, configuration files let it read credential-bearing options without putting their values in command-line arguments.