Skip to content
Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Repository files navigation

Maniforge

A Terraform-like tool for Kubernetes applications

Transform simple app definitions into production-ready Kubernetes manifests using the power of bjw-s-app-template.

๐Ÿ“ฆ Installation

Quick Install (macOS/Linux)

curl -L https://github.com/calebsargeant/maniforge/releases/latest/download/maniforge-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m) -o maniforge
chmod +x maniforge
sudo mv maniforge /usr/local/bin/

Homebrew

brew tap calebsargeant/tap
brew install maniforge

Build from Source

git clone https://github.com/calebsargeant/maniforge.git
cd maniforge
./build.sh
sudo cp dist/maniforge /usr/local/bin/

๐ŸŽฏ Philosophy

Instead of writing complex Kubernetes YAML, define apps like Docker Compose and let Maniforge handle the Kubernetes complexity.

No Python required - maniforge is distributed as a universal executable!

๐Ÿš€ Quick Start

1. Initialize a New Project

./maniforge init --cluster my-cluster

This creates a maniforge.yaml with an example app.

2. Plan Your Changes

./maniforge plan

See what Maniforge will create (like terraform plan):

๐Ÿ“‹ Plan: 1 changes

  ๐ŸŸข nginx-example
      App will be created
      Image: nginx:latest
      Namespace: default

3. Apply Changes

./maniforge apply

Generates Kubernetes manifests in the apps/ directory.

4. Deploy with GitOps

git add apps/
git commit -m "Deploy apps with Maniforge"
git push  # Flux/ArgoCD picks up changes

๐Ÿ“‹ Configuration Format

maniforge.yaml - Your infrastructure as code (single file):

cluster:
  name: homelab
  domain: sargeant.co
  defaults:
    profile: c.small
    nodeSelector: pi

output:
  directory: apps

nodes:
  pi:
    count: 2
    cpu: 4
    mem: 16Gi

apps:
  homebridge:
    image: ghcr.io/homebridge/homebridge:latest
    type: daemonset
    network: host
    profile: c.pico
    storage:
      config:
        type: hostPath
        path: /mnt/nvme/homebridge-config
        mount: /homebridge
    env:
      TZ: Europe/Amsterdam
  
  plex:
    image: plexinc/pms-docker:latest
    type: deployment
    network: nodeport
    profile: r.large
    ports:
      - name: plex
        port: 32400
        nodePort: 32400
    storage:
      config:
        type: hostPath
        path: /mnt/raid/plex-config
        mount: /config
      media:
        type: hostPath
        path: /mnt/raid/media
        mount: /data
        readonly: true
    env:
      PLEX_CLAIM: token-123456789

  postgres:
    image: postgres:15
    type: deployment
    network: clusterip
    profile: m.small
    storage:
      data:
        type: pvc
        size: 20Gi
        mount: /var/lib/postgresql/data
        storageClass: fast-ssd
    env:
      POSTGRES_DB: myapp
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret

๐Ÿ”ง Commands

Initialize

./maniforge init [--cluster name]

Create a new project with example configuration.

Plan

./maniforge plan

Show what changes would be made (like terraform plan).

Apply

./maniforge apply

Generate/update Kubernetes manifests.

Validate

./maniforge validate

Check configuration for errors.

๐Ÿ“– App Configuration Reference

Required Fields

apps:
  myapp:
    image: nginx:latest          # Docker image (required)

Optional Fields

    # Workload type
    type: deployment             # deployment|daemonset|statefulset (default: deployment)
    
    # Networking
    network: clusterip           # clusterip|nodeport|loadbalancer|host (default: clusterip)
    ports:                       # Custom ports (for nodeport/loadbalancer)
      - name: web
        port: 80
        targetPort: 8080
        nodePort: 30080          # Only for nodeport
    
    # Resources & Placement
    profile: c.small             # Resource profile (default: from cluster.defaults)
    nodeSelector: pi             # Node selector (default: from cluster.defaults)
    namespace: default           # Kubernetes namespace (default: default)
    
    # Storage
    storage:
      data:
        type: pvc                # pvc|hostPath|nfs
        size: 10Gi              # PVC size (required for pvc)
        mount: /data            # Container mount path
        storageClass: fast      # Storage class (optional)
        readonly: false         # Read-only mount (default: false)
      
      config:
        type: hostPath
        path: /host/path/to/config
        mount: /config
    
    # Environment
    env:
      TZ: Europe/Amsterdam
      DEBUG: "true"
    
    # Ingress (automatic if cluster.domain is set)
    ingress: false               # Disable ingress (default: true if domain set)

๐Ÿ—๏ธ Resource Profiles

Maniforge uses resource-profiles.yaml as the master definition for all AWS-style resource allocation profiles. It defines CPU and memory requests/limits for different workload types.

Pre-Generated Profiles

โœจ New: This repository now includes pre-generated Kubernetes resource profiles in the _components/resource-profiles directory!

