Skip to content

A TypeScript framework for building reusable, type-safe Kubernetes infrastructure — without the YAML mess.

License

Notifications You must be signed in to change notification settings

thaitype/kubricate

Repository files navigation

kubricate-logo

Kubricate

A TypeScript framework for building reusable, type-safe Kubernetes infrastructure — without the YAML mess.

Build NPM Version npm downloads

Kubricate is preparing to release its first stable version as v1 release soon. API will be not changed Checkout v1 Milestone for more details: v1 Milestone

✨ Features

  • 📦 Type-safe Kubernetes Manifest Generation:

    • Define Kubernetes resources using fully-typed TypeScript objects — with support for reuse, composition, and validation in your IDE.
  • 🧱 Stack-Based Architecture:

    • Group related resources together into reusable Stacks — such as Deployment + Service, or Namespace + RoleBinding. Easily parameterize and extend them across environments.
  • 🔐 Declarative Secret Management:

    • Declare secrets with addSecret({ name }), and hydrate them from multiple backends like .env, Azure Key Vault, 1Password, or Vault — all within your CI/CD pipeline.
  • ♻️ Connectors and Providers:

    • Use Connectors to read/write secrets from systems, and Providers to convert secrets into Kubernetes-native resources (like Secret, ConfigMap, or ExternalSecret).
  • 🚀 CLI-Friendly & GitOps Ready:

    • Run kubricate generate and kubricate secrets apply to validate, sync, and render your infrastructure as YAML — without running anything in your cluster.
  • 🧪 First-Class Dev Experience:

    • Enjoy full IDE autocomplete, refactor support, type checking, and linting across your entire platform configuration — all in TypeScript.

🧭 Motivation

💥 The Problem

Secret management in Kubernetes is fragmented, repetitive, and error-prone. In production environments, teams often deal with:

  • Manually duplicating Secret manifests across environments
  • Templating secret references with Helm or Kustomize
  • Managing complex ExternalSecret or Vault annotations spread across YAML files
  • Relying on runtime injectors or sidecars with unclear debugging paths
  • No clear way to track which secrets are used, where they come from, or who owns them

These patterns result in:

  • ❌ Too much untyped YAML
  • ❌ Difficult-to-test deployments
  • ❌ Poor visibility into secret flow
  • ❌ Secrets being treated as runtime config, not infrastructure

🔍 Existing Solutions (and Limitations)

Tool Strengths Weaknesses
External Secrets Operator (ESO) Reconciles secrets from cloud backends Heavy YAML usage, CRDs, hard to reuse or test
Vault Agent Injector Dynamic injection at runtime Requires sidecars, annotations, Vault policy setup
SOPS / Sealed Secrets GitOps-safe encryption Complex rotation/versioning, no unified source of truth
Helm values + .env Familiar templating No type safety, validation, or traceability

💡 Kubricate’s Approach

Kubricate doesn't replace those tools — it replaces the YAML, glue logic, and guesswork needed to make them work.

Instead of defining secrets across many values.yaml, CRDs, and annotations, Kubricate gives you:

  • ✅ Type-safe secret declarations in code: addSecret({ name: 'API_KEY' })
  • ✅ Secret hydration plans that describe where secrets come from and where they go
  • ✅ Plug-in Connectors to load secrets from .env, 1Password, Vault, or any backend
  • ✅ The ability to generate YAML, ExternalSecret CRDs, or annotations with confidence

Kubricate focuses on design-time control, not runtime magic:

  • You define the truth in TypeScript
  • You hydrate secrets as part of your pipeline
  • You generate manifests, not YAML by hand

Whether you're using ArgoCD, ESO, Vault, or no controller at all — Kubricate makes the configuration safe, testable, and understandable by everyone on your team.


Getting Started

To begin, create a new project using Bun, which provides a fast setup with built-in TypeScript support:

mkdir first-stack
cd first-stack
bun init -y

Then, install the Kubricate CLI:

bun add -d kubricate

