Harthelm Docs

Harthelm 1.3.0

What changed in Harthelm 1.3.0: Valkey, MariaDB, RabbitMQ and S3 object storage as managed services next to PostgreSQL, a managed service's secret as its own variable, in-cluster TLS for managed services.

Last updated 2026-10-19

Released 2026-10-14. API version 0.11.2. A minor release with one database migration, which only adds. Nothing needs to be done before the upgrade, but read Before you upgrade: every PostgreSQL database restarts once, and team quotas now count managed services at their full plan.

Terminal
helm upgrade harthelm oci://<your registry>/charts/harthelm --version 1.3.0 -n harthelm-system -f my-values.yaml

Before you upgrade

  • Every PostgreSQL database restarts once during the upgrade, for a few seconds. Its image is now pinned by tag and digest (PostgreSQL 17.11 and 18.6), so its minor version moves only with a Harthelm release, and each such release restarts the databases once. The services bound to a database no longer restart with it (Fixed).
  • The platform database restarts too. The console and the API are unavailable for about 30 seconds while it moves to its pinned image (PostgreSQL 18.6); workspaces and services keep running.
  • A team's quota counts a managed service at its full plan, CPU and memory, because its pods request the whole plan. Before, it counted only the share that workspaces and services request (by default 20 % of the CPU and 50 % of the memory), so the API could accept a database that Kubernetes then refused. Teams with several managed services may now reach their quota earlier: running services keep running, but creating, resuming or growing one can be refused with quota-exceeded. A cluster admin raises one team's quota on its Settings → Quota, and teams.quota sets the default (Quotas).

New

Four more managed services. Next to PostgreSQL, the catalog offers four more providers, all on by default:

ProviderIn the consoleWhat you getVersions
valkeyValkey (Redis-compatible)a cache or job queue; Redis clients read its redis:// URL unchanged9.1
mariadbMariaDBa database with its user, mysql:// URL and a JDBC URL in its details12.3, 11.8 (default), 11.4
rabbitmqRabbitMQa message broker with its own virtual host and user, amqp:// URL4.3
s3S3 object storagean S3-compatible store on SeaweedFS with the buckets you listone SeaweedFS release per Harthelm release

Each works like PostgreSQL: create it from the Catalog or as a type: managed service in harthelm.yml, Rotate its secret, and a workspace's Teardown pauses it while its data stays. Each is dumped every night unless you turn backups off, and each runs on air-gapped installations: its images are in images.txt. Every instance is one server, without replicas. See Managed services for the plans and settings.

  • Valkey keeps its data as snapshots (persistence: rdb, the default), writes every change to a log (aof), or keeps it in memory only (none: a restart or a pause empties it, and the console warns). maxmemoryPolicy decides what happens when the memory is full.
  • MariaDB moves to a newer series in place: change mariadbVersion from 11.4 to 11.8 or 12.3, or from 11.8 to 12.3. It never goes back, so dump it first; the console's confirmation offers Dump now.
  • RabbitMQ creates quorum queues by default (defaultQueueType; classic uses less memory). Its nightly backup keeps the topology (virtual host, users, queues, exchanges, bindings, policies), not the messages in the queues. When a later release stops shipping a series, Harthelm moves each broker to the next series by itself after a dump; that release's notes say so.
  • S3 object storage creates the buckets you list in buckets (up to 20, default data); publicBuckets makes some readable without a key, and bucketQuotaMiB caps each bucket. A bucket you remove from the list keeps its objects. Use path-style requests. Its nightly backup reads only the objects that changed since the last one.

${{ services.<name>.secret }}. A service reads a managed service's secret on its own: the password of PostgreSQL, MariaDB, Valkey and RabbitMQ, the secret access key of S3. Unlike ${{ secrets.<key> }} it follows a Rotate without a new Sync: the services that use it restart once the new value works.

harthelm.yml
  web:
    env:
      AWS_ENDPOINT_URL: ${{ services.files.dsn }}
      AWS_ACCESS_KEY_ID: ${{ services.files.details.accessKeyId }}
      AWS_SECRET_ACCESS_KEY: ${{ services.files.secret }}

