Skip to content

State & Encryption

Kyku stores infrastructure state in JSON files under the .kyku/ directory. Sensitive fields are automatically encrypted.

State is stored per environment:

.kyku/
├── state.json (default environment)
├── state.dev.json (--env=dev)
├── state.prod.json (--env=prod)
└── .kyku.lock (process lock)

Each state file contains:

{
"version": "1",
"environment": "default",
"encrypted": true,
"encryptionMeta": { ... },
"metadata": { "prefix": "a3f27b1d" },
"resources": {
"vm-web": {
"type": "Vm",
"provider": "aws",
"providerId": "i-0abc123456",
"config": { ... },
"dependencies": ["vpc-main"],
"outputs": { "instanceId": "i-0abc123456" },
"createdAt": "...",
"updatedAt": "..."
}
}
}

State encryption uses AES-256-GCM with PBKDF2 key derivation via the Web Crypto API.

KYKU_PASSPHRASE → PBKDF2 (600k iterations, SHA-256) → AES-256-GCM key

The encryption engine detects sensitive fields by name (password, secret, token, key, private, sshPrivateKey, certificate, apiKey, accessKey, secretKey, signingKey, connectionString) and encrypts their values. Non-sensitive fields (instance types, CIDRs, names) remain in plaintext.

Terminal window
# Environment variable
export KYKU_PASSPHRASE="your-secure-passphrase"
# CLI flag
kyku plan --passphrase "your-secure-passphrase"
# File (env var or CLI flag)
export KYKU_PASSPHRASE_FILE=/path/to/passphrase.txt
kyku plan --passphrase-file /path/to/passphrase.txt
# Interactive (TTY only)
# If no passphrase is provided, Kyku prompts for one

The plan command works without a passphrase — secrets are shown as [encrypted]:

password: [encrypted]

The apply command requires a passphrase to decrypt secrets before sending them to the cloud provider.

Because encryption is field-level and non-sensitive fields remain readable, state files are safe to commit to version control. Only secrets are opaque.

Terminal window
kyku output --show-secrets

This decrypts and displays all outputs, including sensitive ones.

Kyku uses a file-based lock (.kyku/.kyku.lock) with PID and timestamp to prevent concurrent operations. Stale locks older than 5 minutes are automatically broken.

See the state CLI commands for listing, showing, and removing resources from state.