You can directly reference these profiles in your Kustomize configurations without needing to generate them yourself. The pre-generated profiles include:

  • 40 profile variations across 5 types (P, T, C, M, R) and 8 sizes
  • Ready-to-use Kustomize components for Deployments, StatefulSets, and DaemonSets
  • HelmRelease patches for Flux CD integrations
  • Full documentation in _components/resource-profiles/README.md

Quick Start:

# In your kustomization.yaml
components:
  - https://github.com/calebsargeant/maniforge/_components/resource-profiles?ref=main

Then add profile labels to your workloads:

metadata:
  labels:
    resource-profile: c.small

Profile Types

  • P-type (2:1 CPU:Memory) - Video transcoding, image processing, ML inference
  • T-type (1:1 CPU:Memory) - Web servers, APIs, general-purpose applications
  • C-type (1:2 CPU:Memory) - Compute-optimized, load balancers
  • M-type (1:4 CPU:Memory) - Memory-optimized, balanced workloads
  • R-type (1:8 CPU:Memory) - In-memory databases, caches, large datasets

Profile Sizes

Each type has 8 sizes: pico, nano, micro, small, medium, large, xlarge, 2xlarge

Built-in Profiles

Profile CPU Requests CPU Limits Memory Requests Memory Limits Use Case
c.pico 100m 250m 256Mi 512Mi Tiny apps
c.small 250m 500m 512Mi 1Gi Small apps
c.medium 500m 1000m 1Gi 2Gi Medium apps
r.large 500m 1000m 4Gi 8Gi Memory-intensive

Master Definition File

The resource-profiles.yaml file:

  • Defines all available resource profiles with CPU/memory requests and limits
  • Can be used to generate Kubernetes component structures
  • Is automatically loaded by maniforge for app configuration
  • Can be customized by users for their own profile definitions

Generating Custom Kubernetes Components

If you want to generate profiles from a custom resource-profiles.yaml:

./maniforge generate-profiles --output /path/to/output

This generates:

  • Main kustomization.yaml with all profile patches
  • Individual profile directories (e.g., c.small/, r.large/) containing:
    • kustomization.yaml: Component definition
    • patches.yaml: Resource patches for Deployments/StatefulSets/DaemonSets
    • helmrelease-patches.yaml: Patches for Flux HelmRelease resources
  • README.md: Documentation of all available profiles

Note: The default profiles are already pre-generated in _components/resource-profiles, so you only need to run this command if you're creating custom profiles.

Using Pre-Generated or Custom Profiles

Option 1: Use Pre-Generated Profiles (Recommended)

Reference the pre-generated profiles directly from this repository:

# Label-based selection (applies to resources with matching labels)
components:
  - https://github.com/calebsargeant/maniforge/_components/resource-profiles?ref=main

# Or use a specific profile directly
components:
  - https://github.com/calebsargeant/maniforge/_components/resource-profiles/c.small?ref=main

Option 2: Use Local Copy

If you've cloned this repository or want to use profiles locally:

components:
  - ../../_components/resource-profiles

Then add profile labels to your resources:

metadata:
  labels:
    resource-profile: m.medium

Option 3: Generate Custom Profiles

Create your own resource-profiles.yaml and generate components:

./maniforge generate-profiles --profiles-yaml custom-profiles.yaml --output my-components/

๐ŸŒ Network Types

Type Description Use Case
clusterip Cluster-internal access only Internal services, databases
nodeport External access via node ports Development, specific port requirements
loadbalancer External LoadBalancer service Production external services
host Host networking HomeAssistant, network-sensitive apps

๐Ÿ“ Storage Types

Type Configuration Use Case
pvc size, storageClass, accessMode Persistent data, databases
hostPath path Host directory mounts
nfs server, path Shared storage

๐Ÿ”„ Generated Structure

Maniforge creates a clean structure:

apps/
โ”œโ”€โ”€ homebridge/
โ”‚   โ”œโ”€โ”€ kustomization.yaml      # Kustomize config
โ”‚   โ””โ”€โ”€ helm-release.yaml       # HelmRelease with bjw-s-app-template
โ””โ”€โ”€ plex/
    โ”œโ”€โ”€ kustomization.yaml
    โ””โ”€โ”€ helm-release.yaml

Each app gets its own directory with:

  • kustomization.yaml - Kustomize configuration
  • helm-release.yaml - Complete HelmRelease using bjw-s-app-template

๐ŸŽจ Benefits

โœ… Terraform-like Workflow - Plan, apply, version control
โœ… Simple Configuration - Docker Compose-like syntax
โœ… Powerful Output - Full Kubernetes capabilities via bjw-s-app-template
โœ… GitOps Ready - Generated manifests work with Flux/ArgoCD
โœ… Validation - Catch errors before deployment
โœ… Diff-Aware - Shows exactly what changed

