blumeops/docs/tutorials/replicating-blumeops.md
Erich Blume b197bd5f58 Adopt Dagger CI for docs build (Phase 2) (#157)
## Summary

Migrates the docs build pipeline to Dagger (Phase 2 of the Dagger CI adoption plan).

- **Backfill `date-modified` frontmatter** on all 80 docs — Dagger's `--src=.` excludes `.git`, so Quartz can't use git history for page dates. Frontmatter dates work with or without git.
- **New `docs-check-frontmatter` mise task + pre-commit hook** — validates all docs have `title`, `tags`, and `date-modified`
- **New Dagger functions** — `build_changelog` (towncrier in Python container) and `build_docs` (chains changelog → Quartz build in Node container, returns tarball)
- **Simplified CI workflow** — the ~44-line inline Quartz build (clone, npm ci, build, tar, cleanup) is replaced by `dagger call build-docs`. Changelog step remains local on the runner since towncrier needs to modify the host working tree for the git commit.

### Design decisions

- **Towncrier runs twice in CI**: once inside Dagger (for the docs tarball) and once on the runner (for the git commit). This is intentional — Dagger's directory export is additive and can't delete the consumed changelog fragments from the host.
- **Artifact hosting stays on Forgejo Releases** (not migrated to Forgejo Packages as the plan doc originally suggested). That migration can happen independently.
- **`date-modified` frontmatter** preserved even though `build_changelog` installs git — the git there is only for towncrier's `git add` call, not for history. The local iteration story (`dagger call build-docs --src=. --version=dev` with uncommitted changes) depends on frontmatter dates.

### Local iteration

```bash
dagger call build-docs --src=. --version=dev export --path=./docs-dev.tar.gz
tar tf docs-dev.tar.gz | head -20
```

## Deployment and Testing

- [x] `dagger call build-docs --src=. --version=dev` produces valid 1.1MB tarball (149 HTML pages)
- [x] Pre-commit hooks pass (including new `docs-check-frontmatter`)
- [ ] Full `workflow_dispatch` run after merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/157
2026-02-11 16:33:16 -08:00

3.9 KiB

title date-modified tags
Replicating BlumeOps 2026-02-07
tutorials
replication

Replicating BlumeOps

Audiences: Replicator

This tutorial provides a roadmap for building your own homelab GitOps environment inspired by BluemeOps. It links to detailed component tutorials for each major piece.

What You'll Build

By following this guide, you'll have:

  • A secure mesh network connecting your devices
  • A Kubernetes cluster for running containerized services
  • GitOps-driven deployments via ArgoCD
  • Observability with metrics, logs, and dashboards
  • Backup and disaster recovery capabilities

Hardware Requirements

BluemeOps runs on modest hardware. At minimum:

Component BlumeOps Uses Minimum Alternative
Server Mac Mini M1 Any machine with sufficient RAM (16GB recommended)
NAS Synology DS920+ USB drive or second machine
Workstation MacBook Air M4 Whatever you use daily

You can start with a single machine and add storage later.

The Journey

Phase 1: Networking Foundation

Before deploying services, establish secure connectivity.

tailscale-setup

  • Create a tailnet and connect your devices
  • Configure ACLs for service access
  • Set up MagicDNS for convenient naming

This replaces: traditional VPNs, port forwarding, dynamic DNS

Phase 2: Core Services

Bootstrap the essential services that everything else depends on.

core-services

  • Set up forgejo for git hosting and CI/CD
  • Optionally set up zot container registry
  • Configure SSH access and deploy keys

Forgejo is central to GitOps - it's where your infrastructure definitions live and where CI/CD workflows run.

Phase 3: Kubernetes Cluster

A cluster for running containerized workloads.

kubernetes-bootstrap

  • Install minikube (or k3s, kind, etc.)
  • Configure persistent storage
  • Expose the API securely via Tailscale

BlumeOps uses minikube for simplicity, but the patterns apply to any distribution.

Phase 4: GitOps with ArgoCD

Declarative, git-driven deployments.

argocd-config

  • Install ArgoCD in your cluster
  • Connect to your git repository
  • Deploy your first application
  • Set up the app-of-apps pattern

This is the heart of GitOps - changes in git automatically sync to your cluster.

Phase 5: Observability Stack

Know what's happening in your infrastructure.

observability-stack

  • Deploy Prometheus for metrics
  • Deploy Loki for logs
  • Deploy Grafana for dashboards
  • Configure Alloy for collection

Without observability, you're flying blind.

Phase 6: Your First Services

With the foundation in place, deploy actual workloads. BluemeOps runs:

Pick what matters to you. Each service follows similar patterns:

  1. Create Kubernetes manifests
  2. Create ArgoCD Application
  3. Configure ingress routing
  4. Sync and verify

Phase 7: Backups and Resilience

Protect your data.

  • Set up borgmatic for backup automation
  • Configure NAS as backup target
  • Test restore procedures
  • Document disaster recovery

Alternative Approaches

BluemeOps makes specific choices that may not suit everyone:

BlumeOps Choice Alternative
macOS server Linux server (more common)
Minikube k3s, kind, or managed K8s
Tailscale WireGuard, Nebula
ArgoCD Flux, manual kubectl
Ansible NixOS, Docker Compose

The principles (GitOps, IaC, observability) matter more than specific tools.

Getting Started

Begin with tailscale-setup - networking is the foundation everything else builds on.