Skip to content

homelabctl2 Overview

homelabctl2 is the homelab operator CLI. It replaced the legacy Rust homelabctl and ships as the registry.gitlab.com/joelmuehlena/homelab/homelabctl2 container image plus a local binary built from the Go workspace.

homelabctl2
├── gitlab
│ └── schedules
│ └── sync # reconcile pipeline schedules vs declarative list
└── tools
└── k8s
└── password-vault-init # generate passwords + write to Vault via TOML

Each subcommand lives in its own subpackage under cmd/homelabctl2/:

cmd/homelabctl2/
├── main.go / root.go # package main — entry + root cmd
├── gitlab/
│ ├── gitlab.go # package gitlab — group cmd
│ └── schedules/schedules.go # package schedules — sync impl
└── tools/
├── tools.go # package tools — group cmd
└── k8s/
├── k8s.go # package k8s — group cmd
└── password_vault_init.go # cobra wiring (~40 LOC)

Real work lives in internal/vaultcred/ (config parse, vault auth, apply).

All commands accept these on the root, applied in PersistentPreRunE before any subcommand runs:

FlagDefaultDescription
--log-levelinfodebug, info, warning, error
--log-formattexttext, json (use json in-cluster for Fluent Bit)

Timestamps are always UTC. See logging lib for the underlying mechanics.

Errors and usage are silenced on the root (SilenceErrors / SilenceUsage) so the structured-log stream stays clean — main.go re-emits any execute error via logging.Get().Error("command failed", ...).

homelabctl2 is part of the Go workspace rooted at go.work:

Terminal window
cd code/homelabctl2
go build ./cmd/homelabctl2 # local binary
go test ./... # unit tests (internal/vaultcred)

Built by the image-rebuild pipeline from code/homelabctl2/Dockerfile. The Dockerfile is a multi-stage Go build finishing in gcr.io/distroless/static-debian12:nonroot.

Terminal window
docker build -f code/homelabctl2/Dockerfile code/homelabctl2

code/homelabctl2/VERSION is the SemVer source of truth. The image rebuild flow picks <version> for new versions and <version>-N for repeat builds at the same SemVer. Bump VERSION in the same MR as a CLI-breaking change so the next rebuild ships under the new tag.