๐Ÿšฆ Workflow

  1. Edit maniforge.yaml (your infrastructure as code)
  2. Plan with ./maniforge plan (see what will change)
  3. Apply with ./maniforge apply (generate manifests)
  4. Commit generated files to git
  5. Deploy automatically via GitOps

๐Ÿ“Š Example Workflow

# Initialize new project
./maniforge init --cluster homelab

# Edit maniforge.yaml to add your apps
vim maniforge.yaml

# See what will be created
./maniforge plan

# Generate manifests
./maniforge apply

# Deploy via GitOps
git add apps/ maniforge.yaml
git commit -m "Add homebridge and plex"
git push

๐Ÿ”„ GitHub Action

Use maniforge in CI/CD workflows:

name: Validate Manifests
on: [pull_request]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Validate maniforge config
        uses: calebsargeant/maniforge@v1
        with:
          command: validate
          config: maniforge.yaml
      
      - name: Plan changes
        uses: calebsargeant/maniforge@v1
        with:
          command: plan
          config: maniforge.yaml

Inputs:

  • command - Command to run: plan, apply, validate, init (default: plan)
  • config - Path to config file (default: maniforge.yaml)
  • version - Version to use (default: latest)

Outputs:

  • exit-code - Command exit code
  • changes-detected - Whether changes were detected (plan only)

๐Ÿ› ๏ธ Development

Building

./build.sh  # Creates dist/maniforge executable

Releasing

Releases are automatic using semantic versioning. Use conventional commits:

# Features (bumps minor version)
git commit -m "feat: add new storage type support"

# Fixes (bumps patch version)
git commit -m "fix: resolve port mapping issue"

# Breaking changes (bumps major version)
git commit -m "feat!: redesign configuration format"

# Push to main - automatic release triggers
git push origin main

The workflow automatically:

  1. Determines version based on commits
  2. Creates git tag and GitHub release
  3. Builds binaries for all platforms
  4. Uploads binaries + SHA256SUMS
  5. Generates CHANGELOG.md

Download SHA256SUMS from release and update maniforge.rb checksums.

Homebrew Tap Setup

# Create homebrew-tap repo
mkdir homebrew-tap && cd homebrew-tap
mkdir Formula
cp ../maniforge.rb Formula/maniforge.rb
git init && git add . && git commit -m "Add maniforge"
git remote add origin git@github.com:calebsargeant/homebrew-tap.git
git push -u origin main

๐Ÿ“Š Capacity Planning

Maniforge now includes built-in capacity planning that analyzes resource usage across your node groups!

When you run maniforge plan, you'll see:

  • CPU and Memory usage per node type
  • Visual progress bars showing capacity utilization
  • Requests vs Limits analysis
  • Over-capacity warnings when limits exceed node capacity
  • Per-app resource breakdown

Node Capacity Configuration

Define capacity at the top level in maniforge.yaml:

nodes:
  pi:
    count: 2      # number of nodes of this type
    cpu: 4        # per-node CPU (cores or millicores, e.g. 4000m)
    mem: 16Gi     # per-node memory (alias: memory)
    disk: 100Gi   # optional, informational

Example Output

๐Ÿ“Š Capacity Planning Analysis
================================================================================

๐Ÿ–ฅ๏ธ  Node Type: pi
   Apps: 3
   Node Capacity: CPU=4.00 Memory=8.00Gi

   CPU Usage:
     Requests: 850m / 4.00 (21.2%)
       [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘]
     Limits:   1.75 / 4.00 (43.8%)
       [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘]

   Memory Usage:
     Requests: 4.75Gi / 8.00Gi (59.4%)
       [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘]
     Limits:   9.50Gi / 8.00Gi (118.8%)
     โš ๏ธ [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ]

   โœ… Capacity available (40.6% free)

   Apps on this node type:
     โ€ข homebridge: CPU=100m Memory=256.00Mi
     โ€ข plex: CPU=500m Memory=4.00Gi
     โ€ข nginx: CPU=250m Memory=512.00Mi

Capacity Assumptions

Important: Maniforge currently assumes 1 replica per node for capacity planning calculations. This is the typical pattern for:

  • DaemonSets - Run exactly one pod per node
  • Node-pinned deployments - Deployments with specific node selectors that spread across nodes

Limitations:

  • If you have multi-replica deployments targeting the same node type, the capacity analysis will undercount resource usage
  • Future versions may support configurable replica counts or cluster state inspection

Best Practice: Use capacity planning as a guideline for node sizing and to identify potential over-allocation. Always monitor actual cluster resource usage in production.

๐Ÿ”ฎ Future Features

  • ๐ŸŒ Remote Platforms - Load profiles from GitHub repos
  • ๐Ÿ”„ Live Diffing - Compare with running cluster state
  • ๐Ÿ“ฆ App Templates - Pre-built app configurations
  • ๐ŸŽ›๏ธ Advanced Networking - Service mesh, network policies

Maniforge - Because Kubernetes apps should be as easy as docker run.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages