File Formats
Technical specification of all file formats used by kiln for configuration, keys, and encrypted data storage.
Configuration Format (TOML)
Section titled “Configuration Format (TOML)”kiln uses TOML for human-readable configuration with strong typing and validation.
File Structure
Section titled “File Structure”# Recipients with public keys[recipients]name = "public-key-string"
# Optional groups for access management[groups]group-name = ["recipient1", "recipient2"]
# Environment file definitions[files.environment-name]filename = "relative/path/to/file"access = ["recipient-or-group"]TOML Compliance
Section titled “TOML Compliance”- Version: TOML v1.0.0 compliant
- Encoding: UTF-8 required
- Comments:
#prefix supported throughout - Whitespace: Flexible indentation and spacing
- Case sensitivity: Keys are case-sensitive
Validation Rules
Section titled “Validation Rules”Section requirements:
[recipients]section is mandatory[files]section is mandatory[groups]section is optional
Data types:
- Recipient keys: strings (validated as public keys)
- Group members: arrays of strings
- File paths: strings (validated for security)
- Access lists: arrays of strings
Private Key Formats
Section titled “Private Key Formats”Age Private Keys
Section titled “Age Private Keys”Standard age format with X25519 elliptic curve cryptography.
AGE-SECRET-KEY-1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEFFormat specification:
- Prefix:
AGE-SECRET-KEY- - Encoding: Bech32
- Length: 74 characters total
- Key material: 32 bytes (256 bits)
File structure:
AGE-SECRET-KEY-1QYQQ5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5QQSSH Private Keys
Section titled “SSH Private Keys”Standard OpenSSH private key formats supported.
Ed25519 format:
-----BEGIN OPENSSH PRIVATE KEY-----b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAFwAAAAdzc2gtZWQyNTUxOQAAACAbcd...-----END OPENSSH PRIVATE KEY-----Legacy RSA format:
-----BEGIN RSA PRIVATE KEY-----MIIEpAIBAAKCAQEA1234567890abcdef...-----END RSA PRIVATE KEY-----Encrypted SSH keys:
- Passphrase-protected keys supported
- Prompts for passphrase during operation
- Uses standard SSH agent for key management
File Permissions
Section titled “File Permissions”Required permissions:
- Private keys:
0600(read/write owner only) - Public keys:
0644(read-only for others) - Configuration:
0644(readable by others)
Public Key Formats
Section titled “Public Key Formats”Age Public Keys
Section titled “Age Public Keys”age1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdefFormat specification:
- Prefix:
age1 - Encoding: Bech32 with age charset
- Length: 62 characters total
- Key material: 32 bytes public key
SSH Public Keys
Section titled “SSH Public Keys”Ed25519 format:
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGbM7ABCDEFGHIJKLMNOPQRSTUVWXYZ user@hostRSA format:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7... user@hostECDSA format:
ssh-ecdsa AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTY... user@hostFormat components:
- Algorithm identifier: Key type specification
- Key material: Base64-encoded public key
- Comment: Optional user@host identifier
Encrypted Environment Files
Section titled “Encrypted Environment Files”Environment files use age encryption with authenticated encryption.
File Structure
Section titled “File Structure”age-encryption.org/v1-> X25519 recipient1-public-key-> X25519 recipient2-public-key--- encrypted-payload ---base64-encoded-encrypted-datamore-base64-dataEncryption Details
Section titled “Encryption Details”Encryption algorithm:
- Key exchange: X25519 elliptic curve
- Symmetric encryption: ChaCha20-Poly1305 AEAD
- Key derivation: HKDF-SHA256
- MAC: Poly1305 authenticator
Security properties:
- Forward secrecy: Ephemeral key exchange
- Authentication: Prevents tampering
- Multiple recipients: Single file, multiple decryption keys
- Quantum resistance: X25519 provides post-quantum security
Payload Format
Section titled “Payload Format”The encrypted payload contains environment variables in standard format:
KEY1=value1KEY2=value with spacesKEY3="quoted value"# Comments are preservedMULTILINE_KEY=line1\nline2Payload rules:
- UTF-8 encoding required
- Unix line endings (
\n) normalized - Maximum file size: 10MB (practical limit)
- Variables follow shell environment syntax
Environment Variable Syntax
Section titled “Environment Variable Syntax”Standard Format
Section titled “Standard Format”# Simple assignmentDATABASE_URL=postgresql://localhost:5432/myapp
# Values with spaces (quotes optional)API_ENDPOINT=https://api.example.com/v1MESSAGE="Hello, World!"
# Empty valuesOPTIONAL_VAR=
# Comments (preserved during editing)# Database configurationDB_HOST=localhostDB_PORT=5432Validation Rules
Section titled “Validation Rules”Variable names:
- Pattern:
^[a-zA-Z_][a-zA-Z0-9_]*$ - Case-sensitive
- No length restrictions
- Must start with letter or underscore
Variable values:
- UTF-8 encoding
- Maximum length: 1MB per variable
- No null bytes allowed
- Newlines preserved as
\n
Parsing behavior:
- Quotes removed if present:
KEY="value"→value - Escaping supported:
KEY="value with \"quotes\""→value with "quotes" - Environment expansion not supported (values are literal)
Special Characters
Section titled “Special Characters”# Spaces and special charactersPATH="/usr/local/bin:/usr/bin:/bin"COMMAND="echo 'Hello World'"
# Newlines (escaped)MULTILINE="line1\nline2\nline3"
# Shell special characters (literal)REGEX="^[a-zA-Z]+$"JSON='{"key": "value", "number": 42}'JSON Import Format
Section titled “JSON Import Format”The set --from-file command accepts JSON files with specific type handling.
Supported Structure
Section titled “Supported Structure”{ "STRING_VAR": "text value", "NUMBER_VAR": 42, "FLOAT_VAR": 3.14, "BOOLEAN_VAR": true, "NULL_VAR": null}Type Conversion Rules
Section titled “Type Conversion Rules”String values: Used directly without modification Numeric values:
- Integers converted without decimal point:
42→"42" - Floats converted with appropriate precision:
3.14→"3.14"Boolean values: Converted to lowercase strings:true→"true",false→"false"Null values: Converted to empty strings:null→""Unsupported types: Arrays and objects cause validation errors
Validation Constraints
Section titled “Validation Constraints”- Maximum 1,000 variables per JSON file
- All variable names must follow standard validation rules
- File must contain at least one valid variable
- JSON syntax must be valid
Key Discovery Files
Section titled “Key Discovery Files”Discovery Order
Section titled “Discovery Order”- Explicit path:
--keyflag orKILN_PRIVATE_KEY_FILE - Age key:
~/.kiln/kiln.key - SSH Ed25519:
~/.ssh/id_ed25519 - SSH RSA:
~/.ssh/id_rsa
Public Key Derivation
Section titled “Public Key Derivation”For age keys:
# Private key file contains both private and publiccat ~/.kiln/kiln.key# AGE-SECRET-KEY-1234...# Public key: age1234567890abcdef...
# Public key in separate .pub filecat ~/.kiln/kiln.key.pub# age1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdefFor SSH keys:
# Public key in standard .pub filecat ~/.ssh/id_ed25519.pub# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGbM... user@hostCompatibility and Interoperability
Section titled “Compatibility and Interoperability”Age Tool Compatibility
Section titled “Age Tool Compatibility”kiln-encrypted files can be decrypted with standard age:
# Decrypt with age toolage --decrypt --identity ~/.kiln/kiln.key encrypted.env
# Encrypt with age tool for kilnage --encrypt --recipient age1234... --output encrypted.env plaintext.envSSH Agent Integration
Section titled “SSH Agent Integration”For SSH keys, kiln can integrate with SSH agent:
# Add key to agentssh-add ~/.ssh/kiln_key
# kiln will use agent if availablekiln get DATABASE_URLFile System Layout
Section titled “File System Layout”Standard Project Structure
Section titled “Standard Project Structure”project/├── kiln.toml # Configuration file├── .kiln.env # Default encrypted environment├── environments/│ ├── development.env # Development environment│ ├── staging.env # Staging environment│ └── production.env # Production environment├── keys/│ ├── team-lead.key # Private keys (not in VCS)│ └── team-lead.key.pub # Public keys (in VCS)└── .gitignore # Exclude private keysVersion Control Patterns
Section titled “Version Control Patterns”Include in VCS:
kiln.toml(configuration)*.env(encrypted environment files)*.pub(public key files)
Exclude from VCS:
# Private keys*.key!*.pub
# Temporary files.kiln-edit-**.tmpPerformance Characteristics
Section titled “Performance Characteristics”File Size Limits
Section titled “File Size Limits”| Component | Limit | Reason |
|---|---|---|
| Environment file | 10MB | Memory usage during decryption |
| Variable value | 1MB | Practical limit for environment variables |
| Configuration file | 1MB | TOML parser limitations |
| Recipients per file | 1000 | Encryption header size |
Encryption Overhead
Section titled “Encryption Overhead”- Header size: ~100 bytes + 64 bytes per recipient
- Encryption overhead: ~16 bytes (Poly1305 MAC)
- Base64 encoding: ~33% size increase
- Total overhead: ~50 bytes + ~33% of content size
Access Patterns
Section titled “Access Patterns”Optimized operations:
- Single file access (no cross-file operations)
- Sequential variable access within file
- Batch operations during editing
Performance considerations:
- Decryption required for any file access
- Re-encryption required for any modifications
- Memory usage scales with file size
Migration and Backup
Section titled “Migration and Backup”Configuration Export
Section titled “Configuration Export”# Backup all environments in JSON formatfor env in $(grep '^\[files\.' kiln.toml | sed 's/\[files\.//;s/\]//'); do kiln export --file "$env" --format json > "backup-${env}.json"doneRecovery Procedures
Section titled “Recovery Procedures”Corrupted encrypted files:
# Verify file integrityage --decrypt --identity ~/.kiln/kiln.key file.env >/dev/null
# If corrupted, restore from backupcp backup/file.env file.envInvalid configuration:
# Validate configuration syntaxtoml-lint kiln.toml
# Reset to default configurationkiln init config --forceKey Rotation Process
Section titled “Key Rotation Process”# Generate new keyskiln init key --path ./new.key
# Add to configurationkiln rekey --file production --add-recipient "newkey=$(cat ./new.key.pub)"
# Remove old keys (manual configuration edit required)