Skip to content

alegeay/Sherpack

Repository files navigation

Sherpack

A blazingly fast Kubernetes package manager with Jinja2 templating

Rust License Build Tests

A modern Helm alternative written in Rust, featuring familiar Jinja2 templating syntax

FeaturesInstallationQuick StartCommandsTemplating


Why Sherpack?

Feature Sherpack Helm
Templating Jinja2 (familiar syntax) Go templates (complex)
Performance Native Rust binary Go runtime
Binary Size ~19 MB ~50 MB
Learning Curve Minimal (if you know Jinja2) Steep
Dependencies None None
Schema Validation Built-in JSON Schema External tools
Error Messages Contextual suggestions Generic errors
Helm Migration Automatic chart converter N/A
CRD Handling Smart updates with safety analysis Never updates CRDs
CRD Templating Supported in crds/ and templates/ Only in templates/ (dangerous)
Subchart Rendering Full support with global values Full support

Features

Core Templating

  • Jinja2 Templating - Familiar Python-like syntax with {{ }} and {% %}
  • Helm-Compatible Filters - toyaml, tojson, b64encode, indent, nindent, quote, and 20+ more
  • Rich Function Library - get(), ternary(), now(), uuidv4(), tostring(), fail()
  • Strict Mode - Catch undefined variables before deployment

Schema Validation

  • JSON Schema Support - Validate values against schema before rendering
  • Default Extraction - Automatic default values from schema
  • Helpful Error Messages - Contextual suggestions for typos and missing keys

Packaging & Signing

  • Archive Format - Reproducible tar.gz with SHA256 manifest
  • Cryptographic Signatures - Minisign-based signing for supply chain security
  • Integrity Verification - Verify archives before deployment

Kubernetes Integration

  • Full Lifecycle Management - Install, upgrade, rollback, uninstall
  • Server-Side Apply - Modern Kubernetes apply with conflict detection
  • Hook Support - Pre/post install, upgrade, rollback, delete hooks
  • Health Checks - Wait for deployments, custom HTTP/command probes
  • Release Storage - Secrets, ConfigMap, or file-based storage
  • Diff Preview - See changes before applying

CRD Handling (Better than Helm)

  • Smart CRD Updates - Safe updates with change analysis (24 change types)
  • Intent-Based Policies - Explicit control via annotations (managed, shared, external)
  • Templated CRDs - Support templating in both crds/ and templates/
  • Deletion Protection - Impact analysis before CRD deletion
  • Auto-Detection - CRDs in templates/ are automatically protected
  • Rich Diff Output - See exactly what will change in CRD updates

Subchart Support

  • Full Subchart Rendering - Render subcharts with their own values
  • Global Values - Pass global values to all subcharts
  • Conditional Subcharts - Enable/disable via conditions and tags
  • Files Object - Access files in subcharts (.Files.Get, .Files.Glob)

Helm Migration

  • Automatic Conversion - Convert Helm charts to Sherpack packs
  • Template Translation - Go templates → Jinja2 syntax
  • Helper Function Support - Converts include, define, range, with, etc.
  • Full Chart Compatibility - Tested with ingress-nginx (43 templates)

Repository & Dependencies

  • Repository Management - HTTP, OCI, and file-based repositories
  • Dependency Resolution - Lock file with version policies
  • SQLite Search - Fast local search with FTS5
  • OCI Registry Support - Push/pull to container registries

Installation

From Source

# Clone the repository
git clone https://github.com/alegeay/sherpack.git
cd sherpack

# Build release binary
cargo build --release

# Install to your PATH
cp target/release/sherpack ~/.local/bin/

Requirements

  • Rust 1.85+ (Edition 2024)
  • For Kubernetes operations: kubectl configured with cluster access

Quick Start

1. Create a Pack

sherpack create myapp

This generates:

myapp/
├── Pack.yaml           # Pack metadata
├── values.yaml         # Default values
├── values.schema.yaml  # Optional: JSON Schema
└── templates/
    └── deployment.yaml # Kubernetes template

2. Define Your Values

# values.yaml
app:
  name: mywebapp
  replicas: 3

image:
  repository: nginx
  tag: "1.25"

resources:
  limits:
    cpu: "500m"
    memory: "256Mi"