In-cluster TLS for Valkey, RabbitMQ and MariaDB. Where in-cluster TLS is on and cert-manager is installed, each instance gets a certificate of the installation's internal CA. Valkey also listens with TLS on 6380, RabbitMQ on 5671 (AMQPS) and 15671 (its management API over HTTPS), and MariaDB offers TLS on its port 3306. The connection URLs stay plain, so apps connect as before; an app that wants TLS uses the TLS port and trusts the internal CA ($HART_INTERNAL_CA_FILE in a workspace). The nightly backups then always use TLS. A new instance waits for its certificate before it starts (at most two minutes), and a renewal, about every 75 days, restarts the server for a few seconds. S3 has no in-cluster TLS in 1.3.

S3 for browsers. Presigned URLs work through a forward service with one route per bucket, each without strip, and your dev domain as the endpoint. Keys with a space, +, % or a non-ASCII character work only on such routes, not behind a path prefix. See Managed services.

Changed

  • No browser-facing routes for managed services in 1.3. Reach RabbitMQ's management UI and S3 from a workspace, with a port-forward, or through a forward service behind your workspace's sign-in; see Managed services.
  • Managed services no longer reach the internet. Their pods reach their own team's namespace and DNS; nothing is downloaded at runtime.
  • A plan that needs a bigger volume on a storage class that cannot grow volumes is refused up front: the Sync reports update-constraint at the plan ("the storage class … cannot grow volumes; choose a plan with at most … or move the data to a new instance"), the API answers 422 volume-cannot-grow. Before, the change was accepted and the volume kept its size.
  • The Rotate dialog names the references that restart with the new secret, such as ${{ services.db.dsn }} and ${{ services.db.secret }}.

Fixed

  • A database restart no longer restarts the services bound to it. A managed database that restarted (after an upgrade, a node drain) restarted every service that used it, twice. Now they restart only when the connection itself changes: another host, port or user, or an applied Rotate.
  • IDE terminals always start bash. The editor's first window opened bash, every later window sh, without your .bashrc and what it sets up, such as the mirrors and the note on the Git identity.

For operators

The four new providers have one shape of values each, marketplace.builtin.valkey, .mariadb, .rabbitmq and .s3: enabled, the images pinned by tag and digest, storageClass, scheduling, overrides, and podMonitor for RabbitMQ and S3. Their volumes are ReadWriteOnce on the class you name, or the default class; the pods run as security.defaultUid with that number as their primary group and fsGroup, so NFS servers with manage-gids work. See Managed services.

Images from Docker Hub. The Valkey, MariaDB and RabbitMQ images come from Docker Hub, whose anonymous pulls are rate-limited per address. A cluster that creates many instances at once, or restarts them all at an upgrade, wants a login there (global.imagePullSecrets) or a mirror. images.txt and mirror.sh include every built-in provider's images.

hart admin doctor has four new checks: managed-images (each image's digest resolves), managed-storage (the classes allow volume expansion), managed-backups (the backup pods reach every enabled service, and every instance with backups on has a dump of the last 26 hours) and managed-tls (the certificates are issued and renewed). --capabilities lists managed-valkey, managed-mariadb, managed-rabbitmq and managed-s3.

Permissions. Core manages StatefulSets (the new providers' servers), and it may delete a managed service's pod that is stuck at an older revision and not ready; the admission guard allows that delete for managed-service pods only. The chart grants both.

Backups. The backup pods reach the new services' ports (and their TLS ports). A MariaDB instance is dumped with the client of its own server image, in a Job that core starts after the nightly run. An S3 snapshot is a list of objects plus their contents, which the snapshots of an instance share; an instance larger than backup.managed.s3.maxBytes (100 GiB by default) is recorded as a failed dump. See Backups and restore.

API 0.11.2. The change rule upgrade-only for a provider's version field (a newer version, a newer major too, never a lower one), and the 422 volume-cannot-grow of PATCH /managed-services/{ms}. Provider definitions may mark details that change while an instance runs with x-hart-volatile: true: a change of their value does not restart the services that use the instance. The migration adds a warning to backup records (a RabbitMQ dump that found feature flags not enabled).

Changed values

ValueChange
marketplace.builtin.valkey, .mariadb, .rabbitmq, .s3New, on by default. enabled: false hides a provider from the catalog; its existing instances keep running.
marketplace.builtin.postgres.imagesThe default images are now pinned by tag and digest (17.11 and 18.6).
database.bundled.smartShutdownTimeoutNew, default 15 seconds: how long the bundled database waits for open sessions when it restarts. It keeps the outage of an upgrade short.
backup.managed.s3.maxBytesNew, default 100 GiB: the largest S3 instance the nightly backup copies; 0 for no limit.

On this page