Bring Your Own Key encryption for nSelf Cloud MAX tenants. Instead of using an nSelf-managed Key Encryption Key, BYOK connects your instance to an external key management service — AWS KMS, Google Cloud KMS, or HashiCorp Vault Transit — so that your team holds sole control over the master key. nSelf never stores or sees the KEK: encryption and decryption calls are proxied to the KMS at runtime. Revoking the key in your KMS immediately renders all encrypted data inaccessible.
BYOK requires the ɳCloud MAX plan. It is not available on ɳSelf+ or any per-bundle tier. BYOK is only meaningful in a Cloud-managed deployment where nSelf manages the infrastructure — self-hosted operators already control their own environment and should use the nself-vault plugin instead.
nself plugin install byok
nself build
nself start# AWS KMS
BYOK_PROVIDER=aws-kms
BYOK_AWS_KEY_ARN=arn:aws:kms:us-east-1:123456789012:key/mrk-...
BYOK_AWS_REGION=us-east-1
# Credentials via IAM role (preferred) or env vars:
# AWS_ACCESS_KEY_ID=AKIA...
# AWS_SECRET_ACCESS_KEY=...
# Google Cloud KMS
BYOK_PROVIDER=gcp-kms
BYOK_GCP_KEY_NAME=projects/my-project/locations/global/keyRings/nself/cryptoKeys/byok-key
BYOK_GCP_CREDENTIALS_JSON=/run/secrets/gcp-service-account.json
# HashiCorp Vault Transit
BYOK_PROVIDER=vault-transit
BYOK_VAULT_ADDR=https://vault.yourcompany.com
BYOK_VAULT_TOKEN=hvs.your-vault-token
BYOK_VAULT_TRANSIT_KEY=nself-byok| Variable | Required | Default | Description |
|---|---|---|---|
BYOK_PROVIDER | Yes | — | KMS provider: aws-kms, gcp-kms, vault-transit |
BYOK_ENCRYPT_RATE_RPM | No | 300 | Encrypt operations per minute (includes KMS API calls) |
BYOK_DECRYPT_RATE_RPM | No | 600 | Decrypt operations per minute |
BYOK_DEK_CACHE_SECONDS | No | 300 | Data Encryption Key cache TTL — reduces KMS calls for hot records |
BYOK_AUDIT_RETENTION_DAYS | No | 365 | BYOK operation audit log retention |
BYOK_KEY_VERSION_STRATEGY | No | latest | Key version pinning: latest or a specific key version identifier |
BYOK uses the same envelope encryption model as nself-vault: each encrypted record gets a unique Data Encryption Key (DEK). The DEK is wrapped not by a local KEK but by a call to your external KMS. The wrapped DEK and the ciphertext are stored in Postgres. Decryption calls the KMS to unwrap the DEK, then decrypts locally. The plaintext KEK never touches nSelf servers.
# Encrypt a value via REST
curl -X POST https://api.yoursite.com/byok/encrypt \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-d '{"plaintext": "sensitive-data", "context": {"record_id": "user-123"}}'
# Returns: {"ciphertext": "byok:v1:...", "key_version": "mrk-.../1"}
# Decrypt
curl -X POST https://api.yoursite.com/byok/decrypt \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-d '{"ciphertext": "byok:v1:...", "context": {"record_id": "user-123"}}'
# Returns: {"plaintext": "sensitive-data"}The plugin registers byokEncrypt, byokDecrypt, and byokRotate mutations on the Hasura Remote Schema. Frontend apps with appropriate JWT permissions can call them directly via GraphQL.
Disable or schedule-delete your key in the KMS. All subsequent decrypt calls fail immediately with a KMS access-denied error — nSelf cannot recover the data without the key, and neither can anyone else. This is by design: BYOK gives you a hard kill switch.
| Endpoint | Method | Description |
|---|---|---|
/byok/encrypt | POST | Encrypt a plaintext value with the configured KMS |
/byok/decrypt | POST | Decrypt a ciphertext value |
/byok/rotate | POST | Re-wrap all DEKs using the current (latest) KMS key version |
/byok/audit | GET | Query the immutable BYOK operation audit log |
/byok/health | GET | KMS connectivity check and key accessibility test |
np_byok_wrapped_deks — DEK ciphertexts wrapped by the KMS, associated to record IDsnp_byok_audit — immutable audit log of every encrypt, decrypt, and rotate operationEnterprise Plugin — ɳCloud MAX | Port: 3741 | v1.1.1