3. Create Templates

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ release.name }}
  namespace: {{ release.namespace }}
spec:
  replicas: {{ values.app.replicas }}
  template:
    spec:
      containers:
        - name: {{ values.app.name | kebabcase }}
          image: {{ values.image.repository }}:{{ values.image.tag }}
          resources:
            {{ values.resources | toyaml | nindent(12) }}

4. Validate and Render

# Validate against schema
sherpack validate ./myapp

# Lint the pack structure
sherpack lint ./myapp

# Render templates locally
sherpack template myrelease ./myapp

# Render with overrides
sherpack template myrelease ./myapp --set app.replicas=5 -n production

5. Deploy to Kubernetes

# Install to cluster
sherpack install myrelease ./myapp -n production

# Upgrade existing release
sherpack upgrade myrelease ./myapp --set app.replicas=5

# View release status
sherpack status myrelease

# Rollback if needed
sherpack rollback myrelease 1

# Uninstall
sherpack uninstall myrelease

CLI Reference

Templating Commands

Command Description
sherpack template <name> <pack> Render templates to stdout
sherpack lint <pack> Validate pack structure and templates
sherpack validate <pack> Validate values against schema
sherpack show <pack> Display pack information
sherpack create <name> Scaffold a new pack
sherpack convert <chart> Convert Helm chart to Sherpack pack

Packaging Commands

Command Description
sherpack package <pack> Create archive from pack directory
sherpack inspect <archive> Show archive contents and manifest
sherpack keygen Generate signing keypair
sherpack sign <archive> Sign archive with private key
sherpack verify <archive> Verify archive integrity and signature

Kubernetes Commands

Command Description
sherpack install <name> <pack> Install pack to cluster
sherpack upgrade <name> <pack> Upgrade existing release
sherpack uninstall <name> Remove release from cluster
sherpack rollback <name> <rev> Rollback to previous revision
sherpack list List installed releases
sherpack history <name> Show release history
sherpack status <name> Show release status
sherpack recover <name> Recover stale release

Repository Commands

Command Description
sherpack repo add <name> <url> Add repository
sherpack repo list List repositories
sherpack repo update [name] Update repository index
sherpack repo remove <name> Remove repository
sherpack search <query> Search for packs
sherpack pull <pack> Download pack from repository
sherpack push <archive> <dest> Push to OCI registry

Dependency Commands

Command Description
sherpack dependency list <pack> List pack dependencies
sherpack dependency update <pack> Resolve and lock dependencies
sherpack dependency build <pack> Download locked dependencies
sherpack dependency tree <pack> Show dependency tree

Templating Reference

Context Variables

Variable Description Example
values.* Values from values.yaml {{ values.app.name }}
release.name Release name {{ release.name }}
release.namespace Target namespace {{ release.namespace }}
pack.name Pack name from Pack.yaml {{ pack.name }}
pack.version Pack version {{ pack.version }}
capabilities.* Cluster capabilities {{ capabilities.kubeVersion }}

Filters

Serialization

Filter Description
toyaml Object to YAML string
tojson Object to compact JSON
tojson_pretty Object to formatted JSON

Encoding

Filter Description
b64encode Base64 encode
b64decode Base64 decode
sha256 SHA256 hash

Strings

Filter Description
quote / squote Wrap in quotes
upper / lower Change case
snakecase / kebabcase / camelcase Case conversion
trunc(n) Truncate to n characters
trimprefix(s) / trimsuffix(s) Remove prefix/suffix
replace(old, new) Replace substring

Indentation

Filter Description
indent(n) Add n spaces to each line
nindent(n) Newline + indent

Collections

Filter Description
keys Get object keys
haskey(k) Check if key exists
merge(obj) Merge objects
dictsort Sort for iteration
first / last First/last element
default(val) Default if undefined

Validation

Filter Description
required Fail if undefined/empty
empty Check if empty

Type Conversion

Filter Description
int Convert to integer
float Convert to float
string Convert to string

Functions

Function Description
get(obj, key, default) Safe access with default
ternary(true, false, cond) Conditional value
tostring(v) / toint(v) / tofloat(v) Type conversion
now() Current ISO timestamp
uuidv4() Random UUID
fail(msg) Fail with message

Pack Structure