Kubricate is designed to work with standard Node.js environments, but it works well with Bun, too. You can also use it with any package manager — npm, yarn, or pnpm — depending on your workflow. When using Bun, simply run CLI commands with bun.

Then, create your first Kubricate Stack. Kubricate Stacks help you define, reuse, and manage Kubernetes resources in a clean, declarative way.

1. 🧱 Example: Creating a Namespace Stack

// @filename: src/stacks.ts
import { Stack } from 'kubricate';

export const myNamespace = Stack.fromStatic('Namespace', {
  // you can write any name of the resource in the stack
  namespace: {
    apiVersion: 'v1',
    kind: 'Namespace',
    metadata: {
      name: 'my-namespace',
    },
  },
});

2. ⚙️ Configure with kubricate.config.ts

Create a kubricate.config.ts file at the root of your project:

// @filename: kubricate.config.ts
import { defineConfig } from 'kubricate';
import { myNamespace } from './src/stacks';

export default defineConfig({
  stacks: {
    myFirstStack: myNamespace,
  },
});

3. 🚀 Generate Kubernetes Resources

bun kubricate generate

This will generate Kubernetes YAML files in the output folder:

Generating stacks...
• Written: output/myFirstStack.yml
✔ Generated 1 file into "output/"
✔ Done!

See the full working example: with-stack-template


🧠 Architecture & Workflow

Kubricate is a framework for defining, composing, and generating Kubernetes manifests in TypeScript — with optional secret hydration and syncing across environments.

It gives you full control of infrastructure and secrets before deployment, with a type-safe, CLI-first developer experience.

🔁 Step-by-Step Workflow

  1. Register Connectors

    Connect to external secret systems such as .env, Azure Key Vault, 1Password, or Vault.

    // @filename: src/setup-secrets.ts
    export const secretManager = new SecretManager()
      .addConnector('Env', new EnvConnector())
      .addConnector('AzureKV', new AzureKeyVaultConnector());
  2. Register at Least One Provider

    Providers define how secrets will be injected into Kubernetes (e.g., as Secret, ConfigMap, or annotations).

    // @filename: src/setup-secrets.ts
    secretManager.addProvider(
      'OpaqueSecretProvider',
      new OpaqueSecretProvider({ name: 'secret-application' })
    );
  3. Set a Default Connector

    When multiple connectors are registered, you must set the default one to be used during hydration.

    // @filename: src/setup-secrets.ts
    secretManager.setDefaultConnector('AzureKV');

    ℹ️ If multiple providers are registered, you must also set:

    secretManager.setDefaultProvider('OpaqueSecretProvider');
  4. Declare Secrets

    Centralize your secrets and optionally map them to a provider.

    // @filename: src/setup-secrets.ts
    secretManager.addSecret({ name: 'my_app_key' });
  5. Define a Hydration Plan (Optional)

    Describe how secrets should flow from one system to another (e.g. .env → Azure KV).

    // @filename: src/setup-secrets.ts
    secretManager.addHydrationPlan('EnvToKV', {
      from: 'Env',
      to: 'AzureKV',
      options: { conflictStrategy: 'overwrite' },
    });

    ⚠️ Note: Hydration Plan support is in progress. See Issue #75

  6. Define Your Application Stack

    Use existing reusable stacks like AppStack, and inject secrets from providers.

    // @filename: src/stacks.ts
    import { Stack } from 'kubricate';
    import { simpleAppTemplate } from '@kubricate/stacks';
    
    export const myApp = nStack.fromTemplate(simpleAppTemplate, {
       imageName: 'nginx',
       name: 'my-app',
     })
     .useSecrets(secretManager, (c) => {
       c.secrets('my_app_key').forName('ENV_APP_KEY').inject();
     });
  7. Configure the Project

    Wire everything together in kubricate.config.ts.

    import { defineConfig } from 'kubricate';
    import { myApp } from './src/stacks'; // import your stack
    import { secretManager } from './src/setup-secrets'; // import your secret manager
    
    export default defineConfig({
      stacks: {
         app: myApp,
      },
      secrets: {
         manager: secretManager,
      }
    });
  8. CLI: Generate YAML

    Render Kubernetes manifests from all defined stacks.

    kubricate generate
  9. CLI: Plan & Hydrate Secrets (Optional)

    Run secret hydration workflows to sync secrets between systems.

    kubricate secret plan     # Preview hydration actions
    kubricate secret hydrate  # Execute hydration

    ⚠️ Note: Hydration Plan support is in progress. See Issue #75

  10. CLI: Validate & Apply Secrets (Optional)

    Validate that all declared secrets exist and apply them to providers if needed.

    kubricate secret validate     # Validate connector/provider state
    kubricate secret apply        # Apply secrets to target provider (e.g. Azure KV, Kubernetes)

