//Eddie Brinton-Quinn ghostwire

2nd Line Support Engineer · 24/7 tinkerer · united kingdom

DOSSIER — PRJ-003

AI-assisted draft

This dossier was drafted with AI assistance. The long-term plan is to hand-write these as time allows; this one hasn't been rewritten yet.

Bleecker — Ansible estate automation platform

Project ID

PRJ-003

Status

Perpetual · maintained

Commenced

2024 (Oct)

Production

22 months · 397 commits

Line

Estate foundation · carries PRJ-002's device roles

Source

github.com/eddiebquinn/Bleecker (public mirror)

Not a bounded project - a platform the estate runs on, treated as production tooling: versioned, CI-gated, actively maintained. This dossier describes the system as it stands, not a completion state.

Lifecycle model

Hosts move through explicit phases, with state held in a marker file rather than inferred:

  • Detection (00-detect): classifies the estate into provisioned / unprovisioned / unreachable, emitted as CI artifacts that later jobs intersect against
  • First contact (10-provision): bootstrap user becomes a dedicated automation user with its own key; marker written; never mixed into recurring runs
  • Convergence (20-baseline, site.yml): composable roles - users, ssh_hardening, apt_timers, motd_dynamic, docker_packages, docker_agent_user, docker_registry_auth, k3s_agent_user - idempotent, gated by inventory group
  • Patching (30-apt-upgrade): scheduled, non-interactive, reboot-aware, autoremove

Inventory defines what exists (hosts, IPs, MACs, groups); group_vars define how each class is configured. No conditional logic scattered through tasks, no snowflake state.

Deployment contract

29 compose applications deploy through one generic contract instead of per-app logic:

  • 26 of the deploy playbooks are thin wrappers over a shared _app.yml import template - 22 are minimal (app name only), 4 carry extra overrides (vars prefix, repo label, a custom git base URL)
  • 3 structural exceptions encode real topology splits: core/periphery (Komodo, Pangolin), core/exporters (monitoring)
  • Conventions derive what would otherwise be per-app config: repo URL from a shared base + app name, branch overrides and deploy targets from app name, Infisical path /<app>/application, deploy script ./deploy.sh
  • Adding an application = one 3-line playbook + one CI variable set

This shape is paid-down debt: the wrappers were previously ~90% duplicated boilerplate (55-line deploy plays reduced to 4), with the deploy smoke-test job hand-picked per app rather than systematic.

CI pipeline

Lifecycle-aware gating before anything mutates a host:

  1. Syntax validation across all playbooks on every MR
  2. State detection - the dry-run scope intersects the provisioned set, so a brand-new host cannot fail the gate it has not yet passed
  3. Check-mode dry-run with diff, provisioned hosts only
  4. Provisioning and apply remain manual, explicitly scoped, fail-fast
  5. Scheduled pipelines run patching autonomously

Security and validation templates are included from a central CI repository rather than copied per-project. forks = 5 was tuned from dry-run reliability evidence across the estate, not guessed.

Network configuration

Both network devices are inventory citizens under network_devices:

Group Device Transport
routeros_switches gridlink-1 (CRS328 L3 switch) network_cli + community.routeros, SSH key
opnsense_firewalls blackice-1 (OPNsense) REST API (oxlorg.opnsense), key/secret

Discovery-then-enforce: a read-only baseline capture (interfaces, routes, firewall filter/NAT/mangle, OSPF, LLDP) feeds authoring of the enforcement roles - routeros_l3_switch and opnsense_firewall. PRJ-002's device configuration is these roles.

Secrets and environment

No secrets in git. Credentials arrive at run time via CI variables or Infisical; sensitive tasks run no_log. The dev shell is a pinned Nix flake, so the contributor environment is reproducible.

Maintenance

In production since October 2024: 397 commits. Cadence tracks demand on the tool - quiet when the estate is stable (10 commits in the launch quarter, a near-silent late 2025), 142 in 2026-Q2 and 164 already in Q3 as the network and deploy estate leaned on it. The public repository is a read-only mirror; the canonical source runs on self-managed GitLab and builds the running systems.


← back to selected work