mypack/
├── Pack.yaml             # Required: Pack metadata
├── values.yaml           # Required: Default values
├── values.schema.yaml    # Optional: JSON Schema for validation
├── Pack.lock.yaml        # Generated: Locked dependencies
├── packs/                # Downloaded dependencies
└── templates/            # Required: Template files
    ├── deployment.yaml
    ├── service.yaml
    └── _helpers.tpl      # Optional: Shared helpers

Pack.yaml

apiVersion: sherpack/v1
kind: application
metadata:
  name: myapp
  version: 1.0.0
  description: My application
  appVersion: "2.0.0"

# Optional: Dependencies
dependencies:
  - name: redis
    version: ">=7.0.0"
    repository: https://charts.example.com

# Optional: Engine settings
engine:
  strict: true  # Fail on undefined variables

values.schema.yaml

$schema: http://json-schema.org/draft-07/schema#
type: object
properties:
  app:
    type: object
    properties:
      name:
        type: string
        default: myapp
      replicas:
        type: integer
        minimum: 1
        maximum: 10
        default: 3
    required: [name]

Kubernetes Hooks

Sherpack supports lifecycle hooks for custom actions:

# templates/pre-install-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: {{ release.name }}-pre-install
  annotations:
    sherpack.io/hook: pre-install
    sherpack.io/hook-weight: "0"
    sherpack.io/hook-delete-policy: hook-succeeded
spec:
  template:
    spec:
      containers:
        - name: migrate
          image: myapp:{{ values.image.tag }}
          command: ["./migrate.sh"]
      restartPolicy: Never

Hook Phases

Phase When
pre-install Before install
post-install After install
pre-upgrade Before upgrade
post-upgrade After upgrade
pre-rollback Before rollback
post-rollback After rollback
pre-delete Before uninstall
post-delete After uninstall
test On sherpack test

CRD Handling

Sherpack provides superior CRD handling compared to Helm:

CRD Policies

Use annotations to declare how CRDs should be managed:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: myresources.example.com
  annotations:
    sherpack.io/crd-policy: managed  # or: shared, external
Policy Behavior Use Case
managed Owned by release, protected on uninstall Operator CRDs
shared Never deleted, even with --delete-crds Shared infrastructure
external Don't touch (managed by GitOps) External management

Templated CRDs

Unlike Helm, Sherpack allows templating in crds/ directory:

# crds/myresource-crd.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: {{ values.crdName }}.{{ values.group }}
  labels:
    {{- values.labels | toyaml | nindent 4 }}

Safe Updates

CRD changes are analyzed by severity:

$ sherpack upgrade myrelease ./mypack --show-crd-diff

CRD Analysis: myresources.example.com
══════════════════════════════════════════════════════════════════

Versions:
  ✓ + Added API version v1beta2

Schema Changes:
  ✓ + Added optional field: spec.newFeature
  ⚠ ~ Tightened validation: spec.config.maxLength 256 → 128
  ✗ - Removed field: spec.deprecated (DANGEROUS)

Summary:
  ✓ 2 safe change(s)
  ⚠ 1 warning(s)
  ✗ 1 dangerous (require --force-crd-update)

Deletion Protection

$ sherpack uninstall my-operator --delete-crds

⚠ CRD Deletion Impact Analysis

  myresources.example.com:
    Policy: managed
    Existing resources: 47 across 12 namespaces
      - production (23 resources)
      - staging (15 resources)

  This will PERMANENTLY DELETE all 47 resources.
  Use --confirm-crd-deletion to proceed.

Helm Chart Conversion

Sherpack can automatically convert Helm charts to Sherpack packs:

# Convert a Helm chart
sherpack convert ./my-helm-chart

# Specify output directory
sherpack convert ./my-helm-chart -o ./my-sherpack-pack

# Preview without writing
sherpack convert ./my-helm-chart --dry-run

# Force overwrite existing
sherpack convert ./my-helm-chart --force

Conversion Examples

Go templates are automatically translated to Jinja2:

