Project ID
PRJ-003
2nd Line Support Engineer · 24/7 tinkerer · united kingdom
DOSSIER — PRJ-003
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.AI-assisted draft
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.
Hosts move through explicit phases, with state held in a marker file rather than inferred:
00-detect): classifies the estate into provisioned / unprovisioned / unreachable, emitted as CI artifacts that later jobs intersect against10-provision): bootstrap user becomes a dedicated automation user with its own key; marker written; never mixed into recurring runs20-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 group30-apt-upgrade): scheduled, non-interactive, reboot-aware, autoremoveInventory defines what exists (hosts, IPs, MACs, groups); group_vars define how each class is configured. No conditional logic scattered through tasks, no snowflake state.
29 compose applications deploy through one generic contract instead of per-app logic:
_app.yml import template - 22 are minimal (app name only), 4 carry extra overrides (vars prefix, repo label, a custom git base URL)/<app>/application, deploy script ./deploy.shThis 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.
Lifecycle-aware gating before anything mutates a host:
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.
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.
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.
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.