feat(fleet): FleetDM osquery fleet-manager for all computers #113

Merged
kblack0610 merged 2 commits from feat/fleet-osquery-integration into master 2026-07-10 02:00:32 +00:00
Owner

What

Stand up FleetDM as the single osquery-based inventory / live-query / compliance pane across every computer in the homelab (macOS + x86 Linux + Pi k3s nodes), plus the Ansible osquery-agent role that enrolls hosts into it.

Best-practice model adopted: fleet management is layered by function - Fleet = visibility, Ansible = config convergence, MDM stays per-platform (Headwind/Android is a separate, unaffected track). Plan: ~/.claude/plans/agile-bubbling-stroustrup.md.

Contents

  • apps/fleet/ (Flux): FleetDM v4.88.0 server (stateless) + MySQL 8 + Redis co-located (neither existed in-cluster; shared Postgres does not apply to Fleet). Migrations via a retrying fleet prepare db init container. LAN/Tailnet-only ingress at fleet.kblab.me. Wired into apps/kustomization.yaml.
  • ansible/roles/osquery-agent/: authored, NOT bound (mirrors k3s-agent). macOS (brew cask + LaunchDaemon) and Debian/Pi (apt repo + osqueryd) supported; Arch/x86 fails loudly (osquery is AUR-only) as a tracked follow-up.
  • site.yml: fix stale nut_clients comment (pi5-worker1 IS a nut_client per inventory).

Verified

  • kubectl kustomize apps/fleet builds (10 resources); root apps still builds.
  • ansible-playbook --syntax-check passes; SOPS secret round-trips (3 keys).

GATED before merge/deploy (Flux reconciles on merge to master)

  1. Label a datastore node (REQUIRED) - keeps MySQL/Redis off asus-laptop (the SPOF that took the cluster down 2026-07-09):
    kubectl --context home-k3s label node <non-asus-node> fleet.storage/node=true
    Until then the datastores stay Pending by design.
  2. Confirm exposure: LAN/Tailnet-only (default) vs public crowdsec bouncer.
  3. Post-deploy: bootstrap admin at https://fleet.kblab.me, copy the osquery enroll secret into vault_fleet_enroll_secret, then bind + run the osquery-agent role.

See apps/fleet/README.md and ansible/roles/osquery-agent/README.md.

## What Stand up **FleetDM** as the single osquery-based inventory / live-query / compliance pane across every **computer** in the homelab (macOS + x86 Linux + Pi k3s nodes), plus the Ansible `osquery-agent` role that enrolls hosts into it. Best-practice model adopted: fleet management is **layered by function** - Fleet = visibility, Ansible = config convergence, MDM stays per-platform (Headwind/Android is a separate, unaffected track). Plan: `~/.claude/plans/agile-bubbling-stroustrup.md`. ## Contents - **`apps/fleet/`** (Flux): FleetDM v4.88.0 server (stateless) + MySQL 8 + Redis co-located (neither existed in-cluster; shared Postgres does not apply to Fleet). Migrations via a retrying `fleet prepare db` init container. LAN/Tailnet-only ingress at `fleet.kblab.me`. Wired into `apps/kustomization.yaml`. - **`ansible/roles/osquery-agent/`**: authored, **NOT bound** (mirrors `k3s-agent`). macOS (brew cask + LaunchDaemon) and Debian/Pi (apt repo + osqueryd) supported; Arch/x86 fails loudly (osquery is AUR-only) as a tracked follow-up. - **`site.yml`**: fix stale nut_clients comment (pi5-worker1 IS a nut_client per inventory). ## Verified - `kubectl kustomize apps/fleet` builds (10 resources); root `apps` still builds. - `ansible-playbook --syntax-check` passes; SOPS secret round-trips (3 keys). ## GATED before merge/deploy (Flux reconciles on merge to master) 1. **Label a datastore node** (REQUIRED) - keeps MySQL/Redis off asus-laptop (the SPOF that took the cluster down 2026-07-09): `kubectl --context home-k3s label node <non-asus-node> fleet.storage/node=true` Until then the datastores stay Pending by design. 2. **Confirm exposure**: LAN/Tailnet-only (default) vs public crowdsec bouncer. 3. **Post-deploy**: bootstrap admin at https://fleet.kblab.me, copy the osquery enroll secret into `vault_fleet_enroll_secret`, then bind + run the `osquery-agent` role. See `apps/fleet/README.md` and `ansible/roles/osquery-agent/README.md`.
Stand up FleetDM as the single inventory / live-query / compliance pane
across every computer in the homelab (macOS + x86 Linux + Pi k3s nodes).
Fleet management is layered by function: Fleet = visibility, Ansible =
config convergence, MDM stays per-platform (Headwind for Android is a
separate track and unaffected).

apps/fleet (Flux):
- FleetDM v4.88.0 server (stateless), MySQL 8 + Redis co-located since
  neither existed in-cluster (shared Postgres does not apply to Fleet).
- Datastores pinned OFF asus-laptop via a fleet.storage/node label so they
  can never land on the storage SPOF that hit DiskPressure on 2026-07-09;
  they stay Pending until one non-asus node is labelled (fail-safe).
- LAN/Tailnet-only ingress at fleet.kblab.me (all managed hosts are on the
  LAN/Headscale); crowdsec-public path documented for off-net enrollment.
- Migrations run via a retrying init container (fleet prepare db).
- Wired into apps/kustomization.yaml.

ansible/roles/osquery-agent (authored, NOT bound - like k3s-agent):
- Enrolls hosts into Fleet over TLS. macOS (brew cask + LaunchDaemon) and
  Debian/Pi (official apt repo + osqueryd unit) supported; Arch/x86 fails
  loudly as a tracked follow-up (osquery is AUR-only).
- Enroll secret via vault_fleet_enroll_secret (asserted, no_log). Bind only
  after Fleet is deployed and the secret is generated (see READMEs).

ansible: fix stale nut_clients comment in site.yml (pi5-worker1 IS a
nut_client per inventory; the "intentionally excluded" note was stale).

Syntax-checked (ansible-playbook --syntax-check) and kustomize-built; SOPS
secret round-trips. Deploy is gated on labelling a datastore node + admin
bootstrap - see apps/fleet/README.md.
There is no replicated block storage in home-k3s (local-path only), so
Fleet's MySQL is node-pinned like every other stateful app - the root
cause of the asus-laptop SPOF. Pinning to hp-victus trades one single-node
dependency for another, so it is explicitly interim.

Add docs/distributed-storage-roadmap.md: a phased Longhorn plan to give the
bare-metal cluster replicated storage that survives + reschedules past a
node loss, with FleetDM's MySQL as the first tenant (Phase 3). Cross-link it
from the Fleet mysql-deployment comment + README.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kblack0610/home-config!113
No description provided.