@crvouga/dev-fleet 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -17
- package/ansible/github/git.yml +66 -0
- package/ansible/macos/policy.json +12 -1
- package/ansible/monitoring/compose.yml +10 -0
- package/ansible/monitoring/container-watchdog.py +118 -0
- package/ansible/monitoring/hub-darwin.yml +146 -0
- package/ansible/net/remote-probe.sh +5 -0
- package/ansible/platforms.json +111 -0
- package/ansible/ubuntu/authorize-sudo.sh +7 -16
- package/ansible/ubuntu/baseline.yml +6 -28
- package/ansible/ubuntu/disk-gc.py +211 -7
- package/ansible/ubuntu/disk-guard.py +24 -5
- package/ansible/ubuntu/policy.json +68 -4
- package/ansible/ubuntu/t3-desktop.yml +2 -2
- package/ansible/ubuntu/tailscale.yml +20 -9
- package/ansible/ubuntu/tasks/browser.yml +56 -0
- package/ansible/ubuntu/tasks/docker.yml +52 -0
- package/ansible/ubuntu/tasks/dpkg.yml +46 -0
- package/ansible/ubuntu/tasks/install.yml +38 -0
- package/ansible/ubuntu/tasks/packages.yml +4 -55
- package/ansible/ubuntu/tasks/release.yml +25 -0
- package/ansible/ubuntu/tasks/resources.yml +7 -6
- package/ansible/ubuntu/tasks/services.yml +13 -0
- package/ansible/ubuntu/tasks/snapshot.yml +50 -0
- package/ansible/ubuntu/tasks/unattended-upgrades.yml +24 -0
- package/bootstrap/doctor.ts +32 -6
- package/bootstrap/fleet-remote-bootstrap.sh +49 -45
- package/bootstrap/setup.ts +23 -8
- package/bootstrap/worker-tools.ts +118 -0
- package/cliproxy/README.md +1 -1
- package/cliproxy/compose.yaml +4 -0
- package/cliproxy/scripts/checkpoint.py +1 -1
- package/docs/authentication.md +90 -0
- package/docs/consumer-setup.md +32 -30
- package/docs/declared.md +6 -5
- package/docs/machine-setup.md +22 -12
- package/docs/operations.md +87 -31
- package/docs/runbooks.md +377 -0
- package/docs/state.md +13 -7
- package/docs/support-matrix.md +36 -0
- package/docs/ubuntu-sync.md +16 -13
- package/docs/worker-contract.md +28 -1
- package/examples/fleet.json +19 -1
- package/llms.txt +2 -0
- package/mise.toml +7 -0
- package/package.json +2 -2
- package/schema/check-ids.json +526 -0
- package/schema/fleet.schema.json +185 -4
- package/schema/output/check.schema.json +23 -0
- package/schema/output/error.schema.json +14 -0
- package/schema/output/fleet-report.schema.json +79 -0
- package/schema/output/fleet-sync.schema.json +112 -0
- package/schema/output/report.schema.json +38 -0
- package/src/auth-checks.ts +3 -0
- package/src/cli/agent-guide.ts +5 -3
- package/src/cli/fleet-report.ts +126 -0
- package/src/cli/fleet-sync-manager.ts +11 -0
- package/src/cli/fleet-sync-plan.ts +200 -0
- package/src/cli/fleet-sync-remote.ts +4 -2
- package/src/cli/fleet-sync-schedule.ts +142 -35
- package/src/cli/fleet-sync.ts +90 -8
- package/src/cli/fleet-watch.ts +198 -0
- package/src/cli/fleet.ts +4 -0
- package/src/cli/register-fleet.ts +51 -0
- package/src/cli/registry.ts +13 -0
- package/src/cli/schedule-logs.ts +36 -0
- package/src/clock.ts +63 -0
- package/src/definition.ts +160 -12
- package/src/git-identity.ts +160 -0
- package/src/machine/platform.ts +48 -28
- package/src/machine/support-matrix.ts +76 -0
- package/src/machine-health.ts +51 -4
- package/src/manager-health.ts +205 -0
- package/src/manager-sync.ts +27 -9
- package/src/monitoring/hub-backup.ts +63 -17
- package/src/monitoring/manager-hub.ts +44 -2
- package/src/network-definition.ts +1 -1
- package/src/node-converge-linux.ts +16 -5
- package/src/node-converge.ts +1 -1
- package/src/notify.ts +239 -0
- package/src/platform/debian-version.ts +62 -0
- package/src/platform/ubuntu-audit.ts +11 -4
- package/src/platform/ubuntu-release.ts +41 -0
- package/src/remote-bootstrap.ts +89 -25
- package/src/remote-operation.ts +213 -0
- package/src/schedule-check.ts +40 -0
- package/src/secrets.ts +26 -8
- package/src/ssh.ts +10 -2
- package/src/state/history.ts +172 -0
- package/src/state/store.ts +11 -4
- package/src/tailscale.ts +51 -0
- package/src/toolchain-checks.ts +8 -3
- package/src/worker-capability-checks.ts +167 -0
- package/src/worker-capacity.ts +19 -7
- package/src/worker-host-checks.ts +68 -10
- package/src/worker-policy.ts +33 -0
- package/src/worker-readiness.ts +10 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Support matrix
|
|
2
|
+
|
|
3
|
+
Which platforms dev-fleet runs on, in which role, and what happens to the
|
|
4
|
+
rest. The default is one macOS manager and Ubuntu workers treated as cattle.
|
|
5
|
+
|
|
6
|
+
- **supported**: converged, measured and tested on every pull request.
|
|
7
|
+
- **best effort**: works and is not tested as a fleet role.
|
|
8
|
+
- **refused**: stopped with the named reason before anything is installed.
|
|
9
|
+
|
|
10
|
+
<!-- Generated by `bun src/machine/support-matrix.ts` from ansible/macos/policy.json, ansible/ubuntu/policy.json and ansible/platforms.json; features/rules/support-matrix.feature fails when it differs. -->
|
|
11
|
+
|
|
12
|
+
| Role | Platform | Versions | Architectures | Status | Note |
|
|
13
|
+
| -------------- | --------- | ------------------- | --------------- | ----------- | ----------------------------------------------------------------------------------------- |
|
|
14
|
+
| manager | macOS | 14 or newer | arm64, x86_64 | supported | ansible/macos/policy.json |
|
|
15
|
+
| worker | Ubuntu | 26.04 (resolute) | amd64, arm64 | supported | ansible/ubuntu/policy.json; a machine of its own, physical or virtual |
|
|
16
|
+
| manager | any other | any | any | refused | The fleet configuration accepts only a macOS manager. |
|
|
17
|
+
| worker | Ubuntu | any other release | any | refused | UBUNTU_BASELINE_MISMATCH |
|
|
18
|
+
| worker | Ubuntu | an accepted release | any other | refused | UBUNTU_BASELINE_MISMATCH |
|
|
19
|
+
| worker | Debian | any | any | refused | UBUNTU_BASELINE_MISMATCH |
|
|
20
|
+
| worker | macOS | any | any | refused | The fleet configuration accepts only Linux workers. |
|
|
21
|
+
| worker | Windows | any | any | refused | The fleet configuration accepts only Linux workers. |
|
|
22
|
+
| worker | WSL2 | any | any | refused | WORKER_ENVIRONMENT_UNSUPPORTED |
|
|
23
|
+
| worker | container | any | any | refused | WORKER_ENVIRONMENT_UNSUPPORTED |
|
|
24
|
+
| toolchain only | macOS | any | arm64, x86_64 | best effort | No fleet role: devfleet bootstrap installs the pinned tools (docs/machine-setup.md). |
|
|
25
|
+
| toolchain only | Linux | any | x86_64, aarch64 | best effort | No fleet role: devfleet bootstrap installs the pinned tools (docs/machine-setup.md). |
|
|
26
|
+
| toolchain only | WSL2 | any | x86_64 | best effort | Treated as Linux: devfleet bootstrap installs the pinned tools (docs/machine-setup.md). |
|
|
27
|
+
| toolchain only | Windows | any | x64 | best effort | No fleet role: bootstrap/bootstrap.ps1 installs the pinned tools (docs/machine-setup.md). |
|
|
28
|
+
| toolchain only | Alpine | any | any | refused | musl: the pinned mise build needs glibc. |
|
|
29
|
+
|
|
30
|
+
A worker is refused by the first check that can tell: the fleet configuration
|
|
31
|
+
refuses a worker that is not Linux, the platform probe refuses another
|
|
32
|
+
release, CPU or environment (`ubuntu:release`, `platform:environment`), and
|
|
33
|
+
the bootstrap and the Ubuntu baseline refuse them again on the machine.
|
|
34
|
+
|
|
35
|
+
Supporting another platform means adding it to the policy that names it, with
|
|
36
|
+
its package pins, a fresh-box job and its row here.
|
package/docs/ubuntu-sync.md
CHANGED
|
@@ -61,10 +61,9 @@ resolve enrolled fleet
|
|
|
61
61
|
|
|
62
62
|
Bare invocation selects every canonical Linux and macOS node. It does not mean
|
|
63
63
|
“this computer,” and the manager is not implicitly a deployment target. Its own
|
|
64
|
-
node is targeted only if explicitly declared in Fleet membership.
|
|
65
|
-
the
|
|
66
|
-
|
|
67
|
-
Windows machines stay declared for diagnostics and are never converged.
|
|
64
|
+
node is targeted only if explicitly declared in Fleet membership. Workers are the
|
|
65
|
+
Ubuntu releases the [support matrix](support-matrix.md) lists; it also says what
|
|
66
|
+
is refused (macOS and Windows workers, WSL2, containers) and why.
|
|
68
67
|
`--node ID` filters troubleshooting/rollout. `--all` is an explicit spelling of the
|
|
69
68
|
default. Neither flag authorizes managing arbitrary Tailscale peers.
|
|
70
69
|
|
|
@@ -117,9 +116,8 @@ included, to the exact version in `ansible/ubuntu/policy.json`. The interactive
|
|
|
117
116
|
roster in the [fleet state](state.md), using the existing roster schema.
|
|
118
117
|
Preserve workspace/runtime paths, capabilities and explicit `tailscaleId`
|
|
119
118
|
bindings.
|
|
120
|
-
- Workstation network consumers derive their inventory from
|
|
121
|
-
|
|
122
|
-
lossless identity-path migration; conflicts fail rather than silently winning.
|
|
119
|
+
- Workstation network consumers derive their inventory from the fleet
|
|
120
|
+
configuration; conflicts fail rather than silently winning.
|
|
123
121
|
- Manager approval: the `enrollment` document in the [fleet state](state.md).
|
|
124
122
|
Manager deployment lock: `~/.local/share/personal/fleet/manager/sync.lock`.
|
|
125
123
|
- Remote source: `~/.local/share/personal/fleet/revisions/FULL_SHA`.
|
|
@@ -211,14 +209,19 @@ vault kv get -field=FLEET_WORKER_TOKEN_WORKER_ONE secret/personal/prd \
|
|
|
211
209
|
| ssh worker-one 'vault login -address=https://vault.example.com -no-print -'
|
|
212
210
|
```
|
|
213
211
|
|
|
214
|
-
From then on the node's `personal-worker-auth` timer renews that token and
|
|
215
|
-
GitHub login
|
|
212
|
+
From then on the node's `personal-worker-auth` timer renews that token and
|
|
213
|
+
restores its GitHub login from it (`bootstrap/worker-auth.ts`). It renders no
|
|
214
|
+
provider configuration: agent profiles are applied by `fleet-sync`. See
|
|
215
|
+
[Authentication and accounts](authentication.md).
|
|
216
216
|
|
|
217
217
|
## Ubuntu and remote-work safety
|
|
218
218
|
|
|
219
|
-
The
|
|
220
|
-
|
|
221
|
-
|
|
219
|
+
The accepted releases are named once, in `ansible/ubuntu/policy.json`, and
|
|
220
|
+
listed in the [support matrix](support-matrix.md). Other releases receive
|
|
221
|
+
`UBUNTU_BASELINE_MISMATCH`, and WSL2 and containers
|
|
222
|
+
`WORKER_ENVIRONMENT_UNSUPPORTED`; there is no automatic release upgrade or
|
|
223
|
+
package downgrade. Package pins are minimums: see the
|
|
224
|
+
[worker contract](worker-contract.md#package-pins-and-security-updates). Fleet audits release, packages, service state and dpkg
|
|
222
225
|
consistency, declares snapshot sources for managed transactions, and pins its
|
|
223
226
|
selected APT packages. Unrelated applications and package sources are preserved.
|
|
224
227
|
|
|
@@ -268,7 +271,7 @@ promise. Inspect disk/inodes, swap/memory pressure, `systemctl --failed`, and pr
|
|
|
268
271
|
boot journal evidence locally; sanitize it before sharing. Do not enable automatic
|
|
269
272
|
reboot-on-pressure or kill active work to obtain a green report.
|
|
270
273
|
|
|
271
|
-
T3
|
|
274
|
+
The pinned T3's (`t3_version` in `mise.toml`) supported administrator policy at `/etc/t3code/policy.json`
|
|
272
275
|
disables independent updates and declares the existing managed Codex instance
|
|
273
276
|
plus an OpenCode instance for all five gateway models. Fleet reuses the
|
|
274
277
|
existing `agents/t3.json` renderer; it does not edit the live settings database.
|
package/docs/worker-contract.md
CHANGED
|
@@ -12,7 +12,8 @@ devfleet fleet-status --workers
|
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
The manager needs Node/npm, Git, SSH, Tailscale, and its own authorized T3 link.
|
|
15
|
-
Initially each
|
|
15
|
+
Initially each worker (an Ubuntu release the [support matrix](support-matrix.md)
|
|
16
|
+
lists) needs a
|
|
16
17
|
designated non-root account, trusted SSH access and administrator authorization. Standard Ubuntu cloud-image users
|
|
17
18
|
already commonly have noninteractive sudo; otherwise establish the repository's
|
|
18
19
|
`authorize-sudo.sh` policy once during administrator enrollment. Routine commands
|
|
@@ -39,6 +40,32 @@ HEAD. Private rosters contain connection paths and identities, not weaker policy
|
|
|
39
40
|
| No routine password prompts | Verified BatchMode SSH, `sudo -n`, source-owned NOPASSWD policy; missing initial authorization is a failure |
|
|
40
41
|
| Keep service authorization alive | Native service credentials stay per-node; Vault self-renewal timer and GitHub recovery from authorized Vault credentials; expiring T3 links are reported before expiry |
|
|
41
42
|
|
|
43
|
+
## Package pins and security updates
|
|
44
|
+
|
|
45
|
+
A pin in `ansible/ubuntu/policy.json` is a **minimum**, never a hold. Ubuntu
|
|
46
|
+
keeps installing security updates by itself, and a worker is not turned red by
|
|
47
|
+
one:
|
|
48
|
+
|
|
49
|
+
- The Ubuntu baseline installs a pinned package from the snapshot only when it
|
|
50
|
+
is absent or older than its pin, and never downgrades
|
|
51
|
+
(`ansible/ubuntu/tasks/install.yml`; every pinned package, `systemd-oomd`
|
|
52
|
+
included, goes through it).
|
|
53
|
+
- What Ubuntu installs unattended is declared in
|
|
54
|
+
`/etc/apt/apt.conf.d/52personal-fleet-unattended-upgrades`: security updates
|
|
55
|
+
only, no automatic reboot, no removals.
|
|
56
|
+
- `worker:package:NAME` passes at the pin, **warns** with
|
|
57
|
+
`PACKAGE_NEWER_THAN_PIN` above it, and fails with `PACKAGE_BELOW_PIN` below
|
|
58
|
+
it or when the package is missing. A warning does not block convergence or
|
|
59
|
+
readiness; it says the pin can be raised when the snapshot moves.
|
|
60
|
+
- Tailscale follows the same rule: a newer Tailscale is kept; an older one
|
|
61
|
+
stops with `TAILSCALE_UPGRADE_PENDING`, because upgrading an active VPN can
|
|
62
|
+
drop SSH.
|
|
63
|
+
|
|
64
|
+
A package run cut off by a power loss is finished by the next sync: the
|
|
65
|
+
baseline waits for the APT lock, runs `dpkg --configure -a` once (bounded to
|
|
66
|
+
ten minutes) and audits again; only a database still inconsistent stops with
|
|
67
|
+
`APT_STATE_BROKEN`.
|
|
68
|
+
|
|
42
69
|
Health does not mutate configuration, renew tokens, log in, install software, or
|
|
43
70
|
make billable inference requests. It audits the immutable desired worker deployment,
|
|
44
71
|
not an unrelated developer branch. Every declared worker must be enrolled and
|
package/examples/fleet.json
CHANGED
|
@@ -29,6 +29,14 @@
|
|
|
29
29
|
"proxy-tunnel-token": {
|
|
30
30
|
"path": "cliproxy-fleet/tunnel",
|
|
31
31
|
"field": "TUNNEL_TOKEN"
|
|
32
|
+
},
|
|
33
|
+
"monitoring-backup-access-key": {
|
|
34
|
+
"path": "beszel/backups",
|
|
35
|
+
"field": "ACCESS_KEY_ID"
|
|
36
|
+
},
|
|
37
|
+
"monitoring-backup-secret-key": {
|
|
38
|
+
"path": "beszel/backups",
|
|
39
|
+
"field": "SECRET_ACCESS_KEY"
|
|
32
40
|
}
|
|
33
41
|
}
|
|
34
42
|
},
|
|
@@ -73,7 +81,16 @@
|
|
|
73
81
|
"hubPort": 8443,
|
|
74
82
|
"publicUrl": "https://beszel.example.com",
|
|
75
83
|
"managerAccount": "fleet-manager@example.com",
|
|
76
|
-
"viewerAccount": "public-viewer@example.com"
|
|
84
|
+
"viewerAccount": "public-viewer@example.com",
|
|
85
|
+
"backups": {
|
|
86
|
+
"schedule": "0 3 * * *",
|
|
87
|
+
"keep": 7,
|
|
88
|
+
"storage": {
|
|
89
|
+
"bucket": "my-fleet-hub-backups",
|
|
90
|
+
"endpoint": "https://s3.example.com",
|
|
91
|
+
"region": "auto"
|
|
92
|
+
}
|
|
93
|
+
}
|
|
77
94
|
}
|
|
78
95
|
},
|
|
79
96
|
"ubuntu": {
|
|
@@ -92,6 +109,7 @@
|
|
|
92
109
|
"githubLogin": "example-user",
|
|
93
110
|
"vaultUser": "example-user",
|
|
94
111
|
"toolchain": "mise.lock",
|
|
112
|
+
"toolProfiles": ["go"],
|
|
95
113
|
"agentProfile": "proxy",
|
|
96
114
|
"unattendedSudo": true,
|
|
97
115
|
"persistentT3": true,
|
package/llms.txt
CHANGED
|
@@ -31,6 +31,8 @@ Rules for an agent working in a project that uses dev-fleet:
|
|
|
31
31
|
- [Ubuntu fleet-sync reference](https://github.com/crvouga/dev-fleet/blob/main/docs/ubuntu-sync.md): enrollment, approval, machine policy by platform, remote-work safety
|
|
32
32
|
- [Worker contract](https://github.com/crvouga/dev-fleet/blob/main/docs/worker-contract.md): what a worker guarantees and how readiness is scoped
|
|
33
33
|
- [Operations](https://github.com/crvouga/dev-fleet/blob/main/docs/operations.md): roster, diagnostics and repairs
|
|
34
|
+
- [Runbooks](https://github.com/crvouga/dev-fleet/blob/main/docs/runbooks.md): every failure code, how to confirm it, the fix and when to escalate
|
|
35
|
+
- [Authentication and accounts](https://github.com/crvouga/dev-fleet/blob/main/docs/authentication.md): where each credential lives, how it reaches each node and how it rotates
|
|
34
36
|
- [Coding agents on every node](https://github.com/crvouga/dev-fleet/blob/main/agents/setup.md): agent launchers and the T3 providers
|
|
35
37
|
- [Releasing](https://github.com/crvouga/dev-fleet/blob/main/docs/releasing.md): how a version is published from one commit (for dev-fleet developers)
|
|
36
38
|
- [Features](https://github.com/crvouga/dev-fleet/blob/main/features/README.md): the behaviour specified in Gherkin (for dev-fleet developers)
|
package/mise.toml
CHANGED
|
@@ -110,3 +110,10 @@ docker_desktop_amd64_sha256 = "96b53f9a4a807b6be6207d18f360b9778ff481e1d94b5027b
|
|
|
110
110
|
|
|
111
111
|
# Minimal remote development baseline; versions are resolved exclusively by tools + mise.lock.
|
|
112
112
|
worker_tools = "bun,node,gh,python,uv,docker-cli,vault,jq,codex,claude,aqua:anomalyco/opencode,gemini,copilot,http:grok,http:antigravity"
|
|
113
|
+
# Tool profiles a fleet adds to its workers (`worker.toolProfiles` in
|
|
114
|
+
# fleet.json, fleet-wide or per worker): one `worker_profile_<name>` each,
|
|
115
|
+
# naming tools pinned above. bootstrap/worker-tools.ts lists the names.
|
|
116
|
+
worker_profile_web = "pnpm,deno,npm:@yarnpkg/cli-dist"
|
|
117
|
+
worker_profile_go = "go"
|
|
118
|
+
worker_profile_rust = "rust,cmake,ninja"
|
|
119
|
+
worker_profile_jvm = "java"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crvouga/dev-fleet",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Keeps a set of development machines in sync: one manager and many workers",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "github:crvouga/dev-fleet",
|
|
@@ -72,5 +72,5 @@
|
|
|
72
72
|
"engines": {
|
|
73
73
|
"node": ">=22"
|
|
74
74
|
},
|
|
75
|
-
"gitHead": "
|
|
75
|
+
"gitHead": "620b8de05d662b4dc9072457580ca4b4eab54242"
|
|
76
76
|
}
|