🗺️ Workflow Diagram

Kubricate separates infrastructure and secret management into clear, declarative steps — from configuration to CLI execution. This diagram shows the full lifecycle from connecting secret sources to generating Kubernetes YAML and applying secrets.

Required steps follow a linear flow. Optional steps (gray) are used when you hydrate or validate secrets.

flowchart TD
    %% Required Steps
    Step1["1 Register Connectors"]
    Step2["2 Register at Least One Provider"]
    Step3["3 Set a Default Connector"]
    Step4["4 Declare Secrets"]
    Step6["6 Define Your Application Stack"]
    Step7["7 Configure the Project"]
    Step8["8 CLI: Generate YAML"]

    %% Optional Steps
    Step5["5 Define a Hydration Plan (Optional)"]
    Step9["9 CLI: Plan & Hydrate Secrets (Optional)"]
    Step10["10 CLI: Validate & Apply Secrets (Optional)"]

    %% Core flow
    Step1 --> Step2
    Step2 --> Step3
    Step3 --> Step4
    Step4 --> Step6
    Step6 --> Step7
    Step7 --> Step8

    %% Optional/side flows
    Step4 -.-> Step5
    Step5 --> Step9
    Step4 -.-> Step10
    Step9 --> Step10

    %% Visual styling (safe across Mermaid renderers)
    classDef optional fill:#f3f4f6,stroke:#999,stroke-width:1px;
    class Step5,Step9,Step10 optional
Loading

💡 Legend:

  • Steps 1–8 are part of the core Kubricate workflow
  • Steps 5, 9, 10 are optional — used for secret hydration, previewing, or applying secret changes via CLI
  • This separation reflects Kubricate's design: declarative configuration first, execution via CLI only when needed

🖇️ CLI Alias: kbr

Kubricate now supports a shorter CLI alias: kbr
This is functionally identical to kubricate, making it quicker to type in scripts and terminals.

kbr generate
kbr secret plan
kbr secret hydrate

See PR #77 for details.


Documentation & Examples

Documentation is in progress, please explore the examples directory for real-world usage patterns and advanced features.


Packages

  • kubricate – CLI for configuration and manifest generation
  • @kubricate/core – Core framework for creating and managing stacks
  • @kubricate/plugin-env – Secret connector for .env and environment variables
  • @kubricate/plugin-kubernetes – Kubernetes connectors
  • @kubricate/stacks – Official reusable stack definitions
  • @kubricate/toolkit – Utility functions for custom stack authors

Version Compatibility

Ensure the following packages are always on the same version when upgrading:

  • kubricate
  • @kubricate/core
  • @kubricate/plugin-env
  • @kubricate/plugin-kubernetes
  • @kubricate/stacks

Development

To develop Kubricate:

pnpm install
pnpm build
pnpm dev

This installs dependencies and starts TypeScript in watch mode.

To run the examples run with

pnpm --filter=@examples/with-stack-template kubricate generate

How to Publish

  1. Run pnpm changeset and select the packages to version
  2. Commit and push the changes
  3. GitHub Actions will open a release PR
  4. Review and approve the PR
  5. The packages will be published to NPM automatically

About

A TypeScript framework for building reusable, type-safe Kubernetes infrastructure — without the YAML mess.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 5