Encryption
How OpsKnight encrypts sensitive credentials and how to configure the master key
Encryption
OpsKnight encrypts sensitive secrets — SSO client secrets, Slack tokens, VAPID keys, SMTP passwords, and API keys — at rest using AES-256-CBC Envelope Encryption.
How It Works
OpsKnight uses a two-layer Envelope Encryption model (V2):
ENCRYPTION_KEY (Master Key — from env var)
│
▼
Encrypt a unique DEK (Data Encryption Key) per secret
│
▼
DEK encrypts the actual secret
│
▼
Stored in database: v2:<dekIv>:<encryptedDek>:<payloadIv>:<encryptedPayload>
Why Envelope Encryption?
- The master key only ever encrypts small DEKs, not the raw secrets directly.
- Each secret has its own unique DEK — compromising one ciphertext does not expose others.
- Fast key rotation: only DEKs need re-encryption, not the entire dataset.
Setting the Encryption Key
The master encryption key is configured entirely through the ENCRYPTION_KEY environment variable. There is no UI for key management — this is intentional and follows 12-factor app security best practices: credentials belong in the environment, not in the database.
Generating a Key
# Generate a cryptographically secure 32-byte (256-bit) hex key
openssl rand -hex 32
This outputs a 64-character hex string, for example:
a3f1c2e4b5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2
Setting the Variable
Docker Compose / .env file:
# .env
ENCRYPTION_KEY=a3f1c2e4b5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2
Kubernetes Secret:
kubectl create secret generic opsknight-secrets \
--from-literal=ENCRYPTION_KEY=$(openssl rand -hex 32)
Then reference it in your deployment:
env:
- name: ENCRYPTION_KEY
valueFrom:
secretKeyRef:
name: opsknight-secrets
key: ENCRYPTION_KEY
Helm values:
secrets:
ENCRYPTION_KEY: 'your-64-char-hex-key'
Security: Never commit the
ENCRYPTION_KEYvalue to source control. Use a secrets manager (AWS Secrets Manager, HashiCorp Vault, GCP Secret Manager) in production.
Development Mode
When NODE_ENV=development and ENCRYPTION_KEY is not set, OpsKnight automatically falls back to a stable, well-known developer key. This means:
- Local development works out of the box with zero configuration.
- No secrets are at risk — the dev key is not secret and is only used for local testing.
- A warning is printed to the server console so you know it's active.
Do not use the development fallback in production. Always set
ENCRYPTION_KEYexplicitly in any environment that stores real credentials.
What Gets Encrypted
The following fields are encrypted at rest before being written to the database:
| Integration | Field(s) Encrypted |
|---|---|
| SSO / OIDC | clientSecret |
| Slack | botToken, signingSecret |
| Slack OAuth | clientSecret |
| Twilio | authToken, whatsappAuthToken |
| AWS SNS / SES | secretAccessKey |
| Resend | apiKey |
| SendGrid | apiKey |
| SMTP | password |
| Web Push | vapidPrivateKey |
Fields not in this list (e.g., public keys, provider names, account SIDs) are stored in plaintext.
Key Rotation
Key rotation is the process of replacing your master key with a new one. Since OpsKnight uses envelope encryption, rotation requires re-encrypting the per-secret DEKs — the raw secrets themselves do not change.
Steps
-
Generate a new key:
openssl rand -hex 32 -
Decrypt existing secrets with the old key (using your own tooling or a migration script that calls
decryptWithKey(ciphertext, oldKey)). -
Re-encrypt each secret with the new key (
encryptWithKey(plaintext, newKey)). -
Update
ENCRYPTION_KEYin your deployment environment or secrets manager. -
Redeploy the application.
If you use a secrets manager that supports automatic secret rotation (e.g., AWS Secrets Manager), point
ENCRYPTION_KEYto the latest version and redeploy. No data migration is needed if you manage rotation at the secrets manager level with version-aware decryption.
Rotation Frequency
We recommend rotating the encryption key:
- Every 90 days as a baseline cadence
- Immediately after a suspected key compromise
- When an admin with key access leaves the organization
Migrating from v1.0.0
In OpsKnight v1.0.0, the encryption key could be stored directly in the SystemSettings database table via the System Settings UI. That feature has been removed in v1.1.0.
If you previously set a key via the UI, here's how to migrate without losing data:
-
Retrieve the key that was stored in the database:
SELECT "encryptionKey" FROM "SystemSettings" WHERE id = 'default'; -
Set it as the
ENCRYPTION_KEYenvironment variable in your deployment. -
Redeploy. All existing encrypted data will continue to decrypt correctly — the cryptographic format is unchanged.
There is no need to re-encrypt existing data. The underlying AES-256-CBC envelope encryption format is identical. Only the source of the key has changed (from DB → env var).
Security Considerations
| Concern | Recommendation |
|---|---|
| Key storage | Use a secrets manager; never hardcode in source control |
| Key backup | Keep at least one encrypted backup of the key in a safe place |
| Key access | Restrict who can read ENCRYPTION_KEY in your secrets manager |
| Loss of key | Encrypted data is permanently unrecoverable without the key |
| Same key in dev and prod | Use distinct keys per environment |
FAQ
Q: What happens if ENCRYPTION_KEY is not set in production?
The application starts normally, but any attempt to save an encrypted secret (SSO client secret, Slack token, etc.) will fail with an error. Existing encrypted data cannot be read. The rest of the application continues to function.
Q: Can I use a key shorter than 64 hex characters?
No. The key must be exactly 64 hexadecimal characters (representing 32 bytes / 256 bits). Any other format is rejected at startup.
Q: What if I lost the key?
Encrypted data is permanently unrecoverable without the master key. You will need to set a new key and manually re-enter all integration secrets (SSO, Slack, notification providers) through the UI.
Q: Is data encrypted in transit as well?
Encryption at rest (this feature) is separate from encryption in transit (TLS/HTTPS). Always run OpsKnight behind HTTPS in production.
Q: Can I verify that the correct key is configured?
If your SSO or Slack integrations are functioning correctly, the key is working. You can also attempt to save and load an integration credential — a decryption error in the server logs indicates a key mismatch.
Related Topics
- OIDC SSO Setup — Single sign-on configuration
- Configuration Reference — All environment variables
- Authentication — Authentication methods and session management
Last updated for v1.1
Edit this page on GitHub