Kubernetes cluster using Nixidy and ArgoCD
  • Nix 98.2%
  • Just 1.8%
Find a file
2026-04-11 19:05:17 +00:00
_crds feat: Add import-tree and refactor crd generation 2026-04-11 19:19:37 +02:00
env/dev feat: Add import-tree and refactor crd generation 2026-04-11 19:19:37 +02:00
manifests/dev Add service-name to route template 2026-04-11 12:51:08 +02:00
.gitignore Initial Nixidy and ArgoCD setup 2026-03-29 11:09:20 +00:00
.sops.yaml Sops for storing ArgoCD secrets 2026-03-31 22:55:11 +00:00
AGENTS.md fix: Fix formatting lists in markdown 2026-04-11 19:05:17 +00:00
common.nix refactor: Move nixidy defaults to common 2026-04-11 07:18:30 +00:00
DEPLOYMENT_GUIDE.md fix: Fix formatting lists in markdown 2026-04-11 19:05:17 +00:00
flake.lock feat: Add import-tree and refactor crd generation 2026-04-11 19:19:37 +02:00
flake.nix feat: Add import-tree and refactor crd generation 2026-04-11 19:19:37 +02:00
justfile feat: Add import-tree and refactor crd generation 2026-04-11 19:19:37 +02:00
README.md fix: Fix formatting lists in markdown 2026-04-11 19:05:17 +00:00
renovate.json Write traefik ingressRoute in nix 2026-04-11 08:43:52 +00:00
templates.nix Add service-name to route template 2026-04-11 12:51:08 +02:00
treefmt.nix fix: Fix formatting lists in markdown 2026-04-11 19:05:17 +00:00

Kubernetes Cluster - Nixidy + ArgoCD

GitOps-managed Kubernetes cluster using Nixidy for type-safe manifest generation and ArgoCD for continuous deployment.

Overview

This repository implements the "Rendered Manifests Pattern":

  • Nix configuration (env/dev/*.nix) defines all Kubernetes resources in a type-safe way
  • Nixidy generates plain YAML manifests and commits them to manifests/dev/
  • ArgoCD watches the manifest directory and automatically syncs changes to the cluster
  • App-of-apps pattern: ArgoCD manages itself and all other applications

Key Benefits: Type safety, reproducible builds, Git-based audit trail, declarative infrastructure.

Repository Structure

cluster/
├── flake.nix                   # Nix flake with dependencies and env configuration
├── flake.lock                  # Locked dependency versions
├── justfile                    # Common operations (run `just` to see all)
├── common.nix                  # Shared configuration (networking, domains, etc.)
├── templates.nix               # Reusable application templates
├── treefmt.nix                 # Formatter configuration
├── env/dev/                    # Application definitions (auto-discovered by import-tree)
│   ├── *.nix                   # Application configs (argocd, traefik, etc.)
│   ├── *.sops.yaml             # Encrypted secrets
│   └── _modules/               # Generated CRD type modules (do not edit)
├── _crds/                      # Generated CRD Nix files (regenerate with just regen-crds)
└── manifests/dev/              # Generated YAML manifests (committed, do not edit)
    ├── apps/                   # ArgoCD Application definitions
    ├── argocd/                 # ArgoCD manifests
    ├── sops-secrets-operator/  # SOPS operator manifests
    └── */                      # Other application manifests

Prerequisites

  • Nix with flakes enabled
  • Kubernetes cluster (k3s recommended)
  • SOPS with age keys for secrets management (optional)

Ingress & Routing

The cluster uses Traefik as the ingress controller, deployed via Helm chart.

Configuration

  • LoadBalancer IP: 192.168.10.228 (configured in common.nix)
  • Domain: *.k8s.martials.no (configured in common.nix)
  • Entry Points:
    • web: HTTP (port 80)
    • websecure: HTTPS (port 443)

Routing Methods

Traefik IngressRoute (recommended):

yamls = [
  (''
    apiVersion: traefik.io/v1alpha1
    kind: IngressRoute
    metadata:
      name: myapp-route
      namespace: myapp
    spec:
      entryPoints:
        - web
      routes:
        - match: Host(`myapp.k8s.martials.no`)
          kind: Rule
          services:
            - name: myapp-svc
              port: 80
  '')
];

See toolbox.nix for a complete example.

Customizing Networking

Edit common.nix to configure:

  • networking.localIp: LoadBalancer IP address
  • networking.domain.root: Base domain
  • networking.domain.k8s: Kubernetes subdomain

Quick Start

# Enter development shell (provides nixidy, kubectl, sops)
nix develop

# View available commands
just

# Build manifests (preview, doesn't modify files)
just build

# Generate manifests to manifests/dev/
just switch

# Review changes and commit
git diff manifests/
git add env/ manifests/
git commit -m "Update configuration"
git push

Note: ArgoCD automatically deploys changes pushed to the repository.

Common Operations

Run just or just --list to see all available commands. Most common:

just build              # Preview generated manifests
just switch             # Generate and write manifests
just diff               # Compare current vs generated
just argocd-status      # Check ArgoCD application status
just pods               # View all pods
just sops-edit          # Edit encrypted secrets
just regen-crds         # Regenerate CRD type modules from generators

See the justfile for the complete list of operations.

Development Workflow

Making Changes

  1. Edit configuration in env/dev/*.nix
  2. Build and validate: just build
  3. Generate manifests: just switch
  4. Review: git diff manifests/
  5. Commit and push
  6. ArgoCD auto-syncs within minutes

Adding a New Application

  1. Create env/dev/myapp.nix — it is automatically discovered by import-tree, no registration needed:
{ lib, ... }:

{
  applications.myapp = {
    namespace = "myapp";
    createNamespace = true;
    
    resources = let
      labels = { "app.kubernetes.io/name" = "myapp"; };
    in {
      deployments.myapp.spec = {
        replicas = 2;
        selector.matchLabels = labels;
        template = {
          metadata.labels = labels;
          spec.containers.myapp = {
            image = "registry.example.com/myapp:v1.0.0";
            ports.http.containerPort = 8080;
          };
        };
      };
      
      services.myapp.spec = {
        selector = labels;
        ports.http = { port = 80; targetPort = 8080; };
      };
    };
  };
}
  1. Build, switch, and commit as usual

See DEPLOYMENT_GUIDE.md for detailed examples including ingress, secrets, databases, and CI/CD setup.

Using Helm Charts

helm.releases.myapp = {
  chart = lib.helm.downloadHelmChart {
    repo = "https://charts.example.com";
    chart = "app";
    version = "1.0.0";
    chartHash = "";  # Leave empty; build error provides correct hash
  };
  
  values = {
    replicaCount = 2;
    # ... other values
  };
};

Managing Secrets with SOPS

# Edit encrypted secrets (requires age key configured)
just sops-edit

# Secrets are automatically decrypted by SOPS operator in cluster

Important: Never edit .sops.yaml files directly with text editors. Always use sops command.

Documentation

  • DEPLOYMENT_GUIDE.md: Comprehensive guide for deploying applications with CI/CD
  • AGENTS.md: Guidelines for AI agents and contributors
  • justfile: All available commands with descriptions

Architecture

  • Type Safety: Nixidy validates resources against Kubernetes schemas
  • Reproducibility: flake.lock pins all dependencies
  • GitOps: Single source of truth in Git, ArgoCD handles deployment
  • Declarative: Entire cluster state defined in Nix configuration
  • Secrets: SOPS encrypts secrets at rest in Git, decrypted in-cluster

Resources

License

Personal cluster configuration. Use as reference for your own setup.