Documentation
¶
Overview ¶
Package state manages the homelab-state working copy (default ~/.hlab): the versioned, declarative description of every VM hlab manages.
Layout:
~/.hlab/
config.yaml connection + secrets — GITIGNORED (contains the token)
plans.yaml VM/LXC plans — versioned
vms/<name>.yaml declaration — VERSIONED (source of truth)
terraform/ generated terraform workspace
terraform.tfvars.json specs — versioned
secrets.auto.tfvars.json passwords — GITIGNORED
*.tfstate, .terraform/ operational — GITIGNORED
.gitignore
Secrets (VM passwords) are never written into the declaration YAML; only a HasPassword flag is recorded.
Index ¶
- Variables
- func EnsureGitignore(dir string, required []string) error
- type Store
- func (s *Store) Commit(message string) error
- func (s *Store) Delete(name string) error
- func (s *Store) Init() error
- func (s *Store) List() ([]*VMSpec, error)
- func (s *Store) Load(name string) (*VMSpec, error)
- func (s *Store) Push() error
- func (s *Store) Save(vm *VMSpec) error
- func (s *Store) TerraformDir() string
- type VMSpec
Constants ¶
This section is empty.
Variables ¶
var RequiredGitignore = []string{
"config.yaml",
"terraform/secrets.auto.tfvars.json",
"terraform/*.tfstate",
"terraform/*.tfstate.*",
"terraform/.terraform/",
"terraform/.terraform.lock.hcl",
".env",
}
RequiredGitignore lists the entries that must be present in the state dir's .gitignore. config.yaml carries the Proxmox token; the rest are operational or secret terraform artifacts. Kept in dependency order (config first) so a freshly created file reads sensibly.
Functions ¶
func EnsureGitignore ¶
EnsureGitignore makes sure every entry in required is present in dir/.gitignore, appending only the missing ones so an operator's own additions (and entries already there) are left untouched — never rewriting the whole file. A brand-new file gets a header comment. Idempotent.
Types ¶
type Store ¶
type Store struct {
Dir string
}
Store is the homelab-state directory.
func (*Store) Commit ¶
Commit stages everything and commits with the given message. Best-effort: it is a no-op when git is unavailable or there is nothing to commit.
func (*Store) Init ¶
Init creates the directory layout and a .gitignore, and initializes git if the directory is not yet a repository.
func (*Store) TerraformDir ¶
type VMSpec ¶
type VMSpec struct {
Name string `yaml:"name"` // hostname = guest name = terraform key = inventory name
// Type discriminates the guest kind: "" or "vm" == QEMU VM (back-compat with
// existing declarations that omit it); "lxc" == LXC container.
Type string `yaml:"type,omitempty"`
Node string `yaml:"node"`
VMID int `yaml:"vmid"`
Template string `yaml:"template"` // human-readable template name
TemplateID int `yaml:"template_id"` // source VM id to clone (VMs only)
Storage string `yaml:"storage"`
Bridge string `yaml:"bridge"`
// LXC-only fields (ignored for VMs).
TemplateFile string `yaml:"template_file,omitempty"` // vztmpl volid, e.g. local:vztmpl/debian-12-standard_...tar.zst
OSType string `yaml:"os_type,omitempty"` // bpg operating_system.type: debian|ubuntu|alpine|...
Unprivileged bool `yaml:"unprivileged,omitempty"`
Nesting bool `yaml:"nesting,omitempty"`
SwapMB int `yaml:"swap_mb,omitempty"`
// HostManagedNet: PVE 9.1+ — Proxmox writes the container's network config
// itself. Required for static-IP CTs there, where the bpg default
// (host-managed=0) means nobody configures the interface and the guest boots
// with no IP.
HostManagedNet bool `yaml:"host_managed_net,omitempty"`
Plan string `yaml:"plan,omitempty"` // preconfigured plan name (e.g. "KVM2"/"micro"), empty = custom
Cores int `yaml:"cores"`
MemoryGB int `yaml:"memory_gb"` // VM memory (GB)
MemoryMB int `yaml:"memory_mb,omitempty"` // LXC memory (MB); sub-GB tiers need this
DiskGB int `yaml:"disk_gb"`
DHCP bool `yaml:"dhcp"`
IPCIDR string `yaml:"ip_cidr,omitempty"`
Gateway string `yaml:"gateway,omitempty"`
DNS []string `yaml:"dns,omitempty"`
Username string `yaml:"username"`
SSHKeys []string `yaml:"ssh_keys,omitempty"` // public key contents
HasPassword bool `yaml:"has_password"` // secret stored separately
// Dotfiles exists only for legacy-YAML migration: dotfiles is an ordinary
// software-catalog entry now, but declarations written before that still say
// `dotfiles: true`. This field must stay so Store.Load can read them (yaml.v3
// silently drops unknown keys, so removing it would lose the selection);
// Store.Load migrates a legacy `dotfiles: true` into Software ("dotfiles") and
// zeroes this, so all downstream code reads only Software, and omitempty keeps
// it out of newly-written declarations.
Dotfiles bool `yaml:"dotfiles,omitempty"`
Software []string `yaml:"software,omitempty"` // catalog keys, e.g. ["docker","node"]
}
VMSpec is the declarative description of a single guest (VM or LXC container).