Secrets & ConfigMaps
Both secrets and configmaps are namespaced key-value resources you mount into services. They differ in one important way: secrets are encrypted at rest.
Secrets
Section titled “Secrets”A secret holds sensitive material — API keys, tokens, certificates, passwords.
secrets: - name: db-credentials namespace: default data: - key: username value: admin - key: password value: hunter2Apply with rune cast. Or imperatively:
rune create secret db-credentials \ --from-literal=username=admin \ --from-literal=password=hunter2
rune create secret tls-cert \ --from-file=tls.crt=./certs/server.crt \ --from-file=tls.key=./certs/server.keyHow secrets are encrypted
Section titled “How secrets are encrypted”Rune uses envelope encryption:
plaintext ──▶ AES-256-GCM (DEK) ──▶ ciphertext ─┐ │ stored togetherDEK ──▶ AES-256-GCM (KEK) ──▶ wrapped DEK ─┘- A 32-byte KEK (Key Encryption Key) is loaded once on server start from a file, env var, or generated and persisted with mode
0600. - A fresh DEK (Data Encryption Key) is generated for every secret version.
- Associated data binds the ciphertext to
(namespace, name, version)— moving bytes around the database breaks decryption.
Consequence: lose the KEK, lose every secret. Back it up.
See Security hardening for KEK rotation guidance.
ConfigMaps
Section titled “ConfigMaps”ConfigMaps are the same shape as secrets — namespaced key-value pairs — but stored in plaintext. Use them for non-sensitive config (log levels, feature flags, service URLs).
configmaps: - name: app-settings namespace: default data: - key: log-level value: info - key: feature-x value: enabledrune create config app-settings \ --from-literal=log-level=info \ --from-file=app.toml=./config/app.tomlConsuming from a service
Section titled “Consuming from a service”Mount as files
Section titled “Mount as files”service: name: api image: ghcr.io/example/api:1.0.0 secretMounts: - name: db-secret secretName: db-credentials mountPath: /etc/secrets/db configMounts: - name: app-config configName: app-settings mountPath: /etc/configEach key becomes a file: /etc/secrets/db/username, /etc/config/log-level, etc.
Mount as environment variables
Section titled “Mount as environment variables”service: name: api image: ghcr.io/example/api:1.0.0 envFrom: - secretRef: db-credentials - configRef: app-settings env: LOG_FORMAT: json # plain env vars still work alongsideEach key becomes an env var. Conflicts: explicit env: wins over envFrom:.
Updating values
Section titled “Updating values”Re-apply with rune cast. The secret/configmap version increments. Services that mount it pick up the new value on the next instance restart — Rune does not hot-reload mounted files.
To roll services after a config change:
rune restart apiListing and inspecting
Section titled “Listing and inspecting”rune get secretsrune get secret db-credentials -o yaml # values are NOT printedrune get configsrune get config app-settings -o yamlFor secrets, only metadata comes back. There’s no API to read plaintext — the only way out is to mount it into a service.
Referencing a secret from another resource
Section titled “Referencing a secret from another resource”A few places outside a service spec (notably StorageClass parameters)
accept a string-form secret reference instead of a literal value.
Two forms:
| Form | Syntax | Namespace resolution |
|---|---|---|
| Shorthand | secret:<name>/<key> | Same namespace as the consuming resource. |
| FQDN | secret:<name>.<namespace>.rune/<key> | Explicit namespace — independent of the consumer. |
Reach for the FQDN form whenever the consuming resource is cluster-scoped (e.g. a StorageClass shared across namespaces) or when you want one secret to serve many namespaces. Shorthand is fine inside a namespaced resource that already has its own namespace (a Volume override, for example).
Naming and limits
Section titled “Naming and limits”- Names must match DNS-1123 (
[a-z0-9]([-a-z0-9]*[a-z0-9])?). - Per-secret data limits are enforced server-side (configurable in the runefile).
- Total number of versions kept per secret is also configurable — older versions are garbage-collected.