Jean-Gabriel Gill-Couture 89e5e104dc
All checks were successful
Run Check Script / check (push) Successful in 2m14s
Compile and package harmony_composer / package_harmony_composer (push) Successful in 8m22s
harmony-fleet-operator — release / release (push) Successful in 3m17s
feat(fleet): unify deploy config, switch CLI to tracing, fix OCI chart name collision
fleet-deploy:
- Rename harmony-fleet-release binary to harmony-fleet-publish
- Route all deploy settings through ConfigClient (env → OpenBao → prompt)
  instead of bespoke flags; seed FleetDeploySecrets via OpenBao
- Rename HARMONY_SECRET_NAMESPACE to HARMONY_CONFIG_NAMESPACE
- Append -chart to the Helm chart artifact name so it no longer collides
  with the Docker image in Harbor (application/vnd.cncf.helm.config.v1+json)

harmony_cli:
- Switch from log to tracing for structured output
- Defer topology prep so --list and declined runs are no-ops
- Drop ANSI colour codes around log emojis
- Init cli logger in fleet deploy binary

openbao:
- Scope unseal-keys cache file per instance
- Example gains setup capability and updated README

roadmap:
- Add unified CLI design document (ROADMAP/13-unified-cli.md)
- Update v0.3 fleet platform plan

Squashed commit of the following:

