The previous role was netbox-community/netbox-docker (compose-based) but
the live host runs the upstream tarball install directly: system Postgres
17, system Redis 8, gunicorn under systemd, and Caddy reverse-proxy.
Re-running the old role would have torn the working install down.
This rewrite mirrors what's actually deployed:
- defaults: NetBox 4.6.0, /opt/netbox layout, gunicorn 5w/3t/120s, all
configuration.py knobs exposed as ansible vars.
- tasks: install OS deps, ensure netbox user, create Postgres role + db,
download + extract release tarball, run upgrade.sh, render
configuration.py / gunicorn.py / systemd units, enable services.
- templates: configuration.py.j2 covers the same keys the live file sets;
netbox.service / netbox-rq.service are byte-equivalent to the live
units (modulo paths driven by the install-dir var).
- caddy role gets a per-host Caddyfile-netbox.vntx.net.j2 mirroring the
live vhost (25MB body limit, /static/* file_server, reverse_proxy to
127.0.0.1:8001).
- inventory: new netbox_servers group; netbox.vntx.net added to
caddy_servers so the per-host Caddyfile is wired up.
- host_vars/netbox.vntx.net.yml: secrets reference vault_* vars; role
refuses to render config.py until they're set.
Operator action: create host_vars/netbox.vntx.net/vault.yml with
netbox_secret_key, netbox_db_password, and netbox_api_token_peppers
(value visible via `sudo cat /opt/netbox/netbox/netbox/configuration.py`
on the live host). See roles/netbox/README.md.
caddy_ansible.caddy_ansible was only referenced by the (commented) netbox play,
so removing the disabled play also makes the role unused. ns play was already
superseded by the BIND9 play. Tailscale-on-home-hosts was never re-enabled
post-Talos-migration — drop the stub; restore from git history if needed.
- grafana role: empty grafana_admin_password by default, and only emit
admin_password into grafana.ini when the var is set. Previously the
default 'admin' was rewritten on every run, clobbering passwords
rotated via the Grafana UI.
- bootstrap.yml: probe for sudo state before attempting su-as-root.
The first play was using become_method=su unconditionally; on hosts
where graham already has passwordless sudo (or where -K isn't passed),
ansible blocked indefinitely waiting for a root password prompt.
Now the install-via-su task only runs when sudo is actually missing,
and the python3 task uses sudo when available.
Also bring in latest microwaveprop dashboard tweaks.
Dashboards: aprs-me, towerops-{application,beam,ecto,oban,phoenix,phoenix-live-view}.
prometheus.yml.j2: kubernetes-pods job now honors a `prometheus.io/job`
pod annotation so apps can claim a named job label (e.g. towerops)
instead of bucketing under job=kubernetes-pods.
Cluster-side:
- Deploy kube-state-metrics (kube-system) for cluster-state series.
- Deploy node-exporter DaemonSet on all 7 nodes via the new monitoring ns
(privileged PSS, hostNetwork, read-only host mounts).
- Both managed by ArgoCD apps under home/cluster/argocd/apps/.
Prometheus-side:
- Replace direct pod-IP scraping (which can't reach the 10.244.0.0/16 pod
network from outside the cluster) with API-server-proxy scraping for
both Services and Pods. Now one target per pod, all healthy.
- Extend external Prometheus RBAC with services/proxy + pods/proxy.
Grafana-side:
- Add file-based dashboard provisioner; ship 5 standard dashboards
(Node Exporter Full, k8s cluster-via-prometheus, k8s all-in-one,
k8s monitoring, Prometheus 2.0 overview).
prom.w5isp.com:3000 now shows live data for all 7 cluster nodes plus
the prom host itself.
Provisions prom.w5isp.com (10.0.15.31) as the home-cluster monitoring host.
Prometheus 3.6.0 scrapes the Talos cluster API/nodes/cAdvisor via an external
SA token; Grafana ships with the Prometheus datasource pre-provisioned.
host_vars opens 9090/9093/9100/3000 to 10.0.0.0/16 plus SSH from the home LAN
so the firewall role doesn't lock out admin access.
The towerops-web repo got renamed to codeberg.org/gmcintire/towerops
and its container image follows the same rename
(codeberg.org/gmcintire/towerops). Application source repo and
image-updater registry list updated.
The prop and prop-grid-rs container images now live on
codeberg.org/gmcintire/* (see prop repo commit 8a9c0ba6 for the
workflow flip). Application source repo and image-updater registry
list follow.
Cluster-side state still required for this to roll out, applied
out-of-band via kubectl:
- Secret prop/forgejo-registry — dockerconfigjson with codeberg.org
auth (also keeps git.mcintire.me auth during the transition).
- Secret argocd/forgejo-registry — same shape, used by the
argocd-image-updater registry config.
- Secret argocd/codeberg-credentials-gmcintire (label
argocd.argoproj.io/secret-type=repo-creds) — credentials template
matching url=https://codeberg.org/gmcintire so future codeberg
repos under that owner pick up auth automatically.
- ConfigMap argocd/argocd-image-updater-config — registries.conf
extended with codeberg.org entry referencing the new pull secret.
annotates the 4 Applications so image-updater scans git.mcintire.me
on a 2min loop and writes new tags to spec.source.kustomize.images
(no git commits, no CI sed-and-bump).
Configure passthrough NVMe drives (/dev/sdb) on each worker with
XFS partition mounted at /var/mnt/longhorn. Switch worker installer
image to Talos Image Factory build with iscsi-tools and util-linux-tools
extensions required by Longhorn. Remove conflicting grubUseUKICmdline
setting.
- Upgrade all nodes from v1.12.1/v1.12.2 to v1.12.4 installer image
- Set explicit nameservers (9.9.9.9, 149.112.112.112, 1.1.1.1) on
workers to replace unreliable DHCP-provided resolver at 10.0.15.254
- Fix talos-worker2 missing ExtensionServiceConfig for ext-tailscale
which was causing node reboots every ~35 minutes
- Update tailscale.patch.yaml with working auth key
- Remove proxmox/talos/null providers and variables
- Remove HTTP backend, use local state
- Remove skookum.me, towerops.net, vntx.net, as393837.net from DNS
- Switch aprs.me NS to Cloudflare
- Rename terraform/ to tofu/
- Add marcfrederick/porkbun provider for registrar NS management
- Add dns.tf with all 14 Porkbun domains and import blocks
- Update gridmap.org BIND9 zone NS to Cloudflare
- Update CLAUDE.md to reflect new directory structure