Skip to content

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.

A secret holds sensitive material — API keys, tokens, certificates, passwords.

secrets:
- name: db-credentials
namespace: default
data:
- key: username
value: admin
- key: password
value: hunter2

Apply with rune cast. Or imperatively:

Terminal window
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.key

Rune uses envelope encryption:

plaintext ──▶ AES-256-GCM (DEK) ──▶ ciphertext ─┐
│ stored together
DEK ──▶ 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 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: enabled
Terminal window
rune create config app-settings \
--from-literal=log-level=info \
--from-file=app.toml=./config/app.toml
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/config

Each key becomes a file: /etc/secrets/db/username, /etc/config/log-level, etc.

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 alongside

Each key becomes an env var. Conflicts: explicit env: wins over envFrom:.

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:

Terminal window
rune restart api
Terminal window
rune get secrets
rune get secret db-credentials -o yaml # values are NOT printed
rune get configs
rune get config app-settings -o yaml

For 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:

FormSyntaxNamespace resolution
Shorthandsecret:<name>/<key>Same namespace as the consuming resource.
FQDNsecret:<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).

  • 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.