Runesets
Runesets package multi-service applications with templating and values, like a small, opinionated Helm.
A runeset is a directory (or .runeset.tgz archive) that bundles several Rune resources behind a single template + values surface. Use them when one application is actually 3–10 services, secrets, and configmaps that ship together.
A runeset is the package; installing it produces a release — the stateful record of what was deployed. Every rune cast is tracked as a release, so you can list, diff, upgrade-with-prune, roll back, and uninstall it in one shot.
Anatomy
my-app/
├── runeset.yaml # metadata + default values
├── values/
│ └── values.yaml # values (every *.yaml here is merged)
├── casts/ # the templated resource files (required)
│ ├── api.yaml
│ ├── worker.yaml
│ └── secrets.yaml
├── templates/ # optional partials, included via {{ template: ... }}
│ └── common-labels.yaml.tmpl
└── README.md
runeset.yaml:
name: my-app
version: 1.2.0
description: API + worker + redis
namespace: default
defaults:
image:
tag: "1.2.0"
name doubles as the default release name, namespace as the default target namespace (-n overrides it), and defaults seeds the values map at the lowest precedence.
A cast (casts/api.yaml):
service:
name: api
image: "ghcr.io/example/api:{{ values:image.tag }}"
scale: {{ values:api.replicas | default: 2 }}
ports:
- name: http
port: 8080
Placeholders use {{ values:path.to.key }} for values, {{ context:releaseName }} / {{ context:namespace }} for install-time context, and | default: x for fallbacks. A referenced value that is missing (and has no default:) fails the render — typos surface before anything reaches the cluster. The full syntax is covered in Package a runeset.
Render before applying
Inspect what will be created:
rune cast ./my-app --render
rune cast ./my-app --render --set=image.tag=1.3.0
rune cast ./my-app --render --values=production.values.yaml
Install
rune cast ./my-app --release=my-app-prod --values=production.values.yaml
--release becomes the runeset's identity in the cluster — the release name (it defaults to the name in runeset.yaml). Re-running cast with the same release upgrades in place: Rune computes a 3-way plan (create / update / prune / adopt), shows it, and applies it after confirmation. Resources removed from the runeset are pruned; nothing is orphaned.
Operate the release
Once installed, manage it with rune release:
rune release list # all releases + revision + status
rune release status my-app-prod # owned resources, references, revision
rune release history my-app-prod # revision log
rune release diff my-app-prod # what a re-cast would change
rune release rollback my-app-prod --to 2
rune release delete my-app-prod --yes # uninstall everything it owns
Package and distribute
rune pack ./my-app -o my-app-1.2.0.runeset.tgz --sha256
Produces:
my-app-1.2.0.runeset.tgz— the bundle.my-app-1.2.0.runeset.tgz.sha256— checksum for verification.
Install from a URL or local archive:
rune cast https://example.com/my-app-1.2.0.runeset.tgz --release=my-app-prod
rune cast ./my-app-1.2.0.runeset.tgz --release=my-app-prod
Also supports git refs:
rune cast github.com/example/[email protected] --release=my-app-prod
Values precedence
Highest wins:
--set key=value(CLI flags)--values file.yaml(extra files, last one wins)RUNE_VALUES_*environment variablesvalues/*.yamlinside the runeset (merged in filename order)defaults:inruneset.yaml
Worked example
examples/runesets in the source tree has a working multi-service runeset you can study.
For a step-by-step walkthrough see Package a runeset.