@crvouga/dev-fleet 0.0.0-stage → 0.2.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/.mise/locks/aws-cdk/2.1146.1/aube-lock.yaml +24 -0
- package/.mise/locks/aws-cdk/2.1146.1/package.json +7 -0
- package/.mise/locks/azure-cli/2.91.0~a837e014/pyproject.toml +5 -0
- package/.mise/locks/azure-cli/2.91.0~a837e014/uv.lock +2794 -0
- package/.mise/locks/gemini/0.66.0~84aac8e6/aube-lock.yaml +123 -0
- package/.mise/locks/gemini/0.66.0~84aac8e6/package.json +12 -0
- package/.mise/locks/npm-devcontainers-cli/0.90.0/aube-lock.yaml +24 -0
- package/.mise/locks/npm-devcontainers-cli/0.90.0/package.json +7 -0
- package/.mise/locks/npm-modelcontextprotocol-inspector/2.13.0~4c109bea/aube-lock.yaml +1432 -0
- package/.mise/locks/npm-modelcontextprotocol-inspector/2.13.0~4c109bea/package.json +7 -0
- package/.mise/locks/npm-vercel/65.8.0/aube-lock.yaml +3595 -0
- package/.mise/locks/npm-vercel/65.8.0/package.json +7 -0
- package/.mise/locks/npm-wrangler/4.156.0/aube-lock.yaml +895 -0
- package/.mise/locks/npm-wrangler/4.156.0/package.json +7 -0
- package/.mise/locks/npm-yarnpkg-cli-dist/4.18.1/aube-lock.yaml +24 -0
- package/.mise/locks/npm-yarnpkg-cli-dist/4.18.1/package.json +7 -0
- package/LICENSE +21 -0
- package/README.md +357 -2
- package/agents/antigravity-proxy.ts +3 -0
- package/agents/audit.md +89 -0
- package/agents/claude-proxy +5 -0
- package/agents/claude-proxy.ts +3 -0
- package/agents/codex-proxy.ts +3 -0
- package/agents/grok-proxy.ts +3 -0
- package/agents/managed-proxy.ts +55 -0
- package/agents/opencode-proxy.ts +3 -0
- package/agents/registry.json +209 -0
- package/agents/registry.schema.json +149 -0
- package/agents/setup.md +158 -0
- package/agents/t3.json +40 -0
- package/ansible/macos/manager.yml +30 -0
- package/ansible/macos/policy.json +9 -0
- package/ansible/monitoring/README.md +215 -0
- package/ansible/monitoring/agent-darwin.yml +198 -0
- package/ansible/monitoring/agent.yml +172 -0
- package/ansible/monitoring/beszel-agent.service +42 -0
- package/ansible/monitoring/compose.yml +74 -0
- package/ansible/monitoring/hub-darwin.yml +102 -0
- package/ansible/monitoring/hub-route-darwin.yml +51 -0
- package/ansible/monitoring/lock.json +16 -0
- package/ansible/net/remote-probe.sh +13 -0
- package/ansible/pyproject.toml +12 -0
- package/ansible/ubuntu/authorize-sudo.sh +51 -0
- package/ansible/ubuntu/baseline.yml +89 -0
- package/ansible/ubuntu/disk-gc.py +336 -0
- package/ansible/ubuntu/disk-guard.py +104 -0
- package/ansible/ubuntu/policy.json +52 -0
- package/ansible/ubuntu/recovery.yml +15 -0
- package/ansible/ubuntu/t3/policy.json +7 -0
- package/ansible/ubuntu/t3-desktop.yml +220 -0
- package/ansible/ubuntu/t3-health.sh +33 -0
- package/ansible/ubuntu/t3-policy.yml +76 -0
- package/ansible/ubuntu/t3-route.yml +28 -0
- package/ansible/ubuntu/tailscale.yml +78 -0
- package/ansible/ubuntu/tasks/credentials.yml +47 -0
- package/ansible/ubuntu/tasks/docker.yml +31 -0
- package/ansible/ubuntu/tasks/packages.yml +56 -0
- package/ansible/ubuntu/tasks/power.yml +51 -0
- package/ansible/ubuntu/tasks/recovery.yml +39 -0
- package/ansible/ubuntu/tasks/resources.yml +312 -0
- package/ansible/ubuntu/tasks/services.yml +31 -0
- package/ansible/ubuntu/tasks/ssh.yml +71 -0
- package/ansible/ubuntu/tasks/user.yml +120 -0
- package/ansible/uv.lock +190 -0
- package/bin/devfleet.mjs +36 -0
- package/bootstrap/bootstrap.ps1 +50 -0
- package/bootstrap/bootstrap.sh +80 -0
- package/bootstrap/devfleet +7 -0
- package/bootstrap/docker-desktop.sh +33 -0
- package/bootstrap/doctor.ts +234 -0
- package/bootstrap/fleet-manager-run.sh +103 -0
- package/bootstrap/fleet-remote-bootstrap.sh +258 -0
- package/bootstrap/global-config.ts +171 -0
- package/bootstrap/install-launcher.sh +10 -0
- package/bootstrap/native-aws.ts +86 -0
- package/bootstrap/native-t3.ts +154 -0
- package/bootstrap/npm.ts +358 -0
- package/bootstrap/release-version.ts +157 -0
- package/bootstrap/setup-status.ts +51 -0
- package/bootstrap/setup.ts +88 -0
- package/bootstrap/shell-path.ts +105 -0
- package/bootstrap/verify-t3-archive.py +49 -0
- package/bootstrap/worker-auth.ts +65 -0
- package/bootstrap/worker-github.ts +47 -0
- package/bootstrap/worker-tools.ts +24 -0
- package/cliproxy/AGENTS.md +11 -0
- package/cliproxy/README.md +269 -0
- package/cliproxy/clients/bootstrap.py +143 -0
- package/cliproxy/clients/launcher.py +57 -0
- package/cliproxy/compose.yaml +90 -0
- package/cliproxy/config.template.yaml +70 -0
- package/cliproxy/docs/cloud-adoption.md +16 -0
- package/cliproxy/docs/deployment.png +0 -0
- package/cliproxy/docs/deployment.svg +109 -0
- package/cliproxy/docs/health-workflow.example.yml +185 -0
- package/cliproxy/docs/migration.md +131 -0
- package/cliproxy/docs/model-health-report.schema.json +364 -0
- package/cliproxy/docs/model-health.md +393 -0
- package/cliproxy/image.lock.json +5 -0
- package/cliproxy/launchd/dev.devfleet.cliproxy-backup-check.plist +38 -0
- package/cliproxy/launchd/dev.devfleet.cliproxy-backup.plist +48 -0
- package/cliproxy/launchd/dev.devfleet.cliproxy-fleet.plist +32 -0
- package/cliproxy/launchd/dev.devfleet.cliproxy-gc.plist +38 -0
- package/cliproxy/launchd/dev.devfleet.cliproxy-monitor.plist +29 -0
- package/cliproxy/launchd/dev.devfleet.cliproxy-vault-renew.plist +31 -0
- package/cliproxy/models.json +1618 -0
- package/cliproxy/requirements.lock +78 -0
- package/cliproxy/scripts/accounts.py +38 -0
- package/cliproxy/scripts/audit.py +123 -0
- package/cliproxy/scripts/backup +234 -0
- package/cliproxy/scripts/check.py +34 -0
- package/cliproxy/scripts/checkpoint.py +226 -0
- package/cliproxy/scripts/cli.py +64 -0
- package/cliproxy/scripts/cliproxy_host.py +257 -0
- package/cliproxy/scripts/cloud_state.py +150 -0
- package/cliproxy/scripts/container-health +6 -0
- package/cliproxy/scripts/docker +24 -0
- package/cliproxy/scripts/external-health.py +79 -0
- package/cliproxy/scripts/fleet_config.py +43 -0
- package/cliproxy/scripts/fleet_sync.py +274 -0
- package/cliproxy/scripts/initialize +84 -0
- package/cliproxy/scripts/install-dependencies +48 -0
- package/cliproxy/scripts/install.py +406 -0
- package/cliproxy/scripts/model_health.py +16 -0
- package/cliproxy/scripts/modelhealth/__init__.py +5 -0
- package/cliproxy/scripts/modelhealth/checks.py +429 -0
- package/cliproxy/scripts/modelhealth/cli.py +117 -0
- package/cliproxy/scripts/modelhealth/config.py +186 -0
- package/cliproxy/scripts/modelhealth/emulator.py +536 -0
- package/cliproxy/scripts/modelhealth/expect.py +88 -0
- package/cliproxy/scripts/modelhealth/findings.py +183 -0
- package/cliproxy/scripts/modelhealth/protocol.py +330 -0
- package/cliproxy/scripts/modelhealth/redact.py +28 -0
- package/cliproxy/scripts/modelhealth/report.py +150 -0
- package/cliproxy/scripts/modelhealth/runner.py +390 -0
- package/cliproxy/scripts/modelhealth/scenario.py +131 -0
- package/cliproxy/scripts/modelhealth/schema.py +63 -0
- package/cliproxy/scripts/modelhealth/simulate.py +111 -0
- package/cliproxy/scripts/modelhealth/transport.py +213 -0
- package/cliproxy/scripts/monitor +68 -0
- package/cliproxy/scripts/ops +527 -0
- package/cliproxy/scripts/public-endpoint +127 -0
- package/cliproxy/scripts/recover_node.py +177 -0
- package/cliproxy/scripts/restore-verify +60 -0
- package/cliproxy/scripts/retention.py +144 -0
- package/cliproxy/scripts/service-start +7 -0
- package/cliproxy/scripts/validate-config +56 -0
- package/cliproxy/scripts/vault-access.py +57 -0
- package/cliproxy/scripts/vault-backup-login +55 -0
- package/cliproxy/scripts/vault-recovery +56 -0
- package/cliproxy/scripts/vault-renew +30 -0
- package/cliproxy/systemd/cliproxy-backup-check.service +10 -0
- package/cliproxy/systemd/cliproxy-backup-check.timer +8 -0
- package/cliproxy/systemd/cliproxy-backup.service +13 -0
- package/cliproxy/systemd/cliproxy-backup.timer +8 -0
- package/cliproxy/systemd/cliproxy-fleet.service +17 -0
- package/cliproxy/systemd/cliproxy-gc.service +13 -0
- package/cliproxy/systemd/cliproxy-gc.timer +8 -0
- package/cliproxy/systemd/cliproxy-monitor.service +8 -0
- package/cliproxy/systemd/cliproxy-monitor.timer +7 -0
- package/cliproxy/systemd/cliproxy-vault-renew.service +8 -0
- package/cliproxy/systemd/cliproxy-vault-renew.timer +7 -0
- package/cliproxy/vendor/LICENSE +22 -0
- package/cliproxy/vendor/config.upstream.yaml +1349 -0
- package/docs/consumer-setup.md +408 -0
- package/docs/declared.md +89 -0
- package/docs/machine-setup.md +399 -0
- package/docs/operations.md +276 -0
- package/docs/releasing.md +103 -0
- package/docs/state.md +254 -0
- package/docs/topology.md +67 -0
- package/docs/ubuntu-sync.md +351 -0
- package/docs/worker-contract.md +67 -0
- package/examples/fleet.json +100 -0
- package/examples/roster.json +13 -0
- package/llms.txt +35 -0
- package/mise.lock +1521 -0
- package/mise.toml +110 -0
- package/package.json +74 -4
- package/schema/fleet.schema.json +420 -0
- package/schema/roster.schema.json +77 -0
- package/src/agents/account-relay.ts +111 -0
- package/src/agents/accounts.ts +85 -0
- package/src/agents/audit.ts +77 -0
- package/src/agents/cli.ts +13 -0
- package/src/agents/command.ts +204 -0
- package/src/agents/converge.ts +123 -0
- package/src/agents/doctor.ts +107 -0
- package/src/agents/errors.ts +2 -0
- package/src/agents/files.ts +73 -0
- package/src/agents/fleet-verify.ts +165 -0
- package/src/agents/launch.ts +290 -0
- package/src/agents/native-verify.ts +371 -0
- package/src/agents/provider-errors.ts +57 -0
- package/src/agents/registry.ts +61 -0
- package/src/agents/render.ts +110 -0
- package/src/agents/round-trip.ts +192 -0
- package/src/agents/secrets.ts +13 -0
- package/src/agents/toolchain.ts +34 -0
- package/src/agents/verify-cache.ts +103 -0
- package/src/agents/verify.ts +127 -0
- package/src/auth-checks.ts +163 -0
- package/src/cli/agent-guide.ts +129 -0
- package/src/cli/app.ts +122 -0
- package/src/cli/cli.ts +28 -0
- package/src/cli/command-index.ts +57 -0
- package/src/cli/contracts.ts +25 -0
- package/src/cli/fleet-reference.ts +17 -0
- package/src/cli/fleet-state.ts +499 -0
- package/src/cli/fleet-sync-checkout.ts +130 -0
- package/src/cli/fleet-sync-enrollment.ts +140 -0
- package/src/cli/fleet-sync-forward.ts +134 -0
- package/src/cli/fleet-sync-manager.ts +249 -0
- package/src/cli/fleet-sync-monitoring.ts +185 -0
- package/src/cli/fleet-sync-output.ts +317 -0
- package/src/cli/fleet-sync-privilege.ts +27 -0
- package/src/cli/fleet-sync-progress.ts +109 -0
- package/src/cli/fleet-sync-remote.ts +242 -0
- package/src/cli/fleet-sync-report.ts +26 -0
- package/src/cli/fleet-sync-schedule.ts +138 -0
- package/src/cli/fleet-sync-state.ts +86 -0
- package/src/cli/fleet-sync-vault.ts +166 -0
- package/src/cli/fleet-sync.ts +375 -0
- package/src/cli/fleet.ts +165 -0
- package/src/cli/managed-health.ts +219 -0
- package/src/cli/node-deployment.ts +34 -0
- package/src/cli/node-sync.ts +121 -0
- package/src/cli/node-t3.ts +31 -0
- package/src/cli/options.ts +141 -0
- package/src/cli/probe-source.ts +7 -0
- package/src/cli/program.ts +185 -0
- package/src/cli/project.ts +51 -0
- package/src/cli/register-fleet.ts +296 -0
- package/src/cli/registry.ts +185 -0
- package/src/cli/repair-apply.ts +67 -0
- package/src/cli/repair-guard.ts +11 -0
- package/src/cli/repair-inspect.ts +150 -0
- package/src/cli/repair-script.ts +76 -0
- package/src/cli/repair.ts +209 -0
- package/src/cli/roster.ts +105 -0
- package/src/cli/search.ts +35 -0
- package/src/cli/settings.ts +67 -0
- package/src/cli/source-operations.ts +102 -0
- package/src/cli/t3/command.ts +90 -0
- package/src/cli/t3/register.ts +55 -0
- package/src/cli/tailnet.ts +127 -0
- package/src/cli/ui-actions.ts +133 -0
- package/src/cli/ui-controller.ts +113 -0
- package/src/cli/ui-data.ts +106 -0
- package/src/cli/ui-execute.ts +163 -0
- package/src/cli/ui-repairs.ts +34 -0
- package/src/cli/ui-reports.ts +211 -0
- package/src/cli/ui-targets.ts +100 -0
- package/src/cli/ui-terminal.ts +109 -0
- package/src/cli/ui-types.ts +49 -0
- package/src/cli/ui-wizard.ts +101 -0
- package/src/cli/ui.ts +9 -0
- package/src/cli/worker-health-output.ts +37 -0
- package/src/config.ts +186 -0
- package/src/configure.ts +255 -0
- package/src/definition.ts +290 -0
- package/src/diagnostics.ts +92 -0
- package/src/doctor-check.ts +10 -0
- package/src/errors.ts +1 -0
- package/src/fingerprint.ts +120 -0
- package/src/fleet-config.ts +174 -0
- package/src/input-hashes.ts +73 -0
- package/src/machine/local-source.ts +52 -0
- package/src/machine/lock-error.ts +2 -0
- package/src/machine/platform.ts +44 -0
- package/src/machine/source.ts +68 -0
- package/src/machine/state.ts +173 -0
- package/src/machine-health.ts +95 -0
- package/src/managed-source.ts +47 -0
- package/src/manager-failure.ts +48 -0
- package/src/manager-sync.ts +405 -0
- package/src/manager.ts +62 -0
- package/src/monitoring/agent-evidence.ts +146 -0
- package/src/monitoring/apply.ts +183 -0
- package/src/monitoring/beszel.ts +198 -0
- package/src/monitoring/enroll.ts +111 -0
- package/src/monitoring/hub-access.ts +114 -0
- package/src/monitoring/hub-backup.ts +121 -0
- package/src/monitoring/hub-viewer.ts +142 -0
- package/src/monitoring/hub.ts +93 -0
- package/src/monitoring/manager-agent.ts +73 -0
- package/src/monitoring/manager-hub.ts +248 -0
- package/src/monitoring/remote.ts +65 -0
- package/src/network-definition.ts +83 -0
- package/src/node-converge-linux.ts +374 -0
- package/src/node-converge-shared.ts +83 -0
- package/src/node-converge.ts +40 -0
- package/src/onboard.ts +35 -0
- package/src/package-info.ts +45 -0
- package/src/platform/ansible-receipt.ts +128 -0
- package/src/platform/ansible.ts +66 -0
- package/src/platform/darwin.ts +203 -0
- package/src/platform/detect.ts +11 -0
- package/src/platform/fallback.ts +110 -0
- package/src/platform/index.ts +38 -0
- package/src/platform/launchd.ts +98 -0
- package/src/platform/linux.ts +139 -0
- package/src/platform/ps.ts +45 -0
- package/src/platform/resource-verify.ts +132 -0
- package/src/platform/systemd-user.ts +95 -0
- package/src/platform/t3-policy.ts +137 -0
- package/src/platform/t3-route.ts +68 -0
- package/src/platform/t3-service.ts +75 -0
- package/src/platform/types.ts +123 -0
- package/src/platform/ubuntu-audit.ts +66 -0
- package/src/platform/ubuntu-verify.ts +105 -0
- package/src/platform/windows.ts +148 -0
- package/src/power-recovery.ts +55 -0
- package/src/probe.ts +51 -0
- package/src/protocol.ts +119 -0
- package/src/proxy-converge.ts +85 -0
- package/src/remote-bootstrap.ts +210 -0
- package/src/remote-entry.ts +89 -0
- package/src/remote-lock.ts +12 -0
- package/src/repair-catalog.ts +206 -0
- package/src/repair-plan.ts +78 -0
- package/src/repair-runner.ts +84 -0
- package/src/report.ts +71 -0
- package/src/runner.ts +104 -0
- package/src/secrets.ts +169 -0
- package/src/service-auth.ts +115 -0
- package/src/ssh.ts +135 -0
- package/src/state/bucket.ts +208 -0
- package/src/state/check.ts +74 -0
- package/src/state/connection.ts +92 -0
- package/src/state/enrollment.ts +45 -0
- package/src/state/legacy.ts +89 -0
- package/src/state/litestream.ts +143 -0
- package/src/state/operator.ts +20 -0
- package/src/state/paths.ts +40 -0
- package/src/state/roster.ts +62 -0
- package/src/state/store.ts +169 -0
- package/src/state/sync.ts +352 -0
- package/src/sync.ts +104 -0
- package/src/t3/accounts.ts +81 -0
- package/src/t3/desired.ts +165 -0
- package/src/t3/files.ts +81 -0
- package/src/t3/names-check.ts +53 -0
- package/src/t3/names.ts +155 -0
- package/src/t3/plan.ts +82 -0
- package/src/t3/providers.ts +74 -0
- package/src/t3/reconcile.ts +123 -0
- package/src/t3-endpoint.ts +104 -0
- package/src/t3-linked-check.ts +123 -0
- package/src/tailnet-health.ts +231 -0
- package/src/tailnet-matching.ts +37 -0
- package/src/tailscale.ts +141 -0
- package/src/toolchain-checks.ts +108 -0
- package/src/topology.ts +24 -0
- package/src/transport.ts +122 -0
- package/src/types.ts +99 -0
- package/src/vault-config.ts +38 -0
- package/src/worker-access-checks.ts +168 -0
- package/src/worker-capacity.ts +34 -0
- package/src/worker-host-checks.ts +181 -0
- package/src/worker-policy.ts +64 -0
- package/src/worker-readiness.ts +64 -0
- package/src/workstation-checks.ts +29 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
---
|
|
2
|
+
# The worker's only T3 process: the pinned desktop app, which embeds the server
|
|
3
|
+
# on 127.0.0.1:3773. GDM logs the designated user in automatically and the user
|
|
4
|
+
# unit starts the app with the graphical session, so the UI is on screen and the
|
|
5
|
+
# server is up after every boot. Starting or migrating is left to fleet-sync.
|
|
6
|
+
#
|
|
7
|
+
# The upstream .deb declares libxss1, which Ubuntu 26.04 no longer ships and the
|
|
8
|
+
# binary does not link. Instead of patching the package or leaving apt with an
|
|
9
|
+
# unmet dependency, the verified package payload is unpacked to its own path and
|
|
10
|
+
# its real runtime libraries and bundled AppArmor profile are installed.
|
|
11
|
+
- name: Install the pinned T3 Code desktop app and start it with the session
|
|
12
|
+
hosts: localhost
|
|
13
|
+
connection: local
|
|
14
|
+
become: true
|
|
15
|
+
gather_facts: false
|
|
16
|
+
vars:
|
|
17
|
+
t3_desktop_dir: /opt/T3 Code (Nightly)
|
|
18
|
+
# The package's Depends without libxss1 (see above).
|
|
19
|
+
t3_desktop_libraries:
|
|
20
|
+
- libasound2t64
|
|
21
|
+
- libatspi2.0-0t64
|
|
22
|
+
- libgbm1
|
|
23
|
+
- libgtk-3-0t64
|
|
24
|
+
- libnotify4
|
|
25
|
+
- libnss3
|
|
26
|
+
- libsecret-1-0
|
|
27
|
+
- libuuid1
|
|
28
|
+
- libxtst6
|
|
29
|
+
- xdg-utils
|
|
30
|
+
tasks:
|
|
31
|
+
- name: Create the package cache
|
|
32
|
+
ansible.builtin.file:
|
|
33
|
+
path: /var/cache/personal-fleet
|
|
34
|
+
state: directory
|
|
35
|
+
owner: root
|
|
36
|
+
group: root
|
|
37
|
+
mode: '0755'
|
|
38
|
+
- name: Download the pinned desktop package
|
|
39
|
+
ansible.builtin.get_url:
|
|
40
|
+
url: '{{ t3_desktop_url }}'
|
|
41
|
+
dest: '/var/cache/personal-fleet/{{ t3_desktop_name }}'
|
|
42
|
+
checksum: 'sha256:{{ t3_desktop_sha256 }}'
|
|
43
|
+
mode: '0644'
|
|
44
|
+
timeout: 300
|
|
45
|
+
- name: Install the desktop runtime libraries
|
|
46
|
+
ansible.builtin.apt:
|
|
47
|
+
name: '{{ t3_desktop_libraries }}'
|
|
48
|
+
state: present
|
|
49
|
+
lock_timeout: 120
|
|
50
|
+
- name: Read the unpacked app version
|
|
51
|
+
ansible.builtin.command:
|
|
52
|
+
argv: [cat, '{{ t3_desktop_dir }}/.personal-fleet-version']
|
|
53
|
+
register: t3_desktop_installed
|
|
54
|
+
changed_when: false
|
|
55
|
+
failed_when: false
|
|
56
|
+
- name: Unpack the pinned app when its version differs
|
|
57
|
+
when: t3_desktop_installed.stdout | default('') != t3_desktop_name
|
|
58
|
+
block:
|
|
59
|
+
- name: Clear the staging directory
|
|
60
|
+
ansible.builtin.file:
|
|
61
|
+
path: /opt/.t3code-staging
|
|
62
|
+
state: absent
|
|
63
|
+
- name: Unpack the verified package payload
|
|
64
|
+
ansible.builtin.command:
|
|
65
|
+
argv:
|
|
66
|
+
- dpkg-deb
|
|
67
|
+
- -x
|
|
68
|
+
- '/var/cache/personal-fleet/{{ t3_desktop_name }}'
|
|
69
|
+
- /opt/.t3code-staging
|
|
70
|
+
changed_when: true
|
|
71
|
+
- name: Record the unpacked package
|
|
72
|
+
ansible.builtin.copy:
|
|
73
|
+
dest: '/opt/.t3code-staging{{ t3_desktop_dir }}/.personal-fleet-version'
|
|
74
|
+
content: '{{ t3_desktop_name }}'
|
|
75
|
+
mode: '0644'
|
|
76
|
+
- name: Remove the copy kept from the previous update
|
|
77
|
+
ansible.builtin.file:
|
|
78
|
+
path: '{{ t3_desktop_dir }}.previous'
|
|
79
|
+
state: absent
|
|
80
|
+
- name: Inspect the current app directory
|
|
81
|
+
ansible.builtin.stat:
|
|
82
|
+
path: '{{ t3_desktop_dir }}'
|
|
83
|
+
register: t3_desktop_current
|
|
84
|
+
- name: Keep the current app until the next update (a running app keeps its files)
|
|
85
|
+
ansible.builtin.command:
|
|
86
|
+
argv:
|
|
87
|
+
[mv, -T, '{{ t3_desktop_dir }}', '{{ t3_desktop_dir }}.previous']
|
|
88
|
+
when: t3_desktop_current.stat.exists
|
|
89
|
+
changed_when: true
|
|
90
|
+
- name: Move the pinned app into place
|
|
91
|
+
ansible.builtin.command:
|
|
92
|
+
argv:
|
|
93
|
+
- mv
|
|
94
|
+
- -T
|
|
95
|
+
- '/opt/.t3code-staging{{ t3_desktop_dir }}'
|
|
96
|
+
- '{{ t3_desktop_dir }}'
|
|
97
|
+
changed_when: true
|
|
98
|
+
- name: Add the launcher entry and icon
|
|
99
|
+
ansible.builtin.copy:
|
|
100
|
+
src: '/opt/.t3code-staging/usr/share/{{ item }}'
|
|
101
|
+
dest: '/usr/share/{{ item }}'
|
|
102
|
+
remote_src: true
|
|
103
|
+
mode: '0644'
|
|
104
|
+
loop:
|
|
105
|
+
- applications/t3code.desktop
|
|
106
|
+
- icons/hicolor/512x512/apps/t3code.png
|
|
107
|
+
- name: Remove the staging directory
|
|
108
|
+
ansible.builtin.file:
|
|
109
|
+
path: /opt/.t3code-staging
|
|
110
|
+
state: absent
|
|
111
|
+
- name: Install the AppArmor profile the package ships
|
|
112
|
+
ansible.builtin.copy:
|
|
113
|
+
src: '{{ t3_desktop_dir }}/resources/apparmor-profile'
|
|
114
|
+
dest: /etc/apparmor.d/t3code
|
|
115
|
+
remote_src: true
|
|
116
|
+
mode: '0644'
|
|
117
|
+
register: t3_desktop_apparmor
|
|
118
|
+
- name: Load the AppArmor profile so the app sandbox can start
|
|
119
|
+
ansible.builtin.command:
|
|
120
|
+
argv:
|
|
121
|
+
[
|
|
122
|
+
apparmor_parser,
|
|
123
|
+
--replace,
|
|
124
|
+
--write-cache,
|
|
125
|
+
--skip-read-cache,
|
|
126
|
+
/etc/apparmor.d/t3code,
|
|
127
|
+
]
|
|
128
|
+
when: t3_desktop_apparmor.changed
|
|
129
|
+
changed_when: true
|
|
130
|
+
- name: Inspect the GDM configuration
|
|
131
|
+
ansible.builtin.stat:
|
|
132
|
+
path: /etc/gdm3/custom.conf
|
|
133
|
+
register: gdm_config
|
|
134
|
+
- name: Log the designated user in automatically
|
|
135
|
+
ansible.builtin.lineinfile:
|
|
136
|
+
path: /etc/gdm3/custom.conf
|
|
137
|
+
regexp: '^#?\s*{{ item.key }}\s*='
|
|
138
|
+
line: '{{ item.key }} = {{ item.value }}'
|
|
139
|
+
insertafter: '^\[daemon\]'
|
|
140
|
+
loop:
|
|
141
|
+
- { key: AutomaticLoginEnable, value: 'true' }
|
|
142
|
+
- { key: AutomaticLogin, value: '{{ development_user }}' }
|
|
143
|
+
when: gdm_config.stat.exists
|
|
144
|
+
- name: Create the user unit directory
|
|
145
|
+
ansible.builtin.file:
|
|
146
|
+
path: '{{ development_home }}/.config/systemd/user'
|
|
147
|
+
state: directory
|
|
148
|
+
owner: '{{ development_user }}'
|
|
149
|
+
mode: '0700'
|
|
150
|
+
- name: Declare the desktop app as a session service
|
|
151
|
+
ansible.builtin.copy:
|
|
152
|
+
dest: '{{ development_home }}/.config/systemd/user/t3code-desktop.service'
|
|
153
|
+
owner: '{{ development_user }}'
|
|
154
|
+
mode: '0600'
|
|
155
|
+
content: |
|
|
156
|
+
# Managed by personal fleet-sync: ansible/ubuntu/t3-desktop.yml
|
|
157
|
+
[Unit]
|
|
158
|
+
Description=T3 Code desktop (UI and server)
|
|
159
|
+
PartOf=graphical-session.target
|
|
160
|
+
After=graphical-session.target
|
|
161
|
+
StartLimitIntervalSec=300
|
|
162
|
+
StartLimitBurst=5
|
|
163
|
+
[Service]
|
|
164
|
+
Type=simple
|
|
165
|
+
WorkingDirectory=%h
|
|
166
|
+
Environment=T3CODE_HOME=%h/.t3
|
|
167
|
+
# /tmp is RAM with a per-user quota that agent and build caches
|
|
168
|
+
# exhaust; agents use disk-backed /var/tmp (aged by tasks/resources.yml).
|
|
169
|
+
Environment=TMPDIR=/var/tmp
|
|
170
|
+
# Native Wayland hangs before the first window on Asahi (16K pages);
|
|
171
|
+
# XWayland works on every GNOME worker, so use it everywhere.
|
|
172
|
+
ExecStart="{{ t3_desktop_dir }}/t3code" --ozone-platform=x11
|
|
173
|
+
KillMode=mixed
|
|
174
|
+
Restart=always
|
|
175
|
+
RestartSec=5
|
|
176
|
+
CPUWeight=1000
|
|
177
|
+
IOWeight=1000
|
|
178
|
+
MemoryLow=1536M
|
|
179
|
+
OOMScoreAdjust=100
|
|
180
|
+
ManagedOOMPreference=avoid
|
|
181
|
+
[Install]
|
|
182
|
+
WantedBy=graphical-session.target
|
|
183
|
+
# Repoint recovery now: a timer still running an older revision's script
|
|
184
|
+
# would restart the headless server right after its approved migration.
|
|
185
|
+
- ansible.builtin.import_tasks: tasks/recovery.yml
|
|
186
|
+
- name: Enable the desktop app for every graphical login
|
|
187
|
+
become: true
|
|
188
|
+
become_user: '{{ development_user }}'
|
|
189
|
+
environment:
|
|
190
|
+
XDG_RUNTIME_DIR: '/run/user/{{ development_uid }}'
|
|
191
|
+
ansible.builtin.systemd_service:
|
|
192
|
+
scope: user
|
|
193
|
+
name: t3code-desktop.service
|
|
194
|
+
daemon_reload: true
|
|
195
|
+
enabled: true
|
|
196
|
+
# One T3 process per worker: the desktop app. The former headless server
|
|
197
|
+
# (`t3 service install`) is retired; absent on machines that never had it.
|
|
198
|
+
- name: Retire the former headless T3 server
|
|
199
|
+
become: true
|
|
200
|
+
become_user: '{{ development_user }}'
|
|
201
|
+
environment:
|
|
202
|
+
XDG_RUNTIME_DIR: '/run/user/{{ development_uid }}'
|
|
203
|
+
ansible.builtin.systemd_service:
|
|
204
|
+
scope: user
|
|
205
|
+
name: t3code.service
|
|
206
|
+
state: stopped
|
|
207
|
+
enabled: false
|
|
208
|
+
failed_when: false
|
|
209
|
+
# Starting needs the auto-login graphical session, which a machine has only
|
|
210
|
+
# after its first reboot; the running state is measured after this play.
|
|
211
|
+
- name: Start the desktop app without restarting a running one
|
|
212
|
+
become: true
|
|
213
|
+
become_user: '{{ development_user }}'
|
|
214
|
+
environment:
|
|
215
|
+
XDG_RUNTIME_DIR: '/run/user/{{ development_uid }}'
|
|
216
|
+
ansible.builtin.systemd_service:
|
|
217
|
+
scope: user
|
|
218
|
+
name: t3code-desktop.service
|
|
219
|
+
state: started
|
|
220
|
+
failed_when: false
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Keep the worker T3 desktop app (UI and server) up and responsive. Run every minute by
|
|
3
|
+
# personal-worker-recovery.timer (managed by fleet-sync, tasks/recovery.yml).
|
|
4
|
+
# Stopped or failed: start it. Running but its local API has not answered for
|
|
5
|
+
# three checks in a row: restart it, since a hung server serves no turns.
|
|
6
|
+
set -u
|
|
7
|
+
url=http://127.0.0.1:3773/.well-known/t3/environment
|
|
8
|
+
state="${XDG_RUNTIME_DIR:?}/personal-t3-health-failures"
|
|
9
|
+
limit=3
|
|
10
|
+
|
|
11
|
+
# The former headless server still runs until its approved migration; never
|
|
12
|
+
# start a second T3 next to it.
|
|
13
|
+
if systemctl --user is-active --quiet t3code.service; then
|
|
14
|
+
echo "Headless T3 still runs; desktop migration pending."
|
|
15
|
+
exit 0
|
|
16
|
+
fi
|
|
17
|
+
if ! systemctl --user is-active --quiet t3code-desktop.service; then
|
|
18
|
+
rm -f "$state"
|
|
19
|
+
echo "T3 is not running; starting it."
|
|
20
|
+
exec systemctl --user start t3code-desktop.service
|
|
21
|
+
fi
|
|
22
|
+
if curl --fail --silent --max-time 10 --output /dev/null "$url"; then
|
|
23
|
+
rm -f "$state"
|
|
24
|
+
exit 0
|
|
25
|
+
fi
|
|
26
|
+
failures=$(($(cat "$state" 2>/dev/null || echo 0) + 1))
|
|
27
|
+
echo "$failures" > "$state"
|
|
28
|
+
echo "T3 local API did not answer ($failures/$limit)."
|
|
29
|
+
if [ "$failures" -ge "$limit" ]; then
|
|
30
|
+
rm -f "$state"
|
|
31
|
+
echo "T3 is unresponsive; restarting it."
|
|
32
|
+
exec systemctl --user restart t3code-desktop.service
|
|
33
|
+
fi
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
- name: Stage the native T3 policy and make the running app load it
|
|
3
|
+
hosts: localhost
|
|
4
|
+
connection: local
|
|
5
|
+
become: true
|
|
6
|
+
gather_facts: false
|
|
7
|
+
tasks:
|
|
8
|
+
- name: Inspect existing administrator policy
|
|
9
|
+
ansible.builtin.stat:
|
|
10
|
+
path: /etc/t3code/policy.json
|
|
11
|
+
register: policy_file
|
|
12
|
+
- name: Inspect Fleet ownership marker
|
|
13
|
+
ansible.builtin.stat:
|
|
14
|
+
path: /etc/t3code/.personal-fleet-policy
|
|
15
|
+
register: policy_owner
|
|
16
|
+
- name: Refuse to overwrite an unrelated administrator policy
|
|
17
|
+
ansible.builtin.assert:
|
|
18
|
+
that: not policy_file.stat.exists or policy_owner.stat.exists
|
|
19
|
+
fail_msg: T3_POLICY_OWNER_CONFLICT; review and merge the existing administrator policy in Git before adoption.
|
|
20
|
+
- name: Create administrator-owned policy directory
|
|
21
|
+
ansible.builtin.file:
|
|
22
|
+
path: /etc/t3code
|
|
23
|
+
state: directory
|
|
24
|
+
owner: root
|
|
25
|
+
group: root
|
|
26
|
+
mode: '0755'
|
|
27
|
+
- name: Record policy ownership before resumable installation
|
|
28
|
+
ansible.builtin.copy:
|
|
29
|
+
dest: /etc/t3code/.personal-fleet-policy
|
|
30
|
+
content: "ansible/ubuntu/t3/policy.json\n"
|
|
31
|
+
owner: root
|
|
32
|
+
group: root
|
|
33
|
+
mode: '0644'
|
|
34
|
+
- name: Stage validated policy with backup
|
|
35
|
+
ansible.builtin.copy:
|
|
36
|
+
content: "{{ t3_policy_document | default(lookup('ansible.builtin.file', 't3/policy.json') | from_json) | to_nice_json }}"
|
|
37
|
+
validate: '{{ t3_executable | quote }} policy check %s'
|
|
38
|
+
dest: /etc/t3code/policy.json
|
|
39
|
+
owner: root
|
|
40
|
+
group: root
|
|
41
|
+
mode: '0644'
|
|
42
|
+
backup: true
|
|
43
|
+
# T3 reads its policy once, at startup. A running app that has not loaded
|
|
44
|
+
# the staged policy is restarted (this ends its running turns) so every
|
|
45
|
+
# node offers the same providers after every sync.
|
|
46
|
+
- name: Check whether the desktop app is running
|
|
47
|
+
become: true
|
|
48
|
+
become_user: '{{ development_user }}'
|
|
49
|
+
environment:
|
|
50
|
+
XDG_RUNTIME_DIR: '/run/user/{{ development_uid }}'
|
|
51
|
+
ansible.builtin.command:
|
|
52
|
+
argv: [systemctl, --user, is-active, --quiet, t3code-desktop.service]
|
|
53
|
+
register: t3_desktop_active
|
|
54
|
+
changed_when: false
|
|
55
|
+
failed_when: false
|
|
56
|
+
- name: Ask the running T3 which policy it loaded
|
|
57
|
+
become: true
|
|
58
|
+
become_user: '{{ development_user }}'
|
|
59
|
+
ansible.builtin.command:
|
|
60
|
+
argv: ['{{ t3_executable }}', policy, show]
|
|
61
|
+
register: t3_policy_loaded
|
|
62
|
+
changed_when: false
|
|
63
|
+
failed_when: false
|
|
64
|
+
when: t3_desktop_active.rc == 0
|
|
65
|
+
- name: Restart T3 so it loads the staged policy
|
|
66
|
+
become: true
|
|
67
|
+
become_user: '{{ development_user }}'
|
|
68
|
+
environment:
|
|
69
|
+
XDG_RUNTIME_DIR: '/run/user/{{ development_uid }}'
|
|
70
|
+
ansible.builtin.systemd_service:
|
|
71
|
+
scope: user
|
|
72
|
+
name: t3code-desktop.service
|
|
73
|
+
state: restarted
|
|
74
|
+
when:
|
|
75
|
+
- t3_desktop_active.rc == 0
|
|
76
|
+
- t3_policy_loaded.stdout is not search('loaded this policy\.\s*$')
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
# The worker's T3 is reached over the tailnet only: Tailscale Serve terminates
|
|
3
|
+
# HTTPS on port 443 and proxies to the loopback T3 server. Never Funnel. A
|
|
4
|
+
# port 443 that already has any owner is left alone (reported, never reset).
|
|
5
|
+
- name: Serve the worker T3 privately over the tailnet
|
|
6
|
+
hosts: localhost
|
|
7
|
+
connection: local
|
|
8
|
+
become: true
|
|
9
|
+
gather_facts: false
|
|
10
|
+
tasks:
|
|
11
|
+
- name: Require the declared loopback target
|
|
12
|
+
ansible.builtin.assert:
|
|
13
|
+
that: "t3_route_target is match('^http://127\\.0\\.0\\.1:[0-9]+$')"
|
|
14
|
+
|
|
15
|
+
- name: Read this node's Serve configuration
|
|
16
|
+
ansible.builtin.command:
|
|
17
|
+
argv: [tailscale, serve, status, --json]
|
|
18
|
+
register: t3_serve_status
|
|
19
|
+
changed_when: false
|
|
20
|
+
- name: Publish T3 on tailnet HTTPS port 443
|
|
21
|
+
ansible.builtin.command:
|
|
22
|
+
argv: [tailscale, serve, --bg, --https=443, '{{ t3_route_target }}']
|
|
23
|
+
vars:
|
|
24
|
+
serve: "{{ t3_serve_status.stdout | default('{}', true) | from_json }}"
|
|
25
|
+
when:
|
|
26
|
+
- "'443' not in (serve.TCP | default({}))"
|
|
27
|
+
- "(serve.Web | default({})) | select('search', ':443$') | list | length == 0"
|
|
28
|
+
changed_when: true
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
- name: Converge native Tailscale without replacing its device identity
|
|
3
|
+
hosts: localhost
|
|
4
|
+
connection: local
|
|
5
|
+
become: true
|
|
6
|
+
gather_facts: true
|
|
7
|
+
# The approved version and the signing key's digest: `tailscale` in policy.json.
|
|
8
|
+
vars_files:
|
|
9
|
+
- policy.json
|
|
10
|
+
tasks:
|
|
11
|
+
- name: Require supported Ubuntu
|
|
12
|
+
ansible.builtin.assert:
|
|
13
|
+
that:
|
|
14
|
+
- ansible_facts.distribution == 'Ubuntu'
|
|
15
|
+
- ansible_facts.distribution_version == release
|
|
16
|
+
- name: Inspect installed packages before possible network interruption
|
|
17
|
+
ansible.builtin.package_facts:
|
|
18
|
+
manager: apt
|
|
19
|
+
- name: Require maintenance for an installed version change
|
|
20
|
+
ansible.builtin.assert:
|
|
21
|
+
that: "'tailscale' not in ansible_facts.packages or ansible_facts.packages.tailscale[0].version == tailscale.version"
|
|
22
|
+
fail_msg: TAILSCALE_UPGRADE_PENDING; upgrading an active VPN can disconnect SSH. Review an explicit maintenance operation.
|
|
23
|
+
- name: Inspect existing package-source ownership before writing
|
|
24
|
+
ansible.builtin.find:
|
|
25
|
+
paths: /etc/apt/sources.list.d
|
|
26
|
+
patterns: ['*.list', '*.sources']
|
|
27
|
+
contains: '.*pkgs.tailscale.com.*'
|
|
28
|
+
read_whole_file: true
|
|
29
|
+
register: existing_sources
|
|
30
|
+
- name: Refuse duplicate or custom sources instead of breaking APT
|
|
31
|
+
ansible.builtin.assert:
|
|
32
|
+
that:
|
|
33
|
+
- existing_sources.matched <= 1
|
|
34
|
+
- existing_sources.matched == 0 or existing_sources.files[0].path == '/etc/apt/sources.list.d/tailscale.list'
|
|
35
|
+
fail_msg: TAILSCALE_SOURCE_OWNER_CONFLICT; review the existing signed source and its migration before creating another repository entry.
|
|
36
|
+
- name: Install pinned upstream signing key
|
|
37
|
+
ansible.builtin.get_url:
|
|
38
|
+
url: https://pkgs.tailscale.com/stable/ubuntu/resolute.noarmor.gpg
|
|
39
|
+
dest: /usr/share/keyrings/tailscale-archive-keyring.gpg
|
|
40
|
+
checksum: 'sha256:{{ tailscale.keySha256 }}'
|
|
41
|
+
owner: root
|
|
42
|
+
group: root
|
|
43
|
+
mode: '0644'
|
|
44
|
+
timeout: 30
|
|
45
|
+
- name: Declare the signed upstream package source
|
|
46
|
+
ansible.builtin.apt_repository:
|
|
47
|
+
repo: deb [signed-by=/usr/share/keyrings/tailscale-archive-keyring.gpg] https://pkgs.tailscale.com/stable/ubuntu resolute main
|
|
48
|
+
filename: tailscale
|
|
49
|
+
state: present
|
|
50
|
+
update_cache: false
|
|
51
|
+
register: tailscale_source
|
|
52
|
+
- name: Install the approved version only when absent
|
|
53
|
+
ansible.builtin.apt:
|
|
54
|
+
name: 'tailscale={{ tailscale.version }}'
|
|
55
|
+
state: present
|
|
56
|
+
update_cache: true
|
|
57
|
+
cache_valid_time: 0
|
|
58
|
+
lock_timeout: '{{ aptLockTimeoutSeconds }}'
|
|
59
|
+
allow_downgrade: false
|
|
60
|
+
allow_unauthenticated: false
|
|
61
|
+
when: "'tailscale' not in ansible_facts.packages"
|
|
62
|
+
- name: Enable and start the native daemon, preserving existing identity
|
|
63
|
+
ansible.builtin.systemd_service:
|
|
64
|
+
name: tailscaled.service
|
|
65
|
+
enabled: true
|
|
66
|
+
state: started
|
|
67
|
+
- name: Inspect native authentication without prompting or opening a browser
|
|
68
|
+
ansible.builtin.command:
|
|
69
|
+
argv: [tailscale, status, '--json']
|
|
70
|
+
changed_when: false
|
|
71
|
+
failed_when: false
|
|
72
|
+
register: tailscale_status
|
|
73
|
+
no_log: true
|
|
74
|
+
- name: Require genuine device authentication before claiming connectivity
|
|
75
|
+
ansible.builtin.assert:
|
|
76
|
+
that: (tailscale_status.stdout | from_json).BackendState == 'Running'
|
|
77
|
+
fail_msg: TAILSCALE_LOGIN_REQUIRED; authorize this device through its native login. Existing state is never copied or reset.
|
|
78
|
+
no_log: true
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
- name: Create persistent worker credential renewal units
|
|
3
|
+
ansible.builtin.file:
|
|
4
|
+
path: '{{ development_home }}/.config/systemd/user'
|
|
5
|
+
state: directory
|
|
6
|
+
owner: '{{ development_user }}'
|
|
7
|
+
mode: '0700'
|
|
8
|
+
- name: Declare native self-token renewal without copying credentials
|
|
9
|
+
ansible.builtin.copy:
|
|
10
|
+
dest: '{{ development_home }}/.config/systemd/user/personal-worker-auth.service'
|
|
11
|
+
owner: '{{ development_user }}'
|
|
12
|
+
mode: '0600'
|
|
13
|
+
content: |
|
|
14
|
+
[Unit]
|
|
15
|
+
Description=Renew this worker's own Vault authorization
|
|
16
|
+
[Service]
|
|
17
|
+
Type=oneshot
|
|
18
|
+
WorkingDirectory={{ development_source }}
|
|
19
|
+
ExecStart={{ development_home }}/.local/bin/mise exec -- bun bootstrap/worker-auth.ts
|
|
20
|
+
Environment="PATH={{ development_home }}/.local/share/mise/shims:{{ development_home }}/.local/bin:/usr/local/bin:/usr/bin:/bin"
|
|
21
|
+
UMask=0077
|
|
22
|
+
TimeoutStartSec=45
|
|
23
|
+
- name: Declare bounded persistent renewal schedule
|
|
24
|
+
ansible.builtin.copy:
|
|
25
|
+
dest: '{{ development_home }}/.config/systemd/user/personal-worker-auth.timer'
|
|
26
|
+
owner: '{{ development_user }}'
|
|
27
|
+
mode: '0600'
|
|
28
|
+
content: |
|
|
29
|
+
[Unit]
|
|
30
|
+
Description=Keep enrolled worker Vault authorization renewed
|
|
31
|
+
[Timer]
|
|
32
|
+
OnBootSec=2min
|
|
33
|
+
OnUnitActiveSec=10min
|
|
34
|
+
Persistent=true
|
|
35
|
+
[Install]
|
|
36
|
+
WantedBy=timers.target
|
|
37
|
+
- name: Enable this user's credential renewal timer
|
|
38
|
+
become: true
|
|
39
|
+
become_user: '{{ development_user }}'
|
|
40
|
+
environment:
|
|
41
|
+
XDG_RUNTIME_DIR: '/run/user/{{ development_uid }}'
|
|
42
|
+
ansible.builtin.systemd_service:
|
|
43
|
+
scope: user
|
|
44
|
+
name: personal-worker-auth.timer
|
|
45
|
+
daemon_reload: true
|
|
46
|
+
enabled: true
|
|
47
|
+
state: started
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
- name: Rotate container logs by default (new containers, after the next Docker restart)
|
|
3
|
+
ansible.builtin.copy:
|
|
4
|
+
dest: /etc/docker/daemon.json
|
|
5
|
+
force: false
|
|
6
|
+
owner: root
|
|
7
|
+
group: root
|
|
8
|
+
mode: '0644'
|
|
9
|
+
content: |
|
|
10
|
+
{
|
|
11
|
+
"log-driver": "json-file",
|
|
12
|
+
"log-opts": { "max-size": "{{ resourceSafety.dockerLogMaxSize }}", "max-file": "{{ resourceSafety.dockerLogMaxFiles }}" }
|
|
13
|
+
}
|
|
14
|
+
validate: dockerd --validate --config-file %s
|
|
15
|
+
- name: Start the native Docker engine without restarting existing workloads
|
|
16
|
+
ansible.builtin.systemd_service:
|
|
17
|
+
name: docker.service
|
|
18
|
+
enabled: true
|
|
19
|
+
state: started
|
|
20
|
+
- name: Grant the designated developer access to the local Docker engine
|
|
21
|
+
ansible.builtin.user:
|
|
22
|
+
name: '{{ development_user }}'
|
|
23
|
+
groups: docker
|
|
24
|
+
append: true
|
|
25
|
+
- name: Verify native Docker Compose and Buildx installation
|
|
26
|
+
ansible.builtin.command:
|
|
27
|
+
argv: '{{ item }}'
|
|
28
|
+
loop:
|
|
29
|
+
- [docker, compose, version]
|
|
30
|
+
- [docker, buildx, version]
|
|
31
|
+
changed_when: false
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
- name: Create owned APT configuration directory
|
|
3
|
+
ansible.builtin.file:
|
|
4
|
+
path: /etc/personal-fleet
|
|
5
|
+
state: directory
|
|
6
|
+
owner: root
|
|
7
|
+
group: root
|
|
8
|
+
mode: '0755'
|
|
9
|
+
- name: Declare snapshot sources used only for managed package transactions
|
|
10
|
+
ansible.builtin.copy:
|
|
11
|
+
dest: /etc/personal-fleet/ubuntu.sources
|
|
12
|
+
owner: root
|
|
13
|
+
group: root
|
|
14
|
+
mode: '0644'
|
|
15
|
+
backup: true
|
|
16
|
+
content: |
|
|
17
|
+
Types: deb
|
|
18
|
+
URIs: https://snapshot.ubuntu.com/ubuntu/{{ snapshot }}/
|
|
19
|
+
Suites: resolute resolute-updates resolute-security
|
|
20
|
+
Components: main universe restricted multiverse
|
|
21
|
+
Signed-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg
|
|
22
|
+
register: snapshot_sources
|
|
23
|
+
- name: Isolate snapshot selection from unrelated APT operations
|
|
24
|
+
ansible.builtin.copy:
|
|
25
|
+
dest: /etc/personal-fleet/apt.conf
|
|
26
|
+
owner: root
|
|
27
|
+
group: root
|
|
28
|
+
mode: '0644'
|
|
29
|
+
content: |
|
|
30
|
+
Dir::Etc::sourcelist "/etc/personal-fleet/ubuntu.sources";
|
|
31
|
+
Dir::Etc::sourceparts "-";
|
|
32
|
+
DPkg::Lock::Timeout "{{ aptLockTimeoutSeconds }}";
|
|
33
|
+
- name: Inspect immutable snapshot package index
|
|
34
|
+
ansible.builtin.stat:
|
|
35
|
+
path: '/var/lib/apt/lists/snapshot.ubuntu.com_ubuntu_{{ snapshot }}_dists_resolute_InRelease'
|
|
36
|
+
register: snapshot_index
|
|
37
|
+
- name: Fetch signed snapshot indexes after source change or interrupted setup
|
|
38
|
+
ansible.builtin.apt:
|
|
39
|
+
update_cache: true
|
|
40
|
+
cache_valid_time: 0
|
|
41
|
+
lock_timeout: '{{ aptLockTimeoutSeconds }}'
|
|
42
|
+
environment:
|
|
43
|
+
APT_CONFIG: /etc/personal-fleet/apt.conf
|
|
44
|
+
when: snapshot_sources.changed or not snapshot_index.stat.exists
|
|
45
|
+
- name: Install exact managed packages without downgrading or restarting services
|
|
46
|
+
ansible.builtin.apt:
|
|
47
|
+
name: '{{ item.key }}={{ item.value }}'
|
|
48
|
+
state: present
|
|
49
|
+
lock_timeout: '{{ aptLockTimeoutSeconds }}'
|
|
50
|
+
allow_downgrade: false
|
|
51
|
+
allow_unauthenticated: false
|
|
52
|
+
fail_on_autoremove: true
|
|
53
|
+
policy_rc_d: 101
|
|
54
|
+
environment:
|
|
55
|
+
APT_CONFIG: /etc/personal-fleet/apt.conf
|
|
56
|
+
loop: '{{ packages | dict2items }}'
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
- name: Ensure systemd policy directories exist
|
|
3
|
+
ansible.builtin.file:
|
|
4
|
+
path: '{{ item }}'
|
|
5
|
+
state: directory
|
|
6
|
+
owner: root
|
|
7
|
+
group: root
|
|
8
|
+
mode: '0755'
|
|
9
|
+
loop:
|
|
10
|
+
- /etc/systemd/logind.conf.d
|
|
11
|
+
- /etc/systemd/sleep.conf.d
|
|
12
|
+
- name: Declare idle and lid policy without restarting login sessions
|
|
13
|
+
ansible.builtin.copy:
|
|
14
|
+
dest: /etc/systemd/logind.conf.d/60-personal-fleet.conf
|
|
15
|
+
owner: root
|
|
16
|
+
group: root
|
|
17
|
+
mode: '0644'
|
|
18
|
+
backup: true
|
|
19
|
+
content: |
|
|
20
|
+
# Managed by personal fleet-sync. Effective after logind reload/reboot.
|
|
21
|
+
[Login]
|
|
22
|
+
HandleLidSwitch=ignore
|
|
23
|
+
HandleLidSwitchExternalPower=ignore
|
|
24
|
+
HandleLidSwitchDocked=ignore
|
|
25
|
+
IdleAction=ignore
|
|
26
|
+
KillUserProcesses=no
|
|
27
|
+
StopIdleSessionSec=infinity
|
|
28
|
+
- name: Declare supported sleep policy
|
|
29
|
+
ansible.builtin.copy:
|
|
30
|
+
dest: /etc/systemd/sleep.conf.d/60-personal-fleet.conf
|
|
31
|
+
owner: root
|
|
32
|
+
group: root
|
|
33
|
+
mode: '0644'
|
|
34
|
+
backup: true
|
|
35
|
+
content: |
|
|
36
|
+
[Sleep]
|
|
37
|
+
AllowSuspend=no
|
|
38
|
+
AllowHibernation=no
|
|
39
|
+
AllowSuspendThenHibernate=no
|
|
40
|
+
AllowHybridSleep=no
|
|
41
|
+
- name: Mask sleep transitions without stopping running user sessions
|
|
42
|
+
ansible.builtin.systemd_service:
|
|
43
|
+
name: '{{ item }}'
|
|
44
|
+
masked: true
|
|
45
|
+
daemon_reload: true
|
|
46
|
+
loop:
|
|
47
|
+
- sleep.target
|
|
48
|
+
- suspend.target
|
|
49
|
+
- hibernate.target
|
|
50
|
+
- hybrid-sleep.target
|
|
51
|
+
- suspend-then-hibernate.target
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
- name: Declare bounded recovery of the worker T3 desktop app
|
|
3
|
+
ansible.builtin.copy:
|
|
4
|
+
dest: '{{ development_home }}/.config/systemd/user/personal-worker-recovery.service'
|
|
5
|
+
owner: '{{ development_user }}'
|
|
6
|
+
mode: '0600'
|
|
7
|
+
content: |
|
|
8
|
+
# Managed by personal fleet-sync: ansible/ubuntu/t3-health.sh
|
|
9
|
+
[Unit]
|
|
10
|
+
Description=Keep the worker T3 desktop app running and responsive
|
|
11
|
+
[Service]
|
|
12
|
+
Type=oneshot
|
|
13
|
+
ExecStart=/bin/sh {{ development_source }}/ansible/ubuntu/t3-health.sh
|
|
14
|
+
TimeoutStartSec=90
|
|
15
|
+
- name: Declare persistent service recovery checks
|
|
16
|
+
ansible.builtin.copy:
|
|
17
|
+
dest: '{{ development_home }}/.config/systemd/user/personal-worker-recovery.timer'
|
|
18
|
+
owner: '{{ development_user }}'
|
|
19
|
+
mode: '0600'
|
|
20
|
+
content: |
|
|
21
|
+
[Unit]
|
|
22
|
+
Description=Check the worker T3 desktop app every minute
|
|
23
|
+
[Timer]
|
|
24
|
+
OnBootSec=1min
|
|
25
|
+
OnUnitActiveSec=1min
|
|
26
|
+
Persistent=true
|
|
27
|
+
[Install]
|
|
28
|
+
WantedBy=timers.target
|
|
29
|
+
- name: Enable bounded T3 recovery without restarting active sessions
|
|
30
|
+
become: true
|
|
31
|
+
become_user: '{{ development_user }}'
|
|
32
|
+
environment:
|
|
33
|
+
XDG_RUNTIME_DIR: '/run/user/{{ development_uid }}'
|
|
34
|
+
ansible.builtin.systemd_service:
|
|
35
|
+
scope: user
|
|
36
|
+
name: personal-worker-recovery.timer
|
|
37
|
+
daemon_reload: true
|
|
38
|
+
enabled: true
|
|
39
|
+
state: started
|