commit 36d9d9aaec
Merge: 12c8d9cf e7148aa8
Author: johnride <jg@nationtech.io>
Date:   Mon Jun 1 15:42:56 2026 +0000

    Merge pull request 'fix: fleet operator chart name was conflicting with the container name. Append -chart to the chart name' (#317) from fix/fleet-operator-chart-name into chore/rename-release-to-publish

    Reviewed-on: #317

commit e7148aa85f
Author: Jean-Gabriel Gill-Couture <jg@nationtech.io>
Date:   Mon Jun 1 11:35:15 2026 -0400

    fix: fleet operator chart name was conflicting with the container name. Append -chart to the chart name

commit 12c8d9cfa0
Author: Jean-Gabriel Gill-Couture <jg@nationtech.io>
Date:   Mon Jun 1 11:12:23 2026 -0400

    feat: Init cli logger in fleet deploy

commit edb62668b6
Author: Jean-Gabriel Gill-Couture <jg@nationtech.io>
Date:   Sun May 31 12:56:36 2026 -0400

    doc: Roadmap entry for cli design and implementation

commit f2ecccb4ab
Author: Jean-Gabriel Gill-Couture <jg@nationtech.io>
Date:   Sun May 31 12:32:19 2026 -0400

    refactor(fleet-deploy): rename harmony-fleet-release to harmony-fleet-publish

    Deploy/publish wording is more intuitive than deploy/release.

commit 2e9052b217
Author: Jean-Gabriel Gill-Couture <jg@nationtech.io>
Date:   Sun May 31 10:12:54 2026 -0400

    fix(openbao): remove extra blank line in example

    Pre-existing formatting issue caught by cargo fmt --check.

commit f7299ebe2b
Author: Jean-Gabriel Gill-Couture <jg@nationtech.io>
Date:   Sun May 31 09:13:39 2026 -0400

    refactor(fleet-deploy): rename HARMONY_SECRET_NAMESPACE to HARMONY_CONFIG_NAMESPACE

    The env var name was a misnomer — ConfigClient resolves both config and
    secrets, not just secrets. The struct field was already config_namespace.
    Legacy SecretManager keeps the old var; this forces migration to
    ConfigClient for new code.

commit d39aa15152
Author: Jean-Gabriel Gill-Couture <jg@nationtech.io>
Date:   Sun May 31 09:06:20 2026 -0400

    feat: fleet deploy uses configuration from configclient for all settings, update the 0_3 plan

commit 57d056fced
Author: Jean-Gabriel Gill-Couture <jg@nationtech.io>
Date:   Sat May 30 11:07:03 2026 -0400

    fix(openbao): scope unseal-keys cache file per instance

    The root token + unseal keys were written to a single fixed
    `~/.local/share/harmony/openbao/unseal-keys.json`, so deploying a second
    OpenBao instance (different namespace/release) overwrote the first's keys —
    after which the first could never be unsealed. Key the file by
    namespace+release (`unseal-keys-<ns>-<release>.json`); `cached_root_token`
    now takes the `OpenbaoInstance` to read the right one.

commit 44aa83199a
Author: Jean-Gabriel Gill-Couture <jg@nationtech.io>
Date:   Sat May 30 11:05:30 2026 -0400

    fix(harmony_cli): drop ANSI colour codes around log emojis

    `console::style(emoji).green()/.yellow()/.red()/.blue()` embedded raw ANSI
    escapes in the message string. `console` force-emits them off its own TTY
    detection, which disagrees with the tracing writer, so they leaked as literal
    `\x1b[..m` garbage around the emoji. Emit plain emojis — the glyph already
    conveys status and the tracing fmt layer still colours the level.

commit 4fef957edb
Author: Jean-Gabriel Gill-Couture <jg@nationtech.io>
Date:   Sat May 30 08:40:54 2026 -0400

    feat: Example openbao now can do openbao  setup and better readme

commit af3205d353
Author: Jean-Gabriel Gill-Couture <jg@nationtech.io>
Date:   Sat May 30 05:55:49 2026 -0400

    refactor(harmony_cli): defer topology prep so --list/declined runs are no-ops

    `Maestro::initialize` (hence `topology.ensure_ready()`) ran before `init`'s
    `--list` / confirmation short-circuits, so merely listing a binary's scores —
    or declining to run them — still prepared the topology (cert-manager install,
    etc.). Build the maestro unprepared and call `prepare_topology()` only once we
    commit to interpreting. Expose `Maestro::prepare_topology`; add tests proving
    `--list` skips prep while the run path triggers it.

commit 199e285e52
Author: Jean-Gabriel Gill-Couture <jg@nationtech.io>
Date:   Sat May 30 05:04:34 2026 -0400

    feat: Use tracing instead of logger in harmon_cli and  work on fleet_staging_install refactor to use harmony_cli properly, still some more work to do

commit fac83d853d
Author: Jean-Gabriel Gill-Couture <jg@nationtech.io>
Date:   Fri May 29 22:39:39 2026 -0400

    refactor(fleet-staging): use tracing instead of println for output

    Swap env_logger for tracing_subscriber (its fmt bridges the framework's
    log:: deploy-progress output) and route the install banner + step logs
    through tracing::info! — no raw println.

commit 0400e9d454
Author: Jean-Gabriel Gill-Couture <jg@nationtech.io>
Date:   Fri May 29 20:25:22 2026 -0400

    feat(fleet-staging): add OpenBao + seed FleetDeploySecrets; route operator creds through the deploy crate

    fleet_staging_install now deploys OpenBao (co-located in fleet-staging,
    cert-manager TLS at secrets-stg.<base>), configures it (fleet-deployer
    read policy), and seeds the operator's FleetDeploySecrets so the operator
    can be upgraded alone via 'harmony-fleet-deploy --from-tag'. Behavior of
    the existing bring-up is unchanged.

    Credential-TOML construction moved out of the example into
    OperatorCredentials::zitadel_jwt (deploy crate) so all callers share it.
    New openbao::cached_root_token() lets the seed reuse the root token setup
    already cached. Seeding mirrors the harmony_sso port-forward pattern.
2026-06-01 11:51:11 -04:00
2026-05-11 16:48:52 -04:00
2026-03-28 13:46:14 -04:00
2025-12-17 17:09:32 -05:00
2026-05-11 16:48:52 -04:00
2026-05-11 16:48:52 -04:00
2026-05-11 16:48:52 -04:00
2026-03-19 22:38:55 -04:00
2026-03-19 22:52:05 -04:00

Harmony

Infrastructure orchestration that treats your platform like first-class code.

Harmony is an open-source framework that brings the rigor of software engineering to infrastructure management. Write Rust code to define what you want, and Harmony handles the rest — from local development to production clusters.

By NationTech

Build License


The Problem Harmony Solves

Modern infrastructure is messy. Your Kubernetes cluster needs monitoring. Your bare-metal servers need provisioning. Your applications need deployments. Each comes with its own tooling, its own configuration format, and its own failure modes.

What if you could describe your entire platform in one consistent language?

That's Harmony. It unifies project scaffolding, infrastructure provisioning, application deployment, and day-2 operations into a single strongly-typed Rust codebase.


Three Principles That Make the Difference

Principle What It Means
Infrastructure as Resilient Code Stop fighting with YAML and bash. Write type-safe Rust that you can test, version, and refactor like any other code.
Prove It Works Before You Deploy Harmony verifies at compile time that your application can actually run on your target infrastructure. No more "the config looks right but it doesn't work" surprises.
One Unified Model Software and infrastructure are one system. Deploy from laptop to production cluster without switching contexts or tools.

How It Works: The Core Concepts

Harmony is built around three concepts that work together:

Score — "What You Want"

A Score is a declarative description of desired state. Think of it as a "recipe" that says what you want without specifying how to get there.

// "I want a PostgreSQL cluster running with default settings"
let postgres = PostgreSQLScore {
    config: PostgreSQLConfig {
        cluster_name: "harmony-postgres-example".to_string(),
        namespace: "harmony-postgres-example".to_string(),
        ..Default::default()
    },
};

Topology — "Where It Goes"

A Topology represents your infrastructure environment and its capabilities. It answers the question: "What can this environment actually do?"

// Deploy to a local K3D cluster, or any Kubernetes cluster via environment variables
K8sAnywhereTopology::from_env()

Interpret — "How It Happens"

An Interpret is the execution logic that connects your Score to your Topology. It translates "what you want" into "what the infrastructure does."

The Compile-Time Check: Before your code ever runs, Harmony verifies that your Score is compatible with your Topology. If your application needs a feature your infrastructure doesn't provide, you get a compile error — not a runtime failure.


What You Can Deploy

Harmony ships with ready-made Scores for:

Data Services

  • PostgreSQL clusters (via CloudNativePG operator)
  • Multi-site PostgreSQL with failover

Kubernetes

  • Namespaces, Deployments, Ingress
  • Helm charts
  • cert-manager for TLS
  • Monitoring (Prometheus, alerting, ntfy)

Bare Metal / Infrastructure

  • OKD clusters from scratch
  • OPNsense firewalls
  • Network services (DNS, DHCP, TFTP)
  • Brocade switch configuration

And more: Application deployment, tenant management, load balancing, and more.


Quick Start: Deploy a PostgreSQL Cluster

This example provisions a local Kubernetes cluster (K3D) and deploys a PostgreSQL cluster on it — no external infrastructure required.

use harmony::{
    inventory::Inventory,
    modules::postgresql::{PostgreSQLScore, capability::PostgreSQLConfig},
    topology::K8sAnywhereTopology,
};

#[tokio::main]
async fn main() {
    let postgres = PostgreSQLScore {
        config: PostgreSQLConfig {
            cluster_name: "harmony-postgres-example".to_string(),
            namespace: "harmony-postgres-example".to_string(),
            ..Default::default()
        },
    };

    harmony_cli::run(
        Inventory::autoload(),
        K8sAnywhereTopology::from_env(),
        vec![Box::new(postgres)],
        None,
    )
    .await
    .unwrap();
}

What this actually does

When you compile and run this program:

  1. Compiles the Harmony Score into an executable
  2. Connects to K8sAnywhereTopology — which auto-provisions a local K3D cluster if none exists
  3. Installs the CloudNativePG operator into the cluster (one-time setup)
  4. Creates a PostgreSQL cluster with 1 instance and 1 GiB of storage
  5. Exposes the PostgreSQL instance as a Kubernetes Service

Prerequisites

  • Rust (edition 2024)
  • Docker (for the local K3D cluster)
  • kubectl (optional, for inspecting the cluster)

Run it

# Clone the repository
git clone https://git.nationtech.io/nationtech/harmony
cd harmony

# Build the project
cargo build --release

# Run the example
cargo run -p example-postgresql

Harmony will print its progress as it sets up the cluster and deploys PostgreSQL. When complete, you can inspect the deployment:

kubectl get pods -n harmony-postgres-example
kubectl get secret -n harmony-postgres-example harmony-postgres-example-db-user -o jsonpath='{.data.password}' | base64 -d

To connect to the database, forward the port:

kubectl port-forward -n harmony-postgres-example svc/harmony-postgres-example-rw 5432:5432
psql -h localhost -p 5432 -U postgres

To clean up, delete the K3D cluster:

k3d cluster delete harmony-postgres-example

Environment Variables

K8sAnywhereTopology::from_env() reads the following environment variables to determine where and how to connect:

Variable Default Description
KUBECONFIG ~/.kube/config Path to your kubeconfig file
HARMONY_AUTOINSTALL true Auto-provision a local K3D cluster if none found
HARMONY_USE_LOCAL_K3D true Always prefer local K3D over remote clusters
HARMONY_PROFILE dev Deployment profile: dev, staging, or prod
HARMONY_K8S_CONTEXT none Use a specific kubeconfig context
HARMONY_PUBLIC_DOMAIN none Public domain for ingress endpoints

To connect to an existing Kubernetes cluster instead of provisioning K3D:

# Point to your kubeconfig
export KUBECONFIG=/path/to/your/kubeconfig
export HARMONY_USE_LOCAL_K3D=false
export HARMONY_AUTOINSTALL=false

# Then run
cargo run -p example-postgresql

Documentation

I want to... Start here
Understand the core concepts Core Concepts
Deploy my first application Getting Started Guide
Explore available components Scores Catalog · Topologies Catalog
See a complete bare-metal deployment OKD on Bare Metal
Build my own Score or Topology Developer Guide

Why Rust?

We chose Rust for the same reason you might: reliability through type safety.

Infrastructure code runs in production. It needs to be correct. Rust's ownership model and type system let us build a framework where:

  • Invalid configurations fail at compile time, not at 3 AM
  • Refactoring infrastructure is as safe as refactoring application code
  • The compiler verifies that your platform can actually fulfill your requirements

See ADR-001 · Why Rust for our full rationale.


Architecture Decisions

Harmony's design is documented through Architecture Decision Records (ADRs):


License

Harmony is released under the GNU AGPL v3.

We choose a strong copyleft license to ensure the project—and every improvement to it—remains open and benefits the entire community.

See LICENSE for the full text.


Made with ❤️ & 🦀 by NationTech and the Harmony community

Description
No description provided
Readme AGPL-3.0 3.5 GiB
Languages
Rust 97%
Shell 1.5%
HTML 0.8%
Python 0.2%
Jinja 0.2%
Other 0.3%