Use any KMS
Protect TulipFarm operator settings and backups with SOPS and AWS KMS, GCP Cloud KMS, Azure Key Vault keys, Vault Transit, or age.
A key management service (KMS) holds a master key that never leaves it. You ask the KMS to encrypt or decrypt small values, and it checks your identity each time. TulipFarm never calls a KMS. Instead, you use a KMS to protect the files that hold TulipFarm’s settings:
- the operator settings file (
self-host/.env) - the
state.jsonbackup and other backups
This guide uses SOPS. SOPS works with AWS KMS, GCP KMS, Azure Key Vault keys, HashiCorp Vault Transit, and offline age keys.
How it works
Section titled “How it works”SOPS uses envelope encryption. It creates a random data key, encrypts each value with it, then asks every configured KMS key to encrypt the data key. The encrypted file stores the encrypted data key next to the values.
encrypt decrypt at startup .env ──▶ sops ──┬─ values ⟵ AES-256-GCM(data key) sops exec-env └─ data key ─▶ KMS ─▶ wrapped key ├─ wrapped key ─▶ KMS ─▶ data key │ └─ values ─▶ environment ─▶ docker compose tulipfarm.sops.env ◀──────┘ (safe to commit)Only someone whom the KMS authorizes can decrypt. You can commit the encrypted file to a private operations repository. The plaintext exists only in the environment of the process that SOPS starts.
Set up
Section titled “Set up”-
Install SOPS on the host.
-
Create
self-host/.sops.yamlwith one rule. Pick your provider from the provider table. This example lists two master keys, so either one can decrypt. Keep an offline age key for emergency recovery:creation_rules:- path_regex: \.sops\.(env|json)$kms: arn:aws:kms:us-east-1:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890abage: age1qyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqszqgpqyqs3290gq -
Encrypt the operator settings, then delete the plaintext:
Terminal window cp .env.example tulipfarm.env # fill it insops encrypt --filename-override tulipfarm.sops.env tulipfarm.env > tulipfarm.sops.envrm tulipfarm.env--filename-overridematches the.sops.yamlrule and selects the dotenv format. Values are taken literally, so$needs no quoting. -
Start TulipFarm with the decrypted values in the environment. Make sure no
self-host/.envexists:Terminal window sops exec-env tulipfarm.sops.env 'docker compose up -d --build' -
To change a value, run
sops edit tulipfarm.sops.env, then repeat step 4.
The host needs permission to decrypt, but not to encrypt. On cloud hosts, use the instance identity instead of stored keys.
Providers
Section titled “Providers”| KMS (SOPS docs) | .sops.yaml key |
Key format | Decrypt permission | Host credentials |
|---|---|---|---|---|
| AWS KMS | kms |
Key ARN | kms:Decrypt |
Instance role, or AWS_PROFILE |
| GCP Cloud KMS | gcp_kms |
projects/P/locations/L/keyRings/R/cryptoKeys/K |
roles/cloudkms.cryptoKeyDecrypter |
Attached service account, or gcloud auth application-default login |
| Azure Key Vault | azure_keyvault |
https://VAULT.vault.azure.net/keys/KEY/VERSION |
Key Vault Crypto User (unwrap key) | Managed identity, or az login |
| Vault / OpenBao Transit | hc_vault_transit_uri |
https://vault.example.com:8200/v1/transit/keys/tulipfarm |
update on transit/decrypt/tulipfarm |
VAULT_ADDR and VAULT_TOKEN |
| age | age |
age1… public key |
Holds the private key | SOPS_AGE_KEY_FILE |
age needs no cloud account. Use it for a laptop, a single server, or emergency recovery. Store its private key outside the server, for example in a password manager.
Encrypt backups
Section titled “Encrypt backups”Encrypt state.json as you export it, so the plaintext never reaches disk:
docker compose run --rm -T --no-deps --entrypoint cat setup /setup/state.json \ | sops encrypt --filename-override state.sops.json > state.sops.jsonRestore it on a new host:
sops decrypt state.sops.json \ | docker compose run --rm -T --no-deps --entrypoint sh setup -c 'umask 077 && cat > /setup/state.json'SOPS is designed for small structured files. For database dumps and volume archives,
use storage that encrypts with your KMS, such as S3 SSE-KMS, GCS CMEK, or Azure
customer-managed keys. Or stream the dump through age -r age1….
Rotate
Section titled “Rotate”| What | How |
|---|---|
| KMS master key | Enable automatic rotation in your KMS. Old key versions still decrypt, so you do nothing. |
| SOPS data key | sops rotate -i tulipfarm.sops.env creates a new data key and encrypts again. |
| Add or remove a master key | Edit .sops.yaml, then run sops updatekeys tulipfarm.sops.env. |
| A setting, such as an API key | sops edit tulipfarm.sops.env, then restart. |
| TulipFarm encryption keys | See key rotation. |
After you remove someone’s access, rotate the settings they could read. Old copies of the encrypted file still open with the old master keys.
Other ways to use a KMS
Section titled “Other ways to use a KMS”- Kubernetes: SOPS with Flux or Argo CD decrypts in the cluster. Or use the External Secrets Operator.
- Cloud secret managers: AWS Secrets Manager, Google Secret Manager, and Azure Key Vault secrets already encrypt with KMS. Choose your own key (CMEK) if you need control. Deliver values as described in Secret stores.
- Infisical: SOPS has no Infisical backend. Keep settings in Infisical secrets, which it encrypts for you. To encrypt a backup with your own key, use Infisical KMS through its encrypt and decrypt API, Infisical Cloud or self-hosted. Turn on Allow Export when you create the key: you can’t change it later, and without it you can’t move the key to another Infisical instance.