Go Template Jinja2
{{ .Values.name }} {{ values.name }}
{{ include "helper" . }} {{ helper() }}
{{- if .Values.enabled }} {% if values.enabled %}
{{ range .Values.items }} {% for item in values.items %}
{{ .Release.Name }} {{ release.name }}
{{ default "foo" .Values.x }} {{ values.x | default("foo") }}
{{ .Values.x | quote }} {{ values.x | quote }}
{{ toYaml .Values | nindent 2 }} {{ values | toyaml | nindent(2) }}

Supported Features

  • {{- define "name" }}{% macro name() %}
  • {{ include "name" . }}{{ name() }}
  • {{ if }}/{{ else }}/{{ end }}{% if %}/{% else %}/{% endif %}
  • {{ range }}/{{ end }}{% for %}/{% endfor %}
  • {{ with }}/{{ end }}{% with %}/{% endwith %} or inline
  • Variable declarations: $var := value
  • All common Helm functions and pipelines

Repository Configuration

Add Repositories

# HTTP repository
sherpack repo add stable https://charts.example.com

# With authentication
sherpack repo add private https://charts.example.com --username user --password pass

# OCI registry
sherpack repo add oci oci://registry.example.com/charts

Search and Pull

# Search across repositories
sherpack search nginx

# Pull specific version
sherpack pull stable/nginx:1.0.0

# Pull from OCI
sherpack pull oci://registry.example.com/charts/nginx:1.0.0

Push to OCI

# Package and push
sherpack package ./myapp
sherpack push myapp-1.0.0.tar.gz oci://registry.example.com/charts/myapp:1.0.0

Architecture

sherpack/
├── crates/
│   ├── sherpack-core/     # Core types: Pack, Values, Context, Archive
│   ├── sherpack-engine/   # Template engine, filters, functions
│   ├── sherpack-convert/  # Helm chart to Sherpack converter
│   ├── sherpack-kube/     # Kubernetes client, storage, hooks, health
│   ├── sherpack-repo/     # Repository, OCI, dependencies, search
│   └── sherpack-cli/      # CLI commands
├── fixtures/
│   ├── simple-pack/       # Basic test fixture
│   ├── demo-pack/         # Comprehensive demo
│   └── helm-nginx/        # Helm conversion test
└── docs/                  # Documentation

Crates

Crate Purpose Tests
sherpack-core Pack, Values, Archive, Manifest, Files 65
sherpack-engine MiniJinja templating, filters, functions, subcharts 118
sherpack-convert Helm Go templates → Jinja2 converter 62
sherpack-kube Kubernetes, storage, hooks, CRD handling 219
sherpack-repo Repository backends, dependencies, search 53
sherpack-cli CLI application 83
Total ~35k lines of Rust 600

Examples

Complete Deployment with ConfigMap

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ release.name }}
  labels:
    app.kubernetes.io/name: {{ release.name }}
    app.kubernetes.io/version: {{ pack.version }}
  annotations:
    checksum/config: {{ values.config | tojson | sha256 | trunc(16) }}
spec:
  replicas: {{ values.replicas }}
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ release.name }}
  template:
    spec:
      containers:
        - name: app
          image: {{ values.image.repository }}:{{ values.image.tag }}
          envFrom:
            - configMapRef:
                name: {{ release.name }}-config
          resources:
            {{ values.resources | toyaml | nindent(12) }}
---
# templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ release.name }}-config
data:
  {% for key, value in values.env | dictsort %}
  {{ key }}: {{ value | quote }}
  {% endfor %}

Conditional Ingress with TLS

{% if values.ingress.enabled %}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ release.name }}
  annotations:
    {% if values.ingress.tls %}
    cert-manager.io/cluster-issuer: letsencrypt
    {% endif %}
spec:
  {% if values.ingress.tls %}
  tls:
    - hosts: {{ values.ingress.hosts | tojson }}
      secretName: {{ release.name }}-tls
  {% endif %}
  rules:
    {% for host in values.ingress.hosts %}
    - host: {{ host }}
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: {{ release.name }}
                port:
                  number: 80
    {% endfor %}
{% endif %}

Development

# Build
cargo build --workspace

# Test
cargo test --workspace

# Lint
cargo clippy --workspace

# Format
cargo fmt --all

# Run CLI
cargo run -p sherpack -- <command>

License

Apache-2.0


Back to top

Made with Rust

About

A Helm-like Kubernetes package manager with Jinja2 templating, written in Rust

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages