Skip to content

Add a Helm chart and Linux packages for Record Store - #105

Merged
danielmarv merged 3 commits into
mainfrom
fix-eslint-peer
Sep 25, 2026
Merged

danielmarv merged 3 commits into
mainfrom
fix-eslint-peer

Conversation

@danielmarv

@danielmarv danielmarv commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

What this adds

New ways to install Record Store, published with every release:

  • Debian and RPM packages for amd64 and arm64. They install the server and CLI, a hardened systemd unit, and a configuration file that upgrades never overwrite. On first install they generate credentials unique to the machine. Nothing starts until an operator enables the service.
  • Statically linked Linux archives (…-musl.tar.gz) next to the existing glibc ones. The glibc archives need Debian 12 or newer; the static ones run on any distribution.
  • A Helm chart, published to oci://ghcr.io/openelementslabs/charts/record-store and attached to the release for air-gapped installs. It runs one standalone server as a StatefulSet on its own volume and the console as a Deployment. The management API stays internal (ClusterIP only).

Docs: docs/deployment/kubernetes.md, docs/deployment/linux-packages.md, and an updated installation page.

What it deliberately does not do

  • No multi-node mode in the chart. The public docs make no multi-node claims, so the chart runs exactly one server pod. Setting replicaCount fails the install rather than being ignored. Multi-node support can come in its own PR together with the docs for it.
  • The static archives and the packages have no SLSA provenance. They are compiled in their own job, while the provenance check covers only the glibc archives taken from the attested image. The release notes say this and point to SHA256SUMS.
  • No macOS packages.

Limits a user needs to know

  • One pod means downtime. Upgrades, configuration changes and node drains stop the service until the pod is ready again. A failed node keeps the pod down until the node comes back or its Node object is deleted, because Kubernetes will not start a second pod against the same volume. The Kubernetes page explains this.
  • The packages run on Debian 11 and RHEL 8 or newer.

Why it is built this way

  • A StatefulSet, even for one pod. It never runs two pods against the same volume, even during an upgrade. A Deployment's rolling update can briefly run both, and two processes must never share a data directory.
  • The static builds are compiled on each architecture's own runner. The container image is glibc, so extracting from it would defeat the purpose, and a release build under QEMU takes about an hour.
  • The release installs and runs the packages before publishing. It installs the .deb on Debian 12, starts the server and waits for /ready, and installs the .rpm on Rocky 9. A broken maintainer script then fails the release, not the first operator's install.
  • CI lints the chart and checks every render variant against the Kubernetes schemas. It also asserts that every render has exactly one replica and no multi-node settings, and that replicaCount is refused. It then installs the chart on a kind cluster.

This branch includes a merge of main. The release job now waits for main's gates, provenance and release-decision jobs as well as linux-packages and chart.


  • cargo fmt, clippy, test, rust-audit: no Rust changes
  • mkdocs build --strict
  • bash tests/compatibility/run.sh: S3 surface unchanged
  • CHANGELOG.md updated under ## [Unreleased]
  • Documentation updated in this pull request
  • helm lint, all render variants and the chart invariants pass locally (the schema check needs Docker and runs in CI)
  • DOC-BOUNDARY passes locally
  • No claim added that is stronger than what the code guarantees

- Introduced a Helm chart for deploying Record Store on Kubernetes, including a values.yaml file for configuration.
- Added scripts for building .deb and .rpm packages for Record Store, ensuring they are statically linked and compatible with various Linux distributions.
- Created systemd service unit and configuration files for Record Store, ensuring proper permissions and security practices.
- Implemented post-install, pre-remove, and post-remove scripts to manage user and group creation, credential generation, and service management.
- Documented the deployment process for both Kubernetes and Linux packages, including installation, configuration, and upgrading procedures.

Signed-off-by: Ntege Daniel <danientege785@gmail.com>
Main moved the Rust audit and fuzz jobs into gates.yml and replaced the
release workflow's rust job with gates, so the Linux packages now build
after the gates, and the release waits for both packaging and the
release decision. Provenance covers only the glibc archives, and the
release notes now say so.
The public documentation makes no multi-node claims, and DOC-BOUNDARY
holds it to that. The chart no longer offers cluster mode: it runs
exactly one server pod, and setting replicaCount fails the render
instead of being ignored. The join-token init container, the peer port,
the pod disruption budget and the multi-node docs are gone.

The Kubernetes page now says what one pod means for availability,
including that a failed node keeps the pod down until the node returns
or is deleted.
@danielmarv
danielmarv merged commit 173c2c9 into main Sep 25, 2026
41 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant