- Nix 83.5%
- JavaScript 16.5%
| .github | ||
| docs | ||
| hex | ||
| scripts | ||
| tests | ||
| .envrc | ||
| .gitignore | ||
| .oxfmtrc.json | ||
| AGENTS.md | ||
| bun.lockb | ||
| default.nix | ||
| flake-compat.nix | ||
| flake.lock | ||
| flake.nix | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
🪄 hex
hex is an opinionated abstraction layer that brings the magic of Nix to Kubernetes configuration management. It allows you to write declarative, composable "spells" that generate Kubernetes resources with all the benefits of the Nix ecosystem. Get your YAML nightmare under control, and keep things DRY!
✨ Features
- Declarative Configuration: Write your Kubernetes configs using Nix's powerful expression language
- Composable Building Blocks: Write functions to orchestrate other functions! Easy to snap things together
- Pre-built modules: Modules/functions for popular tools like ArgoCD, Prometheus, Grafana, and many more
- Smart Diffing: See exactly what will change before applying updates to your cluster
- Built-in Safety: Server-side diffs by default, with proper validation of resources
- Helm Integration: Seamlessly incorporate Helm charts into your configurations
- Custom Resource Support: First-class support for CRDs and custom resources
- Development Friendly: Built-in support for dry runs and partial deployments
- [beta] ArgoCD plugin: ArgoCD plugin is WIP! Deploying ArgoCD with
hexwill auto-configure the hex plugin
🚀 Quick Start
- Install hex:
regular fetchTarball + import:
let
pkgs = import
(fetchTarball {
name = "unstable-2024-10-31";
url = "https://github.com/NixOS/nixpkgs/archive/2d2a9ddbe3f2c00747398f3dc9b05f7f2ebb0f53.tar.gz";
sha256 = "1v6gpivg8mj4qapdp0y5grapnlvlw8xyh5bjahq9i50iidjr3587";
})
{ };
_hex = import
(fetchTarball {
name = "hex-2024-10-31";
# note, you'll probably want to grab a commit sha for this instead of `main`!
url = "https://github.com/jpetrucciani/hex/archive/main.tar.gz";
# this is necessary, but you can find it by letting nix try to evaluate this!
sha256 = "";
})
{ }; # if you override pkgs for this, you _must_ have pog available
paths = with _hex; [
hex
hexcast # not needed, unless you want to use this directly!
];
in
pkgs.buildEnv {
name = "hextest";
paths = paths;
buildInputs = paths;
}
with flakes:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
hex.url = "github:jpetrucciani/hex";
};
outputs = { self, nixpkgs, hex, ... }:
let
system = "x86_64-linux";
pkgs = nixpkgs { inherit system; };
_hex = hex.packages.${system};
in
{
devShells.${system}.default = pkgs.mkShell {
nativeBuildInputs = [
_hex.hex
];
};
};
}
- Create your first spell (e.g.,
specs.nix):
Note: specs.nix is the default target when hex is run without a specific target (-t TARGET_FILE) or without -a/--all
{ hex }:
let
# remember this is just nix code, so you can use any normal language features!
inherit (hex.k8s.svc) metabase;
in
hex [
# every entry in this list will be evaluated + rendered
# lists will be flattened!
# if an entry is a function, it will be called with an empty attrset
hex.k8s.svc.litellm # equivalent to: (hex.k8s.svc.litellm {})
# pass attrs in to override default functionality, or to provide required attrs
(metabase { domain = "metabase.cobi.dev"; })
# if an entry is a yaml file path, it will be merged into the set of all rendered specs
./other_k8s_spec.yaml # includes this file in the rendered output documents
# also, use toYAMLDoc to use arbitrary attrsets!
(hex.toYAMLDoc {
apiVersion = "v1";
kind = "ServiceAccount";
metadata = {
annotations.source = "hex";
name = "my-service-account";
namespace = "default";
};
})
# TODO: show a helm chart example
]
- Cast your spell:
hex
# or, to target a specific file:
hex -t specs.nix
#or, to load all hex files in the current directory:
hex -a # also:
hex --all
🎭 Available Modules
hex comes with a rich set of pre-built modules for common Kubernetes applications:
- Databases: PostgreSQL, Redis, MongoDB, Elastic
- Monitoring: Prometheus, Grafana
- CI/CD: ArgoCD, GitLab Runner
- Identity: Authentik
- Ingress: Kong, Nginx, Traefik
- Observability: Sentry
- Services: generic, best practices service creation module
- Cron: easy + powerful cron job configuration module
- And many more!
🔧 Advanced Usage
# only render and print to stdout
hex --render -t specs.nix
# render and validate against the default Kubernetes schema version
hex --render --validate -t specs.nix
# validate against a different Kubernetes version
hex --render --validate --kubeversion 1.34.0 -t specs.nix
# eval a sring instead of using a file (useful for testing hex itself, or deploying things one-off!)
# '{hex}:' is prepended to the eval string
hex --evaluate --render 'hex [hex.k8s.svc.litellm]'
# dryrun, just show diff
hex --dryrun -t specs.nix
# filter to just the CRDs
# useful to apply the CRDs from a helm chart before attempting to deploy the rest!
hex --crds -t specs.nix
# force apply, don't perform a diff, and don't ask for a confirmation
hex --force -t specs.nix
# clientside diff. available in case you need it, but I would avoid!
hex --clientside -t specs.nix
📚 Components
- hex: Main command-line tool for applying configurations to clusters. Written with pog!
- hexcast: Core rendering engine that transforms Nix configurations into Kubernetes resources
- nixrender: Low-level tool for rendering Nix expressions
Testing
Build and run the integration test suite with:
nix build .#test
./result/bin/test
The test binary is a single derivation, so building it once also supports quick, focused feedback loops:
./result/bin/test --suite fast # CLI, services, and other non-Helm tests
./result/bin/test --suite cli # hex --validate behavior
./result/bin/test --suite services # service abstraction and built-in services
./result/bin/test --suite charts # Helm and chart integrations
./result/bin/test --list-suites
The default remains the complete suite. Individual tests can also be selected
with a comma-separated list, for example
./result/bin/test cli-validate-target,service-lifecycle.
Every successful render is checked with
kubeconform in strict mode against the
pinned Kubernetes 1.35 schemas. Tests for hex.k8s.services require a schema
for every rendered resource. Helm-oriented tests validate all known resources
and report custom resources without an available schema as skipped.
Set KUBECONFORM_CACHE to choose where downloaded schemas are cached.
Demo
TODO