rigscope 0.0.0-stage → 0.1.1
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/.next/BUILD_ID +1 -0
- package/.next/app-path-routes-manifest.json +13 -0
- package/.next/build-manifest.json +20 -0
- package/.next/export-marker.json +6 -0
- package/.next/images-manifest.json +68 -0
- package/.next/next-minimal-server.js.nft.json +1 -0
- package/.next/next-server.js.nft.json +1 -0
- package/.next/package.json +1 -0
- package/.next/prerender-manifest.json +297 -0
- package/.next/react-loadable-manifest.json +1 -0
- package/.next/required-server-files.json +369 -0
- package/.next/routes-manifest.json +114 -0
- package/.next/server/app/_global-error/page.js +31 -0
- package/.next/server/app/_global-error/page.js.nft.json +1 -0
- package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -0
- package/.next/server/app/_global-error.html +1 -0
- package/.next/server/app/_global-error.meta +35 -0
- package/.next/server/app/_global-error.rsc +18 -0
- package/.next/server/app/_global-error.segments/_full.segment.rsc +18 -0
- package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +24 -0
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +3 -0
- package/.next/server/app/_not-found/page.js +1 -0
- package/.next/server/app/_not-found/page.js.nft.json +1 -0
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
- package/.next/server/app/_not-found.html +1 -0
- package/.next/server/app/_not-found.meta +35 -0
- package/.next/server/app/_not-found.rsc +24 -0
- package/.next/server/app/_not-found.segments/_full.segment.rsc +24 -0
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +30 -0
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/administration/page.js +1 -0
- package/.next/server/app/administration/page.js.nft.json +1 -0
- package/.next/server/app/administration/page_client-reference-manifest.js +1 -0
- package/.next/server/app/administration.html +1 -0
- package/.next/server/app/administration.meta +34 -0
- package/.next/server/app/administration.rsc +29 -0
- package/.next/server/app/administration.segments/_full.segment.rsc +29 -0
- package/.next/server/app/administration.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/administration.segments/administration/__PAGE__.segment.rsc +35 -0
- package/.next/server/app/alerts/page.js +1 -0
- package/.next/server/app/alerts/page.js.nft.json +1 -0
- package/.next/server/app/alerts/page_client-reference-manifest.js +1 -0
- package/.next/server/app/alerts.html +1 -0
- package/.next/server/app/alerts.meta +34 -0
- package/.next/server/app/alerts.rsc +28 -0
- package/.next/server/app/alerts.segments/_full.segment.rsc +28 -0
- package/.next/server/app/alerts.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/alerts.segments/alerts/__PAGE__.segment.rsc +34 -0
- package/.next/server/app/connections/page.js +1 -0
- package/.next/server/app/connections/page.js.nft.json +1 -0
- package/.next/server/app/connections/page_client-reference-manifest.js +1 -0
- package/.next/server/app/connections.html +1 -0
- package/.next/server/app/connections.meta +34 -0
- package/.next/server/app/connections.rsc +29 -0
- package/.next/server/app/connections.segments/_full.segment.rsc +29 -0
- package/.next/server/app/connections.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/connections.segments/connections/__PAGE__.segment.rsc +35 -0
- package/.next/server/app/history/page.js +2 -0
- package/.next/server/app/history/page.js.nft.json +1 -0
- package/.next/server/app/history/page_client-reference-manifest.js +1 -0
- package/.next/server/app/history.html +1 -0
- package/.next/server/app/history.meta +34 -0
- package/.next/server/app/history.rsc +33 -0
- package/.next/server/app/history.segments/_full.segment.rsc +33 -0
- package/.next/server/app/history.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/history.segments/history/__PAGE__.segment.rsc +37 -0
- package/.next/server/app/icon.svg/route.js +1 -0
- package/.next/server/app/icon.svg/route.js.nft.json +1 -0
- package/.next/server/app/icon.svg.body +1 -0
- package/.next/server/app/icon.svg.meta +1 -0
- package/.next/server/app/index.html +1 -0
- package/.next/server/app/index.meta +29 -0
- package/.next/server/app/index.rsc +26 -0
- package/.next/server/app/index.segments/__PAGE__.segment.rsc +31 -0
- package/.next/server/app/index.segments/_full.segment.rsc +26 -0
- package/.next/server/app/index.segments/_tree.segment.rsc +3 -0
- package/.next/server/app/login/page.js +1 -0
- package/.next/server/app/login/page.js.nft.json +1 -0
- package/.next/server/app/login/page_client-reference-manifest.js +1 -0
- package/.next/server/app/login.html +1 -0
- package/.next/server/app/login.meta +34 -0
- package/.next/server/app/login.rsc +26 -0
- package/.next/server/app/login.segments/_full.segment.rsc +26 -0
- package/.next/server/app/login.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +32 -0
- package/.next/server/app/machines/[machineId]/page.js +1 -0
- package/.next/server/app/machines/[machineId]/page.js.nft.json +1 -0
- package/.next/server/app/machines/[machineId]/page_client-reference-manifest.js +1 -0
- package/.next/server/app/page.js +1 -0
- package/.next/server/app/page.js.nft.json +1 -0
- package/.next/server/app/page_client-reference-manifest.js +1 -0
- package/.next/server/app/processes/page.js +2 -0
- package/.next/server/app/processes/page.js.nft.json +1 -0
- package/.next/server/app/processes/page_client-reference-manifest.js +1 -0
- package/.next/server/app/processes.html +1 -0
- package/.next/server/app/processes.meta +34 -0
- package/.next/server/app/processes.rsc +30 -0
- package/.next/server/app/processes.segments/_full.segment.rsc +30 -0
- package/.next/server/app/processes.segments/_tree.segment.rsc +4 -0
- package/.next/server/app/processes.segments/processes/__PAGE__.segment.rsc +36 -0
- package/.next/server/app-paths-manifest.json +13 -0
- package/.next/server/chunks/161.js +1 -0
- package/.next/server/chunks/168.js +1 -0
- package/.next/server/chunks/266.js +68 -0
- package/.next/server/chunks/430.js +116 -0
- package/.next/server/chunks/721.js +1 -0
- package/.next/server/chunks/751.js +1 -0
- package/.next/server/chunks/877.js +1 -0
- package/.next/server/chunks/894.js +2 -0
- package/.next/server/functions-config-manifest.json +4 -0
- package/.next/server/interception-route-rewrite-manifest.js +1 -0
- package/.next/server/middleware-build-manifest.js +1 -0
- package/.next/server/middleware-manifest.json +6 -0
- package/.next/server/middleware-react-loadable-manifest.js +1 -0
- package/.next/server/next-font-manifest.js +1 -0
- package/.next/server/next-font-manifest.json +1 -0
- package/.next/server/pages/404.html +1 -0
- package/.next/server/pages/500.html +1 -0
- package/.next/server/pages-manifest.json +4 -0
- package/.next/server/prefetch-hints.json +123 -0
- package/.next/server/preview-props.json +5 -0
- package/.next/server/server-reference-manifest.js +1 -0
- package/.next/server/server-reference-manifest.json +1 -0
- package/.next/server/webpack-runtime.js +1 -0
- package/.next/static/NE6PGEiJxUnKRceuzUWPc/_buildManifest.js +1 -0
- package/.next/static/NE6PGEiJxUnKRceuzUWPc/_ssgManifest.js +1 -0
- package/.next/static/chunks/103-c47318242b24e9ac.js +1 -0
- package/.next/static/chunks/157-0d36ebf66af048ac.js +1 -0
- package/.next/static/chunks/227-417939c480f50747.js +1 -0
- package/.next/static/chunks/408-dc6158e0bb450ef6.js +1 -0
- package/.next/static/chunks/4bd1b696-c7408084347438ae.js +1 -0
- package/.next/static/chunks/794-ceeb732a1a81bc27.js +52 -0
- package/.next/static/chunks/939-2600d7c8e583d5ef.js +1 -0
- package/.next/static/chunks/app/_global-error/page-aba28f88d5781771.js +1 -0
- package/.next/static/chunks/app/_not-found/page-a2a510233e4836e2.js +1 -0
- package/.next/static/chunks/app/administration/page-4b16b19bb6a39c36.js +1 -0
- package/.next/static/chunks/app/alerts/page-fe0e877778c60af8.js +1 -0
- package/.next/static/chunks/app/connections/page-99cd54d6929b3f1f.js +1 -0
- package/.next/static/chunks/app/history/page-1475454737279ee0.js +3 -0
- package/.next/static/chunks/app/layout-4feff677c4071745.js +1 -0
- package/.next/static/chunks/app/login/page-c57e12dbe5146737.js +1 -0
- package/.next/static/chunks/app/machines/[machineId]/page-916ee73de5eb067d.js +1 -0
- package/.next/static/chunks/app/page-1ae9fc94c897785b.js +1 -0
- package/.next/static/chunks/app/processes/page-e471ed23a1d5632f.js +3 -0
- package/.next/static/chunks/framework-ea4f97ca039bd777.js +1 -0
- package/.next/static/chunks/main-a458d32948147b84.js +5 -0
- package/.next/static/chunks/main-app-f92328c8950d2e53.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/app-error-aba28f88d5781771.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/forbidden-aba28f88d5781771.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/global-error-43cbaa3aa1576eb4.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/not-found-aba28f88d5781771.js +1 -0
- package/.next/static/chunks/next/dist/client/components/builtin/unauthorized-aba28f88d5781771.js +1 -0
- package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/.next/static/chunks/webpack-9ca43f4ce1bb8938.js +1 -0
- package/.next/static/css/e45c0c7ef5ba0336.css +1 -0
- package/ARCHITECTURE.md +279 -0
- package/CHANGELOG.md +37 -0
- package/DESIGN.md +299 -0
- package/LICENSE +21 -0
- package/README.md +74 -2
- package/SECURITY.md +12 -0
- package/THIRD_PARTY_NOTICES.md +8847 -0
- package/bin/rigscope.cjs +6 -0
- package/dist/cli.cjs +9075 -0
- package/dist/collector.cjs +5679 -0
- package/dist/hub.cjs +8364 -0
- package/dist/ops.cjs +4976 -0
- package/dist/system.cjs +4333 -0
- package/docs/bottlenecks.md +62 -0
- package/docs/configuration.md +85 -0
- package/docs/development.md +46 -0
- package/docs/exports.md +39 -0
- package/docs/installation.md +306 -0
- package/docs/monitoring.md +112 -0
- package/docs/operations.md +550 -0
- package/docs/releasing.md +154 -0
- package/docs/scale-acceptance.json +412 -0
- package/docs/scale-validation.json +1898 -0
- package/docs/scale-validation.md +294 -0
- package/docs/stress-2026-11-04/180301-probe-m100-u1-s1-20000ms.json +412 -0
- package/docs/stress-2026-11-04/180335-probe-m200-u1-s1-20000ms.json +412 -0
- package/docs/stress-2026-11-04/180409-probe-m400-u1-s1-20000ms.json +412 -0
- package/docs/stress-2026-11-04/180443-probe-m800-u1-s1-20000ms.json +412 -0
- package/docs/stress-2026-11-04/180518-probe-m600-u1-s1-20000ms.json +412 -0
- package/docs/stress-2026-11-04/180553-probe-m500-u1-s1-20000ms.json +412 -0
- package/docs/stress-2026-11-04/180628-probe-m550-u1-s1-20000ms.json +412 -0
- package/docs/stress-2026-11-04/180716-probe-m800-u1-s0-20000ms.json +415 -0
- package/docs/stress-2026-11-04/180751-probe-m1600-u1-s0-20000ms.json +415 -0
- package/docs/stress-2026-11-04/180828-probe-m3200-u1-s0-20000ms.json +416 -0
- package/docs/stress-2026-11-04/180941-probe-m2400-u1-s0-20000ms.json +416 -0
- package/docs/stress-2026-11-04/181031-probe-m2000-u1-s0-20000ms.json +416 -0
- package/docs/stress-2026-11-04/181114-probe-m1800-u1-s0-20000ms.json +416 -0
- package/docs/stress-2026-11-04/181203-probe-m100-u64-s64-20000ms.json +418 -0
- package/docs/stress-2026-11-04/181304-probe-m200-u64-s64-20000ms.json +418 -0
- package/docs/stress-2026-11-04/181405-probe-m400-u64-s64-20000ms.json +418 -0
- package/docs/stress-2026-11-04/181507-probe-m500-u64-s64-20000ms.json +418 -0
- package/docs/stress-2026-11-04/181609-probe-m450-u64-s64-20000ms.json +418 -0
- package/docs/stress-2026-11-04/181845-probe-m2-u2-s2-3000ms.json +419 -0
- package/docs/stress-2026-11-04/181931-probe-m500-u64-s64-30000ms.json +420 -0
- package/docs/stress-2026-11-04/182108-probe-m1800-u1-s0-120000ms.json +418 -0
- package/docs/stress-2026-11-04/182354-probe-m1200-u1-s0-120000ms.json +418 -0
- package/docs/stress-2026-11-04/182625-probe-m900-u1-s0-120000ms.json +418 -0
- package/docs/stress-2026-11-04/182847-probe-m1050-u1-s0-120000ms.json +418 -0
- package/docs/stress-2026-11-04/183112-probe-m1125-u1-s0-120000ms.json +418 -0
- package/docs/stress-2026-11-04/193608-probe-m500-u64-s64-120000ms.json +420 -0
- package/docs/stress-2026-11-04/193909-probe-m529-u1-s1-15000ms.json +420 -0
- package/docs/stress-2026-11-04/193940-probe-m530-u1-s1-15000ms.json +420 -0
- package/docs/stress-2026-11-04/194011-probe-m100-u1-s65-10000ms.json +421 -0
- package/docs/stress-2026-11-04/README.md +205 -0
- package/docs/stress-2026-11-04/index.jsonl +29 -0
- package/docs/stress-2026-11-04/manifest.json +13 -0
- package/docs/stress-2026-11-04/results.html +22 -0
- package/docs/system-installation.md +195 -0
- package/next.config.js +38 -0
- package/package.json +117 -4
- package/packaging/README.md +5 -0
- package/packaging/collector.env.example +24 -0
- package/packaging/hub.env.example +31 -0
- package/packaging/system/90-rigscope-rapl.rules +7 -0
- package/packaging/system/README.md +5 -0
- package/packaging/system/rigscope-collector.service.example +53 -0
- package/packaging/system/rigscope-hub.service.example +50 -0
- package/packaging/system/rigscope-rapl.sysusers +5 -0
- package/packaging/system/rigscope.sysusers +7 -0
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
# Operations
|
|
2
|
+
|
|
3
|
+
For an npm installation, use the managed commands below. The
|
|
4
|
+
[manifest archive workflow](#low-level-manifest-archive-workflow) is for operators
|
|
5
|
+
building and deploying from source.
|
|
6
|
+
|
|
7
|
+
| Task | Section |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| Check, upgrade or roll back an npm installation | [Managed CLI operations](#managed-cli-operations) |
|
|
10
|
+
| Reset a lost password | [Password recovery](#password-recovery) |
|
|
11
|
+
| Change localhost/HTTPS access | [Access changes](#access-changes) |
|
|
12
|
+
| Back up or restore a database | [Database commands](#database-commands) |
|
|
13
|
+
| Plan what to back up | [Consistent backup set](#consistent-backup-set) |
|
|
14
|
+
| Handle a full database or queue | [Storage pressure recovery](#storage-budgets-and-pressure-recovery) |
|
|
15
|
+
|
|
16
|
+
## Managed CLI operations
|
|
17
|
+
|
|
18
|
+
These commands apply to an installation created by `rigscope install`. Its
|
|
19
|
+
state directory defaults to `~/.local/state/rigscope`.
|
|
20
|
+
|
|
21
|
+
### Check health
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
rigscope status
|
|
25
|
+
rigscope doctor
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`status` shows services and the dashboard URL. `doctor` checks configuration,
|
|
29
|
+
runtimes, database integrity, listeners, TLS destinations, disk space and sensor
|
|
30
|
+
access. It follows enabled components: a hub-only installation does not need a
|
|
31
|
+
collector. Checks are read-only and omit credentials. Use `doctor --json` for
|
|
32
|
+
structured output.
|
|
33
|
+
|
|
34
|
+
### Upgrade
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
rigscope upgrade
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Use `--from PACKAGE` for an exact npm version or local archive. The command
|
|
41
|
+
stages the package, stops running components, takes a consistent hub database
|
|
42
|
+
backup and activates the new runtime. It restarts only the components that were
|
|
43
|
+
running, then checks:
|
|
44
|
+
|
|
45
|
+
- the installed and running versions match the new package;
|
|
46
|
+
- restarted services are active;
|
|
47
|
+
- hub health is OK and its database passes integrity/schema checks;
|
|
48
|
+
- a restarted collector produces a fresh sampling marker.
|
|
49
|
+
|
|
50
|
+
The health timeout is 25 seconds; change it with `--timeout SECONDS`. A failed
|
|
51
|
+
start, migration or health check restores the previous runtime. It also restores
|
|
52
|
+
the paired database backup if the old runtime cannot read the new schema,
|
|
53
|
+
preserving the replaced database first.
|
|
54
|
+
|
|
55
|
+
Credentials, collector identities and pending samples are retained.
|
|
56
|
+
`release-state.json` records which backup belongs to each runtime. Upgrading a
|
|
57
|
+
stopped installation leaves it stopped and reports live checks as skipped.
|
|
58
|
+
|
|
59
|
+
### Roll back
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
rigscope rollback
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Rollback uses `runtime-previous` and runs the same health checks. If that runtime
|
|
66
|
+
can read the current database, post-upgrade data stays intact. Otherwise it
|
|
67
|
+
restores the paired pre-upgrade backup and saves the replaced database.
|
|
68
|
+
|
|
69
|
+
A missing compatible backup stops rollback. Older installations without a
|
|
70
|
+
recorded backup can supply a compatible copy with `--backup PATH`. Never point
|
|
71
|
+
old code at a newer database schema.
|
|
72
|
+
|
|
73
|
+
## Password recovery
|
|
74
|
+
|
|
75
|
+
Stop the installation, enter a new password at the private prompt, then restart:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
rigscope stop
|
|
79
|
+
rigscope recover-password --user owner
|
|
80
|
+
rigscope start
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Recovery requires the hub to be stopped and refuses a live or uncertain database
|
|
84
|
+
lock. For unattended recovery, use `--password-file` with an owned `0600` file.
|
|
85
|
+
It updates the existing user's stored hash. `--enable` also clears that user's
|
|
86
|
+
disabled flag; recovery never creates a user or grants administrator access.
|
|
87
|
+
|
|
88
|
+
The operation records an audit event and invalidates sessions. It keeps
|
|
89
|
+
configuration, history and collector credentials. Sign in again after restart;
|
|
90
|
+
editing bootstrap hashes in `config.json` or `HUB_BROWSER_USERS` does not reset a
|
|
91
|
+
managed account.
|
|
92
|
+
|
|
93
|
+
## Access changes
|
|
94
|
+
|
|
95
|
+
Follow the commands in [Remote access](installation.md#access-from-another-computer).
|
|
96
|
+
`configure` requires a stopped hub and, when changing its local collector's
|
|
97
|
+
destination, a stopped collector.
|
|
98
|
+
|
|
99
|
+
It validates the HTTPS origin and private socket, backs up the old settings, and
|
|
100
|
+
updates the matching local collector destination. It moves that destination's
|
|
101
|
+
whole queue directory, including SQLite WAL files. Credentials and other hubs
|
|
102
|
+
stay unchanged. An existing target queue stops the conversion to avoid merging
|
|
103
|
+
or discarding pending records. Accounts and the hub history database are retained.
|
|
104
|
+
Rollback targets must support the saved configuration and database schema.
|
|
105
|
+
|
|
106
|
+
## Low-level manifest archive workflow
|
|
107
|
+
|
|
108
|
+
The remaining archive deployment examples assume a source checkout with built
|
|
109
|
+
artifacts. They use a manifest `.tar.gz`, which is different from the npm `.tgz`
|
|
110
|
+
used by `rigscope install` and `rigscope upgrade`. For ordinary installations,
|
|
111
|
+
follow [installation](installation.md) and the managed commands above. The npm
|
|
112
|
+
package excludes source helper scripts and does not require users to build it.
|
|
113
|
+
|
|
114
|
+
The built deployment runs `dist/hub.cjs` for the dashboard and collector
|
|
115
|
+
connections, and `dist/collector.cjs` for collection. `dist/ops.cjs` provides the
|
|
116
|
+
database and archive tools below. The hub serves the production Next.js output
|
|
117
|
+
from `.next`; it does not use `next start` or standalone output.
|
|
118
|
+
|
|
119
|
+
Choose a prefix and state directory owned by the service user. All paths below
|
|
120
|
+
are examples; generated units support paths containing spaces.
|
|
121
|
+
|
|
122
|
+
### Build and package
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
npm ci
|
|
126
|
+
npm run build:ui # production .next
|
|
127
|
+
npm run build:runtime # dist/hub.cjs, dist/collector.cjs, dist/ops.cjs
|
|
128
|
+
node scripts/package-release.cjs --output /var/tmp/rigscope-release.tar.gz
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The archive contains the built runtime, `.next` without its cache, package and
|
|
132
|
+
lock files, the repository's `next.config.js`, `tsconfig.json`,
|
|
133
|
+
operational docs and the `packaging/` examples. It deliberately excludes source, tests, git data,
|
|
134
|
+
`node_modules`, private environment files, SQLite databases, keys and logs.
|
|
135
|
+
`manifest.json` lists every packaged file with size and SHA-256; the installer
|
|
136
|
+
re-verifies it before activation.
|
|
137
|
+
|
|
138
|
+
Production dependencies are installed inside each staged release:
|
|
139
|
+
|
|
140
|
+
```sh
|
|
141
|
+
cd /home/operator/.local/opt/rigscope/releases/<version>
|
|
142
|
+
npm ci --omit=dev
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
`install --install-deps` can run that command explicitly, but the installer
|
|
146
|
+
never runs npm implicitly for activation. If a package mirror is unavailable,
|
|
147
|
+
stage without activation and install from an approved mirror; do not weaken npm
|
|
148
|
+
security policy just to make installation pass. Isolated tests use a synthetic
|
|
149
|
+
dependency tree and do not perform remote installs.
|
|
150
|
+
|
|
151
|
+
## Stage and activate
|
|
152
|
+
|
|
153
|
+
```sh
|
|
154
|
+
node scripts/install-release.cjs \
|
|
155
|
+
--source /var/tmp/rigscope-release.tar.gz \
|
|
156
|
+
--prefix /home/operator/.local/opt/rigscope \
|
|
157
|
+
--state-dir /home/operator/.local/state/rigscope \
|
|
158
|
+
--units-dir /home/operator/.config/systemd/user
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
The installer creates:
|
|
162
|
+
|
|
163
|
+
```text
|
|
164
|
+
<prefix>/
|
|
165
|
+
releases/<version>/ immutable built release + manifest
|
|
166
|
+
releases/<version>/node_modules/
|
|
167
|
+
current -> releases/<version>
|
|
168
|
+
previous -> releases/<previous> (retained for rollback)
|
|
169
|
+
<state>/
|
|
170
|
+
hub/telemetry.sqlite hub database (0700 dir, 0600 file)
|
|
171
|
+
hub.env private EnvironmentFile (0600, no secrets printed)
|
|
172
|
+
collector.env private EnvironmentFile (0600)
|
|
173
|
+
collector/collector.json collector identity/enrollment (created by collector)
|
|
174
|
+
outbox/<sha256(url)[0:16]>/ per-destination collector outboxes
|
|
175
|
+
backups/ private pre-upgrade/pre-activation database copies
|
|
176
|
+
install-state.json versions, schema backups, no credentials
|
|
177
|
+
run/ private runtime directory for a Unix socket
|
|
178
|
+
<units-dir>/
|
|
179
|
+
rigscope-hub.service
|
|
180
|
+
rigscope-collector.service
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Staging does not switch `current` or start anything. After production
|
|
184
|
+
dependencies are installed and the old hub is stopped, activate explicitly:
|
|
185
|
+
|
|
186
|
+
```sh
|
|
187
|
+
node scripts/install-release.cjs activate \
|
|
188
|
+
--prefix /home/operator/.local/opt/rigscope \
|
|
189
|
+
--state-dir /home/operator/.local/state/rigscope \
|
|
190
|
+
--version <version> --confirm-stopped
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Activation order is fixed:
|
|
194
|
+
|
|
195
|
+
1. Validate the release manifest, hashes and production dependencies.
|
|
196
|
+
2. Verify no hub lock exists and the operator confirmed the hub is stopped.
|
|
197
|
+
3. Inspect the current database schema.
|
|
198
|
+
4. If migration is needed: write a consistent online backup, then migrate, then
|
|
199
|
+
verify integrity and the target schema. A failed migration restores the
|
|
200
|
+
pre-migration backup and leaves `current` unchanged.
|
|
201
|
+
5. Atomically switch `current`, retaining `previous` and a schema-backup record.
|
|
202
|
+
6. Print (never execute) systemd commands.
|
|
203
|
+
|
|
204
|
+
If validation or migration fails, a good database is never silently replaced.
|
|
205
|
+
The pre-migration backup path is printed. First installation with no database
|
|
206
|
+
creates and migrates a new private database.
|
|
207
|
+
|
|
208
|
+
## systemd user units
|
|
209
|
+
|
|
210
|
+
The generated units use an absolute Node 26 executable, absolute paths,
|
|
211
|
+
`WorkingDirectory=<prefix>/current`, a private `EnvironmentFile`, journald
|
|
212
|
+
logging, `Restart=on-failure`, `NoNewPrivileges=yes`, `PrivateTmp=yes`,
|
|
213
|
+
`UMask=0077`, `ProtectSystem=strict`, and explicit writable state/database/cache paths.
|
|
214
|
+
|
|
215
|
+
Startup is explicit and is not performed by the installer:
|
|
216
|
+
|
|
217
|
+
```sh
|
|
218
|
+
systemctl --user daemon-reload
|
|
219
|
+
systemctl --user enable --now rigscope-hub.service rigscope-collector.service
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Automatic startup after logout/host reboot requires an explicit administrator
|
|
223
|
+
choice to enable user lingering for that account:
|
|
224
|
+
|
|
225
|
+
```sh
|
|
226
|
+
sudo loginctl enable-linger operator
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Review the generated units and private env files first. Health and observation:
|
|
230
|
+
|
|
231
|
+
```sh
|
|
232
|
+
curl --fail --silent http://127.0.0.1:8081/api/health
|
|
233
|
+
systemctl --user status rigscope-hub.service rigscope-collector.service
|
|
234
|
+
journalctl --user -u rigscope-hub.service -f
|
|
235
|
+
journalctl --user -u rigscope-collector.service -f
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Shutdown is bounded: the hub targets five seconds and the collector three
|
|
239
|
+
seconds; the generated `TimeoutStopSec` leaves a ten- and seven-second slack
|
|
240
|
+
respectively. Keep those times at or above the process deadlines.
|
|
241
|
+
|
|
242
|
+
## Configuration
|
|
243
|
+
|
|
244
|
+
`RIGSCOPE_OPS_DEBUG` enables operation diagnostics; keep diagnostic output private. `RIGSCOPE_HUB_LOCK_FILE` overrides the hub lease path when needed; use the same path for the hub and operations commands.
|
|
245
|
+
|
|
246
|
+
The generated `hub.env` and `collector.env` contain only comments. Empty
|
|
247
|
+
configuration fails closed: no `HUB_BROWSER_USERS` means browser data is
|
|
248
|
+
unavailable, and no collector credentials/destinations means no fleet data.
|
|
249
|
+
Never copy the public demo credentials from the examples to a real host.
|
|
250
|
+
|
|
251
|
+
Loopback development:
|
|
252
|
+
|
|
253
|
+
```sh
|
|
254
|
+
HUB_HOST=127.0.0.1
|
|
255
|
+
HUB_PORT=8081
|
|
256
|
+
HUB_DATABASE_PATH=/home/operator/.local/state/rigscope/hub/telemetry.sqlite
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Browser users and collectors belong in the private environment file. Generate
|
|
260
|
+
browser password hashes locally with `scripts/hash-browser-password.cjs`; never
|
|
261
|
+
store plaintext passwords or hashes in shared logs.
|
|
262
|
+
|
|
263
|
+
Remote mode uses a private Unix socket behind an external TLS terminator:
|
|
264
|
+
|
|
265
|
+
```sh
|
|
266
|
+
HUB_PUBLIC_ORIGIN=https://monitor.example.invalid
|
|
267
|
+
HUB_SOCKET_PATH=/home/operator/.local/state/rigscope/run/hub.sock
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
The parent directory must be private and owned by the service user. The
|
|
271
|
+
installer's state `run/` directory is already writable by the unit. Remote
|
|
272
|
+
health checks go through the socket with the exact Host:
|
|
273
|
+
|
|
274
|
+
```sh
|
|
275
|
+
curl --fail --silent --unix-socket <socket> \
|
|
276
|
+
-H 'Host: monitor.example.invalid' http://localhost/api/health
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
This example hostname and every `demo-token-*` value are public fixtures, not a
|
|
280
|
+
deployment. See `development.md` for the exact origin/Host/cookie
|
|
281
|
+
boundary. Never expose the loopback HTTP listener remotely without the private
|
|
282
|
+
socket/TLS boundary and authentication.
|
|
283
|
+
|
|
284
|
+
Collector enrollment remains separate from browser sessions:
|
|
285
|
+
|
|
286
|
+
```sh
|
|
287
|
+
COLLECTOR_ENROLL_URL=ws://127.0.0.1:8081/api/collector/connect
|
|
288
|
+
COLLECTOR_ENROLL_TOKEN=<one-use grant>
|
|
289
|
+
COLLECTOR_MODE=real
|
|
290
|
+
COLLECTOR_STATE_FILE=/home/operator/.local/state/rigscope/collector/collector.json
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Remove the one-use grant after enrollment and start or restart the collector. The
|
|
294
|
+
hub does not need a restart. Enrollment state
|
|
295
|
+
and outboxes live outside the repository.
|
|
296
|
+
|
|
297
|
+
For an isolated local check without touching the real deployment, the public demo
|
|
298
|
+
grant from the packaging examples can drive a loopback enrollment and collection
|
|
299
|
+
run. These are deliberate demo strings only, never a real deployment:
|
|
300
|
+
|
|
301
|
+
```sh
|
|
302
|
+
HUB_STATE_FILE="$PWD/.rigscope-local/hub/enrollment.json" \
|
|
303
|
+
HUB_ENROLLMENT_GRANTS="$(node -e 'console.log(JSON.stringify([{token:"demo-token-enrollment-local",expiresAt:new Date(Date.now()+300000).toISOString()}]))')" \
|
|
304
|
+
npm start
|
|
305
|
+
|
|
306
|
+
# In another terminal:
|
|
307
|
+
COLLECTOR_STATE_FILE="$PWD/.rigscope-local/collector/state.json" \
|
|
308
|
+
COLLECTOR_ENROLL_URL='ws://127.0.0.1:8081/api/collector/connect' \
|
|
309
|
+
COLLECTOR_ENROLL_TOKEN='demo-token-enrollment-local' \
|
|
310
|
+
npm run collector:enroll
|
|
311
|
+
|
|
312
|
+
# Start real local collection with the saved credential:
|
|
313
|
+
COLLECTOR_STATE_FILE="$PWD/.rigscope-local/collector/state.json" npm run collector:start
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Enrollment posts `{collectorId}` to `/api/collector/enroll`; the bearer grant travels
|
|
317
|
+
only in the Authorization header. Grants must expire within fifteen minutes and are
|
|
318
|
+
consumed across restarts. Plaintext is allowed only for literal loopback addresses;
|
|
319
|
+
WSS enrollment uses HTTPS with ordinary certificate validation.
|
|
320
|
+
|
|
321
|
+
## Database commands
|
|
322
|
+
|
|
323
|
+
All commands take explicit paths. They print no credentials, user hashes,
|
|
324
|
+
webhook URLs, tokens or record payloads.
|
|
325
|
+
|
|
326
|
+
```sh
|
|
327
|
+
# Read-only schema/integrity/size/table summary.
|
|
328
|
+
node dist/ops.cjs inspect --database /path/telemetry.sqlite
|
|
329
|
+
|
|
330
|
+
# Consistent single-file online backup. Does NOT migrate the source.
|
|
331
|
+
node dist/ops.cjs backup \
|
|
332
|
+
--database /path/telemetry.sqlite \
|
|
333
|
+
--output /path/private-backups/telemetry-$(date +%Y%m%dT%H%M%S).sqlite
|
|
334
|
+
|
|
335
|
+
# Offline guarded migration. Existing databases require --confirm-stopped.
|
|
336
|
+
node dist/ops.cjs migrate \
|
|
337
|
+
--database /path/telemetry.sqlite \
|
|
338
|
+
--backup-dir /path/private-backups --confirm-stopped
|
|
339
|
+
|
|
340
|
+
# Guarded restore over an existing database: both flags are required.
|
|
341
|
+
node dist/ops.cjs restore \
|
|
342
|
+
--input /path/private-backups/telemetry-....sqlite \
|
|
343
|
+
--database /path/telemetry.sqlite \
|
|
344
|
+
--replace --confirm-stopped
|
|
345
|
+
|
|
346
|
+
# Offline managed-user recovery; password comes from a private 0600 file.
|
|
347
|
+
node dist/ops.cjs recover-admin \
|
|
348
|
+
--database /path/telemetry.sqlite \
|
|
349
|
+
--user owner --password-file /path/private-recovery-password --enable
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Safety rules enforced by `backup`/`restore`:
|
|
353
|
+
|
|
354
|
+
- The hub database is one SQLite file. The online backup copies all tables in
|
|
355
|
+
that file: telemetry, history rollups, receipts/gaps, machine latest and
|
|
356
|
+
inventory, the collector registry/grants/audit, admin users/audit, and alert
|
|
357
|
+
rules/incidents/jobs/webhook state. There is no partial table selection.
|
|
358
|
+
- Backup opens the source read-only, runs `integrity_check`, stages the copy,
|
|
359
|
+
converts it to a self-contained DELETE-journal file, verifies the staged copy,
|
|
360
|
+
sets mode 0600 and atomically renames it. The source schema is never migrated.
|
|
361
|
+
- Restore validates the input integrity and migration ledger, refuses a schema
|
|
362
|
+
newer than this operations build, refuses to overwrite the target without
|
|
363
|
+
`--replace --confirm-stopped`, and refuses if a hub lock is present.
|
|
364
|
+
- It stages and verifies a copy first. For an existing target it checkpoints the
|
|
365
|
+
old database, takes a pre-restore backup, then removes only the old WAL/SHM
|
|
366
|
+
sidecars after proof that the hub is stopped, and atomically replaces the
|
|
367
|
+
main file. A failed validation never overwrites the target.
|
|
368
|
+
- The hub process lease is `<databasePath>.hub.lock` (JSON `{pid,instance}`).
|
|
369
|
+
Operations refuses while it exists, even if the PID looks stale, because only
|
|
370
|
+
the hub's own startup proof may recover a proven-dead lease. The hub removes
|
|
371
|
+
it on clean shutdown/exit; operators must inspect a lock and never delete it
|
|
372
|
+
blindly.
|
|
373
|
+
- Restoring an older-schema backup is allowed; the matching release migrates it
|
|
374
|
+
on the next hub start. Never start an old release against a newer schema.
|
|
375
|
+
|
|
376
|
+
Schema versions are derived from the build's migration ledger. The current
|
|
377
|
+
ledger includes telemetry, latest-session identity, admin, alerts and collector
|
|
378
|
+
registry migrations. A newer database must be opened by newer code; an old
|
|
379
|
+
release must never be pointed at a newer schema. `inspect` reports this state.
|
|
380
|
+
|
|
381
|
+
## Consistent backup set
|
|
382
|
+
|
|
383
|
+
The database backup is not the whole installation. A restorable set is:
|
|
384
|
+
|
|
385
|
+
1. Hub SQLite database: `telemetry.sqlite` (includes registry/admin/alerts).
|
|
386
|
+
Use `ops backup`; do not copy the main file alone while the hub is running.
|
|
387
|
+
2. Enrollment/config state when configured: `HUB_STATE_FILE` (for
|
|
388
|
+
example `hub/enrollment.json`, the import source for previously enrolled
|
|
389
|
+
collectors) and the private hub environment file. These
|
|
390
|
+
contain credentials: protect and copy them only between private locations.
|
|
391
|
+
3. Collector identity/enrollment: `collector/collector.json`.
|
|
392
|
+
4. Collector outboxes: `outbox/<destination-hash>/outbox.sqlite` per hub URL,
|
|
393
|
+
which may contain unacknowledged telemetry. Replay is at-least-once; the hub
|
|
394
|
+
deduplicates by collector/run/sequence.
|
|
395
|
+
5. Optional operational metadata: `install-state.json`, units and the built
|
|
396
|
+
release. Keep the release matching the database schema for rollback.
|
|
397
|
+
|
|
398
|
+
For a consistent set, prefer stopping both services cleanly, then run the online
|
|
399
|
+
database backup and copy the other private files. For an online backup, the SQLite
|
|
400
|
+
copy is internally consistent, but JSON identity/outbox files should be copied in
|
|
401
|
+
a quiescent moment; outbox copies may lag and replay duplicates are harmless.
|
|
402
|
+
|
|
403
|
+
Restore the database with `ops restore`; copy non-database state back separately
|
|
404
|
+
with the same ownership and modes. Never silently copy another installation's private keys, browser credentials or unrelated files.
|
|
405
|
+
|
|
406
|
+
## Upgrade and rollback
|
|
407
|
+
|
|
408
|
+
For an upgrade:
|
|
409
|
+
|
|
410
|
+
1. Package and stage the new release; install `npm ci --omit=dev` there.
|
|
411
|
+
2. Stop the old hub/collector and verify the lock is gone.
|
|
412
|
+
3. Run `install ... --activate --confirm-stopped` (or `activate`).
|
|
413
|
+
4. The installer backs up, migrates and verifies before switching `current`.
|
|
414
|
+
5. Start/enable services explicitly and check health. If the services were
|
|
415
|
+
already installed:
|
|
416
|
+
`systemctl --user restart rigscope-hub.service rigscope-collector.service`.
|
|
417
|
+
|
|
418
|
+
Rollback:
|
|
419
|
+
|
|
420
|
+
```sh
|
|
421
|
+
node dist/ops.cjs rollback \
|
|
422
|
+
--prefix /home/operator/.local/opt/rigscope \
|
|
423
|
+
--state-dir /home/operator/.local/state/rigscope \
|
|
424
|
+
--confirm-stopped
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Rollback is refused while the hub lock exists. If the database schema is newer
|
|
428
|
+
than the previous release's manifest, rollback restores the recorded matching
|
|
429
|
+
pre-upgrade backup (verified against that release's schema) before switching
|
|
430
|
+
`current`. If no matching backup exists, it refuses rather than claiming an old
|
|
431
|
+
binary can read a newer schema. The replaced database is itself backed up first.
|
|
432
|
+
|
|
433
|
+
### Upgrade ordering
|
|
434
|
+
|
|
435
|
+
Within a user installation or this manifest archive layout, hub and collector
|
|
436
|
+
share one release: upgrade the installation together. Stop the hub and
|
|
437
|
+
collector, activate the new release (which migrates and verifies the database),
|
|
438
|
+
then start both services from the same release. Avoid running an old collector
|
|
439
|
+
against a newer hub or vice versa for longer than the restart itself. Do not roll
|
|
440
|
+
a hub back below the schema its database already uses; `rollback` enforces that
|
|
441
|
+
boundary, and collector rollback keeps its private state and outboxes. Process
|
|
442
|
+
detail remains request-scoped and is never persisted or included in the backup
|
|
443
|
+
set. Separate machines and hubs are upgraded independently. System installations
|
|
444
|
+
use the component controls in [System installation](system-installation.md#system-component-lifecycle).
|
|
445
|
+
|
|
446
|
+
On upgrade from the previous collector endpoint, saved `/api/collector/v1/connect`
|
|
447
|
+
URLs normalize to `/api/collector/connect` without changing identity, credentials,
|
|
448
|
+
sharing policy or pending enrollment recovery proofs. The collector recovers the
|
|
449
|
+
old URL's outbox before connecting. If both queue directories exist, it imports
|
|
450
|
+
missing record identities in a transaction before removing the old directory.
|
|
451
|
+
Stored metrics and gaps with the previous `protocolVersion: 2` envelope are
|
|
452
|
+
decoded into the current wire format at the outbox boundary; record identities
|
|
453
|
+
and previously offered gap payloads are preserved. Wire parsers remain strict.
|
|
454
|
+
|
|
455
|
+
## Measurement
|
|
456
|
+
|
|
457
|
+
`ops measure` is a bounded synthetic runner, not a capacity guarantee:
|
|
458
|
+
|
|
459
|
+
```sh
|
|
460
|
+
node dist/ops.cjs measure --machines 2 --batches 30 --records-per-batch 5 \
|
|
461
|
+
--gpus 2 --viewers 2 --json
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
It writes synthetic records through the real `TelemetryStore` into a
|
|
465
|
+
temporary private database and reports accepted/rejected/busy counts, ingestion
|
|
466
|
+
latency, event-loop delay/utilization, RSS, database/WAL size, store queue and
|
|
467
|
+
flush counters, and one history-query latency. The output is labelled synthetic.
|
|
468
|
+
Defaults are intentionally small; upper bounds are 1,000 machines, 2,000 batches,
|
|
469
|
+
32 records per batch and 100,000 records total. It never opens a service socket
|
|
470
|
+
or contacts a hub. `--keep` retains the temporary directory for inspection. The
|
|
471
|
+
library accepts `historyConcurrency` for overlapping History request rounds;
|
|
472
|
+
the CLI exposes it as `--history-concurrency N` (default 1).
|
|
473
|
+
|
|
474
|
+
Current integration notes: storage commits batches of at most 32 records and the
|
|
475
|
+
history query has a 25,000-row/100 ms budget; a 512-record synthetic benchmark
|
|
476
|
+
showed roughly 407 ms transactions. Measure on the actual deployment before
|
|
477
|
+
choosing cadence, retention or viewer counts. No latency or capacity guarantee
|
|
478
|
+
is implied by these development numbers.
|
|
479
|
+
|
|
480
|
+
For sustained concurrent viewers, collector reconnects/replay, slow SSE
|
|
481
|
+
consumers and a fleet beyond 50 machines, use the isolated harness described in
|
|
482
|
+
[scale-validation.md](scale-validation.md). It spawns a temporary loopback hub
|
|
483
|
+
and never contacts the live service.
|
|
484
|
+
|
|
485
|
+
## Verification limits
|
|
486
|
+
|
|
487
|
+
Default repository tests exercise backup/restore, newer-schema refusal, corrupted input,
|
|
488
|
+
lock refusal, installer staging/activation/rollback and failed-upgrade recovery
|
|
489
|
+
in isolated temporary directories. CLI fixture tests additionally cover doctor
|
|
490
|
+
redaction and role separation, inactive and live upgrade validation, paired
|
|
491
|
+
rollback restore/refusal, compatible rollback without data replacement, and
|
|
492
|
+
offline password recovery with lock refusal and audit. They do not start
|
|
493
|
+
services, enable units, touch Tailscale, use real credentials, modify developer
|
|
494
|
+
state, or perform npm network installs; fixture dependency trees stand in for
|
|
495
|
+
production `npm ci`.
|
|
496
|
+
Production visual/render verification and integrated runtime tests are separate.
|
|
497
|
+
The opt-in real-service checks in [releasing](releasing.md#verify-the-exact-archive)
|
|
498
|
+
do install disposable systemd user services and production npm dependencies;
|
|
499
|
+
they remove their test units afterward and use separate state and launchers.
|
|
500
|
+
|
|
501
|
+
Pass `--node /absolute/path/to/node` only when the unit must use a Node 26
|
|
502
|
+
executable different from the one running the installer. The path must be an
|
|
503
|
+
absolute regular file; use the release's `node_modules` installed with
|
|
504
|
+
`npm ci --omit=dev`, never a development-only tree.
|
|
505
|
+
|
|
506
|
+
## Storage budgets and pressure recovery
|
|
507
|
+
|
|
508
|
+
Each Collector Hub connection owns policy filtering, cadence, inventory and its
|
|
509
|
+
durable outbox submission. On restart, recovered metrics are sanitized with the
|
|
510
|
+
current sharing policy before the connection starts; capture-time cadence is not
|
|
511
|
+
reapplied to retained records. Endpoint upgrade recovery and aggregate budgets
|
|
512
|
+
continue to use the existing outboxes. Hub startup restores stored telemetry,
|
|
513
|
+
cadence, inventory and metadata through Sample ingestion while retaining a
|
|
514
|
+
disconnected state until an authenticated Collector reconnects.
|
|
515
|
+
|
|
516
|
+
The default hub main-file plus WAL budget is 2 GiB, shared by every SQLite table.
|
|
517
|
+
The main file has a page-count limit; WAL reserves up to 128 MiB inside that budget.
|
|
518
|
+
Telemetry writes return busy on pressure or SQLITE_FULL, with no receipt/ack for a
|
|
519
|
+
failed transaction. Retention reclaims old raw/one-minute points in bounded chunks
|
|
520
|
+
while preserving the newest hour; hourly rollups retain their configured age window.
|
|
521
|
+
A full newest-hour working set must fit the deployment's budget. Outboxes retry
|
|
522
|
+
while the operator frees space or provisions a larger supported configuration.
|
|
523
|
+
|
|
524
|
+
Collector defaults are 64 MiB logical JSON and 80 MiB physical main+WAL per hub,
|
|
525
|
+
256 MiB logical and 640 MiB physical across eight destinations. Physical pressure
|
|
526
|
+
evicts only pending metrics, records dropped intervals, and protects in-flight
|
|
527
|
+
records. Failed gap writes are held in bounded memory and retried after recovery;
|
|
528
|
+
an abrupt power loss can still lose that in-memory notice.
|
|
529
|
+
|
|
530
|
+
New databases use incremental page reclamation. Existing databases created without
|
|
531
|
+
auto-vacuum may keep allocated pages after retention deletes rows. Startup reports
|
|
532
|
+
pressure and limits growth; it never runs an unbounded VACUUM. Back up the database,
|
|
533
|
+
stop the hub and inspect file/WAL sizes before offline maintenance. These are
|
|
534
|
+
application/SQLite budgets rather than an operating-system filesystem quota. An
|
|
535
|
+
atomic transaction can briefly increase WAL before its post-commit checkpoint;
|
|
536
|
+
blocked checkpoints leave pressure visible and prevent continued ingestion. Keep
|
|
537
|
+
free disk space for backups, SQLite sidecars and release artifacts.
|
|
538
|
+
|
|
539
|
+
Collector state and enrollment file locks now contain an owner PID and instance.
|
|
540
|
+
A proven-dead owner is recovered with inode checks. Legacy empty `.lock` files have
|
|
541
|
+
no owner proof and intentionally require one manual inspection: verify no collector
|
|
542
|
+
or enrollment writer is running before removing that specific abandoned file.
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
Generated user units omit `ProtectKernelModules=yes`: on the target user manager,
|
|
546
|
+
that directive fails before Node starts with `218/CAPABILITIES`. Normal user
|
|
547
|
+
privileges and `NoNewPrivileges=yes` already prevent gaining module-loading
|
|
548
|
+
privileges. PrivateTmp, ProtectSystem=strict, explicit writable paths and the other
|
|
549
|
+
validated user-unit hardening remain enabled. Do not copy root-only hardening into
|
|
550
|
+
user units without starting and stopping an isolated unit on that host.
|