rigscope 0.1.0 → 0.1.2

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.
Files changed (124) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +2 -2
  3. package/.next/build-manifest.json +2 -2
  4. package/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  5. package/.next/server/app/_global-error.html +1 -1
  6. package/.next/server/app/_global-error.rsc +1 -1
  7. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  8. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  10. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  11. package/.next/server/app/_not-found.html +1 -1
  12. package/.next/server/app/_not-found.rsc +2 -2
  13. package/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  14. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  15. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  16. package/.next/server/app/administration/page_client-reference-manifest.js +1 -1
  17. package/.next/server/app/administration.html +1 -1
  18. package/.next/server/app/administration.rsc +2 -2
  19. package/.next/server/app/administration.segments/_full.segment.rsc +2 -2
  20. package/.next/server/app/administration.segments/_tree.segment.rsc +2 -2
  21. package/.next/server/app/administration.segments/administration/__PAGE__.segment.rsc +2 -2
  22. package/.next/server/app/alerts/page_client-reference-manifest.js +1 -1
  23. package/.next/server/app/alerts.html +1 -1
  24. package/.next/server/app/alerts.rsc +2 -2
  25. package/.next/server/app/alerts.segments/_full.segment.rsc +2 -2
  26. package/.next/server/app/alerts.segments/_tree.segment.rsc +2 -2
  27. package/.next/server/app/alerts.segments/alerts/__PAGE__.segment.rsc +2 -2
  28. package/.next/server/app/connections/page_client-reference-manifest.js +1 -1
  29. package/.next/server/app/connections.html +1 -1
  30. package/.next/server/app/connections.rsc +2 -2
  31. package/.next/server/app/connections.segments/_full.segment.rsc +2 -2
  32. package/.next/server/app/connections.segments/_tree.segment.rsc +2 -2
  33. package/.next/server/app/connections.segments/connections/__PAGE__.segment.rsc +2 -2
  34. package/.next/server/app/history/page.js +2 -2
  35. package/.next/server/app/history/page_client-reference-manifest.js +1 -1
  36. package/.next/server/app/history.html +1 -1
  37. package/.next/server/app/history.rsc +5 -5
  38. package/.next/server/app/history.segments/_full.segment.rsc +5 -5
  39. package/.next/server/app/history.segments/_tree.segment.rsc +2 -2
  40. package/.next/server/app/history.segments/history/__PAGE__.segment.rsc +5 -5
  41. package/.next/server/app/index.html +1 -1
  42. package/.next/server/app/index.rsc +2 -2
  43. package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  44. package/.next/server/app/index.segments/_full.segment.rsc +2 -2
  45. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  46. package/.next/server/app/login/page_client-reference-manifest.js +1 -1
  47. package/.next/server/app/login.html +1 -1
  48. package/.next/server/app/login.rsc +2 -2
  49. package/.next/server/app/login.segments/_full.segment.rsc +2 -2
  50. package/.next/server/app/login.segments/_tree.segment.rsc +2 -2
  51. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  52. package/.next/server/app/machines/[machineId]/page.js +1 -1
  53. package/.next/server/app/machines/[machineId]/page_client-reference-manifest.js +1 -1
  54. package/.next/server/app/page_client-reference-manifest.js +1 -1
  55. package/.next/server/app/processes/page_client-reference-manifest.js +1 -1
  56. package/.next/server/app/processes.html +1 -1
  57. package/.next/server/app/processes.rsc +2 -2
  58. package/.next/server/app/processes.segments/_full.segment.rsc +2 -2
  59. package/.next/server/app/processes.segments/_tree.segment.rsc +2 -2
  60. package/.next/server/app/processes.segments/processes/__PAGE__.segment.rsc +2 -2
  61. package/.next/server/app-paths-manifest.json +2 -2
  62. package/.next/server/chunks/168.js +1 -1
  63. package/.next/server/middleware-build-manifest.js +1 -1
  64. package/.next/server/pages/404.html +1 -1
  65. package/.next/server/pages/500.html +1 -1
  66. package/.next/static/chunks/408-4fe7147e38981ee1.js +1 -0
  67. package/.next/static/chunks/app/history/page-22be927a4c3a9c76.js +3 -0
  68. package/.next/static/chunks/app/machines/[machineId]/page-916ee73de5eb067d.js +1 -0
  69. package/.next/static/css/3fbf75e4c471c6a8.css +1 -0
  70. package/CHANGELOG.md +27 -0
  71. package/README.md +53 -136
  72. package/dist/collector.cjs +9 -1
  73. package/dist/hub.cjs +14 -5
  74. package/dist/ops.cjs +8 -4
  75. package/docs/bottlenecks.md +1 -1
  76. package/docs/configuration.md +85 -0
  77. package/docs/development.md +1 -1
  78. package/docs/installation.md +205 -376
  79. package/docs/monitoring.md +112 -0
  80. package/docs/operations.md +103 -68
  81. package/docs/releasing.md +16 -14
  82. package/docs/scale-validation.md +34 -3
  83. package/docs/stress-2026-11-04/180301-probe-m100-u1-s1-20000ms.json +412 -0
  84. package/docs/stress-2026-11-04/180335-probe-m200-u1-s1-20000ms.json +412 -0
  85. package/docs/stress-2026-11-04/180409-probe-m400-u1-s1-20000ms.json +412 -0
  86. package/docs/stress-2026-11-04/180443-probe-m800-u1-s1-20000ms.json +412 -0
  87. package/docs/stress-2026-11-04/180518-probe-m600-u1-s1-20000ms.json +412 -0
  88. package/docs/stress-2026-11-04/180553-probe-m500-u1-s1-20000ms.json +412 -0
  89. package/docs/stress-2026-11-04/180628-probe-m550-u1-s1-20000ms.json +412 -0
  90. package/docs/stress-2026-11-04/180716-probe-m800-u1-s0-20000ms.json +415 -0
  91. package/docs/stress-2026-11-04/180751-probe-m1600-u1-s0-20000ms.json +415 -0
  92. package/docs/stress-2026-11-04/180828-probe-m3200-u1-s0-20000ms.json +416 -0
  93. package/docs/stress-2026-11-04/180941-probe-m2400-u1-s0-20000ms.json +416 -0
  94. package/docs/stress-2026-11-04/181031-probe-m2000-u1-s0-20000ms.json +416 -0
  95. package/docs/stress-2026-11-04/181114-probe-m1800-u1-s0-20000ms.json +416 -0
  96. package/docs/stress-2026-11-04/181203-probe-m100-u64-s64-20000ms.json +418 -0
  97. package/docs/stress-2026-11-04/181304-probe-m200-u64-s64-20000ms.json +418 -0
  98. package/docs/stress-2026-11-04/181405-probe-m400-u64-s64-20000ms.json +418 -0
  99. package/docs/stress-2026-11-04/181507-probe-m500-u64-s64-20000ms.json +418 -0
  100. package/docs/stress-2026-11-04/181609-probe-m450-u64-s64-20000ms.json +418 -0
  101. package/docs/stress-2026-11-04/181845-probe-m2-u2-s2-3000ms.json +419 -0
  102. package/docs/stress-2026-11-04/181931-probe-m500-u64-s64-30000ms.json +420 -0
  103. package/docs/stress-2026-11-04/182108-probe-m1800-u1-s0-120000ms.json +418 -0
  104. package/docs/stress-2026-11-04/182354-probe-m1200-u1-s0-120000ms.json +418 -0
  105. package/docs/stress-2026-11-04/182625-probe-m900-u1-s0-120000ms.json +418 -0
  106. package/docs/stress-2026-11-04/182847-probe-m1050-u1-s0-120000ms.json +418 -0
  107. package/docs/stress-2026-11-04/183112-probe-m1125-u1-s0-120000ms.json +418 -0
  108. package/docs/stress-2026-11-04/193608-probe-m500-u64-s64-120000ms.json +420 -0
  109. package/docs/stress-2026-11-04/193909-probe-m529-u1-s1-15000ms.json +420 -0
  110. package/docs/stress-2026-11-04/193940-probe-m530-u1-s1-15000ms.json +420 -0
  111. package/docs/stress-2026-11-04/194011-probe-m100-u1-s65-10000ms.json +421 -0
  112. package/docs/stress-2026-11-04/README.md +205 -0
  113. package/docs/stress-2026-11-04/index.jsonl +29 -0
  114. package/docs/stress-2026-11-04/manifest.json +13 -0
  115. package/docs/stress-2026-11-04/results.html +22 -0
  116. package/docs/system-installation.md +195 -0
  117. package/package.json +9 -1
  118. package/packaging/system/README.md +1 -1
  119. package/.next/static/chunks/408-18819c6490a5f8d3.js +0 -1
  120. package/.next/static/chunks/app/history/page-3fa5846eca26b7f7.js +0 -3
  121. package/.next/static/chunks/app/machines/[machineId]/page-a5aa1d8676272f38.js +0 -1
  122. package/.next/static/css/e41ccbccc3afaae5.css +0 -1
  123. /package/.next/static/{DZKWF9ur7H5wI0c7RAhdq → npHoP6NSY976Yaye-xi86}/_buildManifest.js +0 -0
  124. /package/.next/static/{DZKWF9ur7H5wI0c7RAhdq → npHoP6NSY976Yaye-xi86}/_ssgManifest.js +0 -0
@@ -1,136 +1,149 @@
1
1
  # Installation
2
2
 
3
- ## Install a release
3
+ Start with [npm installation](#install-from-npm). For a shared dashboard, see
4
+ [remote access](#access-from-another-computer) and [adding machines](#add-machines-and-hubs).
5
+ [Upgrades](#upgrades) and [troubleshooting](#troubleshooting) cover existing installs.
4
6
 
5
- Linux, Node.js 26+ with npm and a working systemd user manager are required for
6
- background installation. Install Node.js before running Rigscope; the user installer
7
- uses the selected Node executable. No global npm installation or source checkout is needed:
7
+ ## Install from npm
8
+
9
+ Requires Linux, Node.js 26+ with npm, and a working systemd user manager. Install
10
+ Node.js first; Rigscope uses that Node executable for its background services.
8
11
 
9
12
  ```sh
10
13
  npx --yes rigscope@latest install --boot
11
- ~/.local/bin/rigscope
12
14
  ```
13
15
 
14
- If the npm release is not available yet, use [Install from an archive](#install-from-an-archive).
16
+ Save the generated `owner` password and open the printed URL, normally
17
+ `http://127.0.0.1:8081`. The password is shown only when the account is first
18
+ created. An existing installation keeps its account and password.
15
19
 
16
- Save the generated `owner` password. Open the printed dashboard URL. The installer
17
- starts a verified background service and returns to the shell. Closing the terminal
18
- does not stop it. The service restarts after crashes. `--boot` runs
19
- `loginctl enable-linger` for the current user so startup does not require a login;
20
- if host authorization prevents it, the installer reports the exact recovery command.
21
- Omit `--boot` to start at login only. `status` reports the actual startup setting.
20
+ The installer starts a hub and a collector in the background. Closing the
21
+ terminal does not stop them. `--boot` enables startup at boot, including before
22
+ login. If the host requires authorization, the installer prints the recovery
23
+ command. Omit `--boot` to start at login instead.
22
24
 
23
- `--no-start` leaves a new installation stopped, and `--no-enable` disables login
24
- startup. Repeating `install` repairs registration/launcher and startup settings
25
- without replacing the runtime or credentials; use `rigscope upgrade` to change code.
26
- Re-registration with `--no-start` leaves an already-running service running.
25
+ Add `~/.local/bin` to PATH, or run `~/.local/bin/rigscope` directly. No global npm
26
+ install or source checkout is needed. The launcher and services use the installed
27
+ runtime, so removing the npx cache does not break them.
27
28
 
28
- | Goal | Install options | Runs |
29
- | --- | --- | --- |
30
- | Monitor this computer | `install --boot` | Background hub and local collector |
31
- | Connect to a hub | `install --role collector --boot` | Collector after enrollment |
32
- | Host and monitor through HTTPS | `install --origin https://hub.example.com --boot` | Background hub and colocated collector |
33
- | Dedicated remote dashboard | `install --role hub --origin https://hub.example.com --boot` | Hub without collection |
34
- | Foreground evaluation | `try` | Isolated hub and collector on port 8082 |
35
-
36
- Add `~/.local/bin` to PATH if necessary. The generated command is a small launcher
37
- that pins the installation's Node executable, state directory and stable managed
38
- runtime path. It survives deletion of an npx cache or the original source checkout.
39
- The service uses the same Node and runtime. An unrelated command at the destination
40
- is preserved and the installer prints the usable absolute command path instead.
41
- An owned symlink into the checkout used for installation is replaced by the managed
42
- launcher. `install --from /path/release.tgz` can also stage a supplied archive.
29
+ Releases are on [npm](https://www.npmjs.com/package/rigscope). `@latest` selects
30
+ the current stable release; replace it with `@0.1.0` to select that exact version.
31
+
32
+ ### Installation options
33
+
34
+ Append these options to `npx --yes rigscope@latest install`:
35
+
36
+ | Goal | Options |
37
+ | --- | --- |
38
+ | Monitor this computer | `--boot` |
39
+ | Send readings to another hub | `--role collector --boot` |
40
+ | Host a dashboard over HTTPS and monitor this computer | `--origin https://hub.example.com --boot` |
41
+ | Host a dashboard without collecting local readings | `--role hub --origin https://hub.example.com --boot` |
42
+ | Use another local port | `--port 8086 --boot` |
43
+ | Leave a new installation stopped | `--no-start` |
44
+ | Disable startup at login | `--no-enable` |
45
+
46
+ Repeating `install` repairs the services, launcher and startup settings. It keeps
47
+ the existing runtime and credentials; use `rigscope upgrade` to update the code.
48
+ `--no-start` does not stop a service that is already running.
43
49
 
44
50
  ### Install from an archive
45
51
 
46
- For testing before npm publication, or for a downloaded release, run from the
47
- directory containing the archive or supply its absolute path:
52
+ For a downloaded package or one built from source, run from the directory
53
+ containing the archive, or give its absolute path:
48
54
 
49
55
  ```sh
50
56
  npx --yes --package ./rigscope-0.1.0.tgz rigscope install --boot
51
57
  ```
52
58
 
53
- The archive contains the built application. npm still needs access to its registry
54
- or a populated cache to install production dependencies. A `.tgz` alone is not a
55
- complete offline installation. All role, origin and startup options below also
56
- work with the archive command.
59
+ The same installation options apply. npm still needs registry access or cached
60
+ production dependencies; the archive alone is not a complete offline installer.
57
61
 
58
62
  ## Everyday commands and installation selection
59
63
 
60
- Bare `rigscope` shows status and never initializes state or starts a trial.
61
- `start` is idempotent. `status` includes scope, role, startup, PID, CLI/runtime
62
- versions, and live hub health/version when a user service is active. `logs` shows
63
- 100 journal lines; `logs --follow` follows new entries.
64
+ Run only the command for the task you want:
64
65
 
65
- ```sh
66
- rigscope
67
- rigscope start
68
- rigscope stop
69
- rigscope logs --follow
70
- rigscope upgrade
71
- rigscope uninstall
72
- ```
66
+ | Task | Command |
67
+ | --- | --- |
68
+ | Check services, versions and the dashboard URL | `rigscope status` (or just `rigscope`) |
69
+ | Start or stop | `rigscope start` / `rigscope stop` |
70
+ | Restart the hub | `rigscope restart hub` |
71
+ | Stop local collection | `rigscope stop collector` |
72
+ | Follow logs | `rigscope logs --follow` |
73
+ | Check configuration, services and sensor access | `rigscope doctor` |
74
+ | Remove services and the managed runtime | `rigscope uninstall` |
73
75
 
74
- `uninstall` removes both user services, their matching launcher and installed runtime
75
- copies, preserving accounts, history, identity, queues and backups. Reinstall
76
- using npm or an archive to restore the application with retained settings. No data purge is implicit.
76
+ `start` is safe to repeat. `logs` shows the last 100 journal lines by default.
77
+ `enable` and `disable` control the hub and collector independently; the initial
78
+ role is a preset. Use `rigscope enable collector` to add local collection to a
79
+ hub-only installation.
80
+
81
+ `uninstall` keeps accounts, history, identity, pending samples and backups.
82
+ Reinstalling reuses that data, including the existing password.
77
83
 
78
84
  ## Access from another computer
79
85
 
80
- For a new installation, set the browser-visible HTTPS origin at install time:
86
+ Run the commands on the hub machine. The examples use Tailscale already signed
87
+ in, with HTTPS enabled. Replace `machine.example.ts.net` with the hub's Tailscale
88
+ DNS name. Choose the section for a new or existing installation.
89
+
90
+ ### New HTTPS installation
81
91
 
82
92
  ```sh
83
93
  npx --yes rigscope@latest install \
84
94
  --origin https://machine.example.ts.net:8081 --boot
95
+ tailscale serve --bg --tls-terminated-tcp=8081 \
96
+ "unix:$HOME/.local/state/rigscope/run/hub.sock"
85
97
  ```
86
98
 
87
- The default `local` role means a colocated hub and collector. It supports either
88
- localhost or HTTPS access. Its collector uses the configured HTTPS endpoint, with
89
- normal certificate validation and its existing machine credential. No second
90
- collector or grant is needed. Use `--role hub` for an initial dashboard without
91
- collection, then `rigscope enable collector` to add collection later.
92
- `enable` and `disable` control each component independently; `start`, `stop`,
93
- `restart` and `logs` accept `hub` or `collector`.
94
- For a hub-first setup, install `--role hub`, then enroll a separate collector using **Add machine**.
99
+ ### Convert a retained localhost installation
95
100
 
96
- Run the HTTPS proxy on the hub machine. With Tailscale already configured, preserve
97
- other Serve routes and use TLS-terminated TCP forwarding to preserve Rigscope's
98
- exact Host/Origin boundary:
101
+ If you already installed for localhost, change access without reinstalling:
99
102
 
100
103
  ```sh
104
+ rigscope stop
105
+ rigscope configure --origin https://machine.example.ts.net:8081
101
106
  tailscale serve --bg --tls-terminated-tcp=8081 \
102
107
  "unix:$HOME/.local/state/rigscope/run/hub.sock"
108
+ rigscope start
103
109
  ```
104
110
 
105
- Use the actual socket printed by the installer if selecting another state directory.
106
- Open the configured HTTPS origin from a computer permitted to reach the hub through
107
- Tailscale. The viewing computer needs no Rigscope installation unless it should
108
- also be monitored. The background proxy and Rigscope service continue after closing
109
- the terminal.
111
+ This keeps accounts, history and collector credentials. It updates the local
112
+ collector's destination and moves its pending samples. Both services must be
113
+ stopped during conversion. See [Access changes](operations.md#access-changes)
114
+ for backup and queue checks.
110
115
 
111
- ### Convert a retained localhost installation
116
+ ### Open and check the dashboard
117
+
118
+ Open `https://machine.example.ts.net:8081/` from a device allowed to reach the
119
+ hub through Tailscale. Sign in with the existing account or the password printed
120
+ at first installation. The viewing device needs no Rigscope installation.
121
+
122
+ ```sh
123
+ rigscope status
124
+ tailscale serve status
125
+ ```
126
+
127
+ The forwarding command changes only port 8081 and keeps other Serve routes.
128
+ Use the socket path printed by Rigscope if you chose another state directory.
129
+ `--bg` keeps the route active after the terminal closes and across reboots.
130
+
131
+ Use TLS-terminated TCP forwarding to preserve the request's Host header,
132
+ including its port. See the [Tailscale Serve reference](https://tailscale.com/docs/reference/tailscale-cli/serve).
133
+ Remote mode listens on a private Unix socket instead of a plaintext TCP port;
134
+ collectors connect through HTTPS with certificate validation.
112
135
 
113
- `uninstall` removes services, the command and runtime copies, while preserving
114
- configuration, accounts, history, identity and queues. A reinstall with different role or
115
- origin settings therefore refuses rather than silently resetting that state.
116
- Change access explicitly instead:
136
+ ### Return to localhost
117
137
 
118
138
  ```sh
119
139
  rigscope stop
120
- rigscope configure --origin https://machine.example.ts.net:8081
140
+ rigscope configure --local
141
+ tailscale serve --bg --tls-terminated-tcp=8081 off
121
142
  rigscope start
122
143
  ```
123
144
 
124
- `configure` requires a stopped hub and also a stopped collector when its colocated
125
- destination changes. It validates the new origin/socket, backs up the
126
- previous private settings, and updates the colocated collector's matching destination.
127
- It moves that destination's entire outbox, including SQLite WAL, without changing
128
- credentials or other hubs. An existing target outbox refuses conversion to avoid
129
- merging or discarding pending records. Accounts and the history database are untouched.
130
- Run `configure --local` while stopped to return to localhost. Rollback targets must declare support for the saved configuration and database schema.
131
-
132
- If already uninstalled, configure retained state through the package entry point,
133
- then reinstall the full application:
145
+ If you already uninstalled, change retained settings through the package entry
146
+ point, then reinstall:
134
147
 
135
148
  ```sh
136
149
  npx --yes rigscope@latest configure \
@@ -138,340 +151,156 @@ npx --yes rigscope@latest configure \
138
151
  npx --yes rigscope@latest install --boot
139
152
  ```
140
153
 
141
- Before npm publication, substitute the archive entry point shown above.
142
- Users, history and identity remain intact when restoring the launcher/services.
143
-
144
154
  ## Add machines and hubs
145
155
 
146
- 1. Install the collector role on the new machine. It stays stopped until enrolled.
147
- 2. On the hub choose **Add machine**, then **New machine** and create a connection
148
- grant. Grants are single-use and expire within 15 minutes.
149
- 3. Run the displayed `rigscope connect https://hub.example.com` command on the new
150
- machine. Paste the grant at its private prompt.
151
- 4. The installed collector starts in the background after successful enrollment.
152
- Use `--no-start` to enroll without starting.
153
-
154
- On the collector machine:
156
+ 1. On the hub, choose **Add machine**, then **New machine**. Create a connection
157
+ grant; it can be used once and expires within 15 minutes.
158
+ 2. On the machine to monitor, run:
155
159
 
156
- ```sh
157
- npx --yes rigscope@latest install --role collector --boot
158
- ~/.local/bin/rigscope connect https://hub.example.com
159
- ```
160
+ ```sh
161
+ npx --yes rigscope@latest install --role collector --boot
162
+ ~/.local/bin/rigscope connect https://hub.example.com
163
+ ```
160
164
 
161
- Stop a running collector before changing destinations. Replacement uses a grant
162
- explicitly bound to the existing machine and `connect --replace`.
163
- For unattended enrollment, put the grant in an owned private regular file and use
164
- `--token-file /private/path`. It is never accepted as a command-line token. Delete
165
- the file after use. Generated commands contain no grants, and clipboard contents
166
- remain under the user's control.
165
+ 3. Paste the grant at the private prompt. The collector starts after enrollment.
166
+ Use `connect --no-start` to enroll without starting it.
167
167
 
168
- Collectors connect outbound: no incoming collector port and no root collector are
169
- needed. Each collector samples once and reports independently to up to eight hubs.
170
- Retry queues persist across restart. CPU, memory, swap, GPU, disk, network rates and
171
- on-demand processes are shared by default. Network addresses and full process
172
- arguments are disabled. Per-hub sharing settings are in `collector/state.json`;
173
- edit while stopped. Existing destinations keep their policies.
168
+ Collectors connect outbound and need no incoming port or root access. Each can
169
+ send to up to eight hubs. Sharing is separate for each hub; network addresses
170
+ and full process arguments start disabled. See [Collection and sharing](monitoring.md#collection-and-sharing).
174
171
 
175
- A hub has no fixed machine-count limit. Its concurrent connection budget defaults
176
- to 100, configurable with `maxCollectorConnections` in private user `config.json`
177
- or `HUB_MAX_COLLECTOR_CONNECTIONS` for raw/system hub services. Restart after edits.
172
+ Stop a running collector before changing its destinations. To replace an
173
+ existing machine credential, create a grant bound to that machine and use
174
+ `connect --replace`. For unattended enrollment, use `--token-file` with an owned
175
+ private file and delete it afterward; do not put the grant on the command line.
178
176
 
179
177
  ## Explicit foreground trial
180
178
 
181
179
  ```sh
182
- rigscope try
183
- # Ctrl+C stops the trial hub and collector.
180
+ npx --yes rigscope@latest try
184
181
  ```
185
182
 
186
- The default trial uses a separate `~/.local/state/rigscope-trial` directory and
187
- port 8082. Trial credentials/history persist. `try --state-dir PATH --port PORT`
188
- selects another trial. A managed runtime directory cannot be used for `try`.
189
- `start --foreground` intentionally runs an existing installation in the terminal;
190
- stop its background service first. It does not install a systemd service.
183
+ Ctrl+C stops the trial. It uses separate data at `~/.local/state/rigscope-trial`
184
+ and port 8082. Trial accounts and history persist. Use `try --state-dir PATH
185
+ --port PORT` to choose another trial directory and port.
191
186
 
192
- From source, prepare an archive with `npm ci` then `npm run package:npm`.
193
- End users run the built package; they do not need a source build or checkout deployment command.
187
+ To run an existing installation in the terminal, stop its background service
188
+ first, then use `rigscope start --foreground`. This does not install services.
189
+ A managed runtime directory cannot be used for `try`.
194
190
 
195
191
  ## Hub configuration
196
192
 
197
- `rigscope config` prints the owned 0600 `config.json` path. `--state-dir PATH` or
198
- `RIGSCOPE_STATE_DIR` selects another installation; directories must be private (0700).
199
- Each installation has separate hashed hub and collector service names. The installed alias defaults to
200
- the state directory it belongs to. Settings include the initial role preset, independent component enablement, local port, remote origin,
201
- socket, bootstrap users and local collector mapping. Restart after edits. Managed hub
202
- users become authoritative in SQLite after the first start; editing bootstrap password
203
- hashes later does not change existing accounts. Use Administration for user changes.
204
-
205
- A new hub prints an `owner` password once and stores only a salted scrypt hash. Save
206
- that password. Local trial mode always listens on loopback and still requires login.
207
- The trial persists real samples and identity; restarting it reuses the same credentials.
208
-
209
- For a remote hub, forward the exact configured HTTPS origin to its private Unix socket,
210
- for example with Tailscale Serve or a TLS reverse proxy running as the same user.
211
- Configure the proxy separately and keep the socket private. The hub opens no plaintext
212
- TCP listener in this mode; remote collectors use normal certificate-validated WSS.
213
- Do not turn off TLS verification or expose the local trial listener to a LAN.
214
- See the [HTTPS boundary](development.md#https-boundary) for proxy requirements.
193
+ `rigscope config` prints the private `config.json` path. The installed launcher
194
+ selects its own state directory. `--state-dir PATH` or `RIGSCOPE_STATE_DIR`
195
+ selects another installation, with separate data and service names.
196
+
197
+ Settings include component enablement, port, HTTPS origin and socket. Keep state
198
+ directories at mode `0700` and configuration files at `0600`. Restart after edits.
199
+ Use `configure` for access changes and **Administration** for users: editing
200
+ first-run password hashes does not change an account already stored in SQLite.
201
+
202
+ There is no fixed machine-count limit. The default connection limit is 100.
203
+ Set `maxCollectorConnections` in private `config.json` and restart to change it.
204
+ For direct hub/collector services, see the [environment reference](configuration.md).
205
+ For another HTTPS proxy, see the [proxy requirements](development.md#https-boundary).
215
206
 
216
207
  ## Upgrades
217
208
 
218
- Use the installed command to upgrade the managed runtime and preserve its data:
209
+ Use the installed command:
219
210
 
220
211
  ```sh
221
- rigscope upgrade # latest published npm release
222
- rigscope upgrade --from rigscope@0.1.0 # select an exact published version
223
- rigscope upgrade --from ./rigscope-VERSION.tgz # select a local archive
224
- rigscope rollback # return to the retained previous runtime
212
+ rigscope upgrade
225
213
  ```
226
214
 
227
- Run only the command for the desired operation. A fresh installation has no
228
- previous runtime to roll back to. Updating a global npm package does not update
229
- the runtime managed by `rigscope install`.
230
-
231
- `rigscope doctor` checks the installation's runtime, private configuration,
232
- service, database, listener, TLS destinations and sensor access. `--json` produces
233
- redacted structured output. Checks follow component enablement: a hub does not need
234
- an enabled collector.
235
-
236
- `rigscope upgrade --from ./rigscope-VERSION.tgz` stages while active components
237
- run, then stops them, verifies runtime leases and preserves a consistent database
238
- backup paired with the old runtime. After activation it checks the running hub's
239
- embedded version, database schema/integrity and, for active collectors, a fresh
240
- sampling marker from the collector process. `--timeout SECONDS` bounds activation
241
- health verification. A failed activation stops the attempted runtime before restoring
242
- the previous code and, when needed, its matching database copy. Recovery is verified
243
- before it is called healthy; an unresolved recovery error is reported explicitly.
244
- Only components running before the upgrade are restarted. Startup settings are
245
- preserved independently. Inactive components stay inactive.
246
-
247
- `rigscope rollback` uses `runtime-previous` and `release-state.json`. Compatible
248
- current databases retain post-upgrade data. An incompatible schema needs the paired
249
- pre-upgrade backup (or an explicit compatible `--backup PATH`); the replaced database
250
- is backed up first. Missing pairings fail closed. Do not manually move runtimes or
251
- run old code against newer schemas. Keep separate off-machine backups.
252
-
253
- For a lost owner password, stop the installation and use
254
- `rigscope recover-password --user owner`. Entry is private and confirmed twice;
255
- noninteractive use requires `--password-file` naming an owned private regular file.
256
- Recovery changes the durable managed user, records an audit event and invalidation
257
- marker, and leaves bootstrap configuration, machine access and collector credentials
258
- intact. It refuses a live database lease and does not create or elevate users.
259
- The stopped hub's in-memory sessions are gone; restart and use the new password.
260
-
261
- Without `--from`, upgrade requests `rigscope@latest`. Before the first npm
262
- publication, use `--from` with a local archive.
215
+ It gets `rigscope@latest` from npm, backs up the hub database and replaces the
216
+ managed runtime. Accounts, history and collector settings are retained. Only
217
+ components that were running are restarted; startup settings stay the same.
263
218
 
264
- ## Hardware
219
+ | Alternative | Command |
220
+ | --- | --- |
221
+ | Select an exact published version | `rigscope upgrade --from rigscope@0.1.0` |
222
+ | Install a local archive | `rigscope upgrade --from ./rigscope-VERSION.tgz` |
223
+ | Return to the retained previous runtime | `rigscope rollback` |
265
224
 
266
- Linux is the supported collection platform. CPU/memory/process counters use procfs,
267
- not CPU-vendor-specific tools. ARM/RISC-V CPU naming recognizes their common fields;
268
- CPU utilization continues to use per-core procfs counters.
225
+ A fresh installation has no previous runtime to roll back to. Updating a global
226
+ npm package does not update this runtime. Do not move runtime directories or run
227
+ old code against a newer database. See [Upgrade and rollback checks](operations.md#managed-cli-operations)
228
+ for health checks, failure recovery, database compatibility and backup selection.
229
+ Keep separate backups outside the machine.
269
230
 
270
- | Hardware | Available readings | Limit |
271
- | --- | --- | --- |
272
- | NVIDIA | Utilization, dedicated memory, temperature, power; compute-process memory | Requires `nvidia-smi`; existing asynchronous bounded polling |
273
- | AMD discrete GPU | Busy percentage, dedicated VRAM, temperature, power | Requires readable amdgpu sysfs/hwmon counters |
274
- | AMD integrated GPU | Busy percentage and available hardware sensors | Driver-reported VRAM only; no synthesized shared-memory totals |
275
- | Intel discrete or integrated GPU | Available hwmon temperature/power; optional driver-exposed busy/VRAM counters | No general Intel utilization/engine backend yet; most Intel utilization remains unavailable |
276
- | ASPEED/other display adapters | Inventory | No telemetry backend |
231
+ ## Troubleshooting
277
232
 
278
- On AMD APUs the reported power counter can include CPU/SoC power; it is not a
279
- GPU-exclusive power measurement.
233
+ ### No password was printed
280
234
 
281
- Every field is optional. Drivers, permissions and kernel versions determine what can
282
- be read. An adapter with no readable counters remains unsupported; missing readings
283
- never become successful zeros. Intel sensor presence does not imply utilization or
284
- per-process GPU accounting support. Hotplug uses the existing inventory refresh.
285
- AMD/Intel adapters retain PCI-based IDs, while NVIDIA retains its UUID-based IDs.
235
+ The `owner` password appears only when the account is created. Reinstalling with
236
+ saved settings keeps the old password. If you lost it, stop the installation
237
+ and reset it at a private prompt:
286
238
 
287
- AMD uses the kernel's [amdgpu sysfs and hwmon interfaces](https://docs.kernel.org/gpu/amdgpu/thermal.html).
288
- The Radeon 860M iGPU and RTX 5060 Laptop GPU have now been checked on the actual
289
- laptop, including fresh iGPU utilization, driver-reported memory, temperature and
290
- power samples persisted by the hub. The Ubuntu RTX 3090 rig remains validated. Intel
291
- sensor and ARM/RISC-V naming paths have fixture coverage and still need physical
292
- validation. macOS, Windows, Apple GPU telemetry and a
293
- complete Intel GPU utilization backend are not included in this release pass.
294
-
295
-
296
- ## System installation
297
-
298
- The optional system scope uses dedicated unprivileged accounts and starts at boot without user lingering. Review its plan before applying changes. Mutations require root and `--apply`; without `--apply` they print the proposed changes. The installed `rigscope system` command uses the same implementation as `dist/system.cjs`.
299
-
300
- ### Scope and generated layout
301
-
302
- ```text
303
- /opt/rigscope/ root:root 0755
304
- releases/<version>/ immutable root-owned release
305
- current -> releases/<version>
306
- previous -> releases/<previous> retained for rollback
307
- node/node root-owned Node 26 when the selected binary was not root-owned
308
- /etc/rigscope/
309
- hub.env root:root 0600 (credentials, never printed)
310
- collector.env root:root 0600
311
- /var/lib/rigscope/
312
- hub/telemetry.sqlite rigscope-hub 0600, private 0700 directory
313
- hub/enrollment.json rigscope-hub 0600
314
- hub/run/hub.sock private Unix socket (remote mode)
315
- collector/state.json rigscope-collector 0600
316
- collector/outbox/ durable collector outboxes
317
- backups/ root:root 0700, pre-upgrade/pre-rollback SQLite copies
318
- system-install.json root:root 0600, version 2 component state/versions/backups/adoption
319
- power-access.json root:root 0600, original counter modes for reversal
320
- /etc/systemd/system/rigscope-hub.service root:root 0644, hub boot unit
321
- /etc/systemd/system/rigscope-collector.service root:root 0644, collector boot unit
322
- /etc/sysusers.d/rigscope.conf root:root 0644, both nologin accounts
323
- /etc/sysusers.d/rigscope-rapl.conf root:root 0644, collector-only power membership
324
- /etc/udev/rules.d/90-rigscope-rapl.rules root:root 0644
239
+ ```sh
240
+ rigscope stop
241
+ rigscope recover-password --user owner
242
+ rigscope start
325
243
  ```
326
244
 
327
- Build the checkout before using `dist/system.cjs`; an installed package exposes the same commands through `rigscope system`. Reference copies are in `packaging/system/`. They are for review only; the
328
- renderer in `src/cli/system.ts` is authoritative.
329
-
330
- `systemd-sysusers` creates `rigscope-hub` and `rigscope-collector` as nologin
331
- system accounts even when one component is disabled, so the other can be
332
- enabled later without reinstalling. The hub and collector never run as root.
333
- The units set `NoNewPrivileges=yes`, `ProtectSystem=strict`,
334
- `ProtectHome=yes`, an empty `CapabilityBoundingSet=`/`AmbientCapabilities=`,
335
- `UMask=0077`, explicit writable state paths and a read-only release tree. The
336
- collector uses `--await-connection` to exit cleanly when no destinations are
337
- configured, including after an interrupted enrollment. The
338
- collector does **not** use `PrivateDevices=yes` because GPU telemetry still
339
- needs real device nodes. The hub does.
245
+ Recovery keeps history and collector credentials. Sign in again afterward.
246
+ It changes an existing account; it does not create a missing user or grant
247
+ administrator access. See [Password recovery](operations.md#password-recovery).
340
248
 
341
- ### System component lifecycle
249
+ ### An old command opens, or uninstall is unknown
342
250
 
343
- All mutating commands require `--apply` and root. Without `--apply`, the exact
344
- files and command sequence are printed and nothing is written. Every component
345
- operation touches only its own unit; enabling or starting one component never
346
- stops or restarts the other.
251
+ If installation prints `Keeping existing command at …`, another launcher already
252
+ occupies that path. The installer leaves it intact and prints a usable `Command:`
253
+ path for the new CLI. Use that path, or invoke the published CLI directly:
347
254
 
348
255
  ```sh
349
- # Package first (from a built checkout).
350
- node scripts/package-release.cjs --output /var/tmp/rigscope-<version>.tar.gz
351
-
352
- # Review a release before granting sudo.
353
- node dist/system.cjs plan \
354
- --source /var/tmp/rigscope-<version>.tar.gz --role local --node /usr/bin/node
355
-
356
- # Install one complete package. --role selects the initial enabled preset.
357
- sudo node dist/system.cjs install \
358
- --source /var/tmp/rigscope-<version>.tar.gz --role hub \
359
- --node /usr/bin/node --install-deps --enable --apply
360
-
361
- # Add the other component later; no reinstall and no new package are needed.
362
- sudo node dist/system.cjs enable collector --apply
363
- sudo node dist/system.cjs enable hub --apply
364
-
365
- # Component-specific lifecycle when both exist.
366
- sudo node dist/system.cjs disable collector --apply
367
- sudo node dist/system.cjs restart hub --apply
368
- sudo node dist/system.cjs restart collector --apply
369
- sudo node dist/system.cjs restart --apply # enabled components only
370
-
371
- # Component-specific status and logs.
372
- node dist/system.cjs status
373
- node dist/system.cjs status collector --json
374
- node dist/system.cjs logs hub --follow
256
+ npx --yes rigscope@latest status
257
+ npx --yes rigscope@latest uninstall
375
258
  ```
376
259
 
377
- `install` stages a complete release, verifies both runtimes and UI artifacts,
378
- copies a non-root-owned Node executable into the root-owned prefix, installs
379
- production dependencies when `--install-deps` is given, writes private
380
- configuration and both units, creates both accounts, then switches `current`.
381
- Staging happens before any service is stopped.
382
-
383
- - With `--enable`, `--role local` initially enables both components.
384
- - With `--enable`, `--role hub` initially enables only the hub.
385
- - With `--enable`, `--role collector` initially enables only the collector.
386
- - Without `--enable`, both components are installed but disabled.
387
- - `--start` starts only the requested preset and verifies those components.
388
- - `--without-power` skips the collector RAPL grant at that mutation.
389
-
390
- `enable hub` creates the owner account once when `HUB_BROWSER_USERS` is empty
391
- and prints the password only in that mutation. It is never stored in plaintext
392
- or printed again. `enable collector` completes the collector account, unit,
393
- identity and RAPL grant. With no destination it tries the colocated hub:
394
-
395
- - A live configured hub gets a short-lived, single-use grant in its
396
- authoritative SQLite registry. The collector then enrolls through the normal
397
- hub API, which updates the live registry without stopping or restarting the
398
- hub.
399
- - A stopped hub gets the identity written to the authoritative registry (or a
400
- static `HUB_COLLECTORS` bootstrap when the registry is not initialized yet);
401
- enabling the collector never starts the hub.
402
- - If there is no configured hub, the collector is enabled but stays dormant and
403
- reports `Awaiting connection`. Its unit uses `--await-connection` to exit
404
- cleanly before collection until a destination is saved.
405
-
406
- Configured remote destinations and credentials are never overwritten. Re-running
407
- `enable collector` leaves its destination, token, identity and outboxes intact.
408
-
409
- ### Connecting to an independent hub
410
-
411
- For a hub-first test where the hub and collector are separate installations,
412
- create a connection grant in the hub's admin Collectors panel. Save the grant to
413
- a private file and connect the system collector:
260
+ Choose the operation you need; `uninstall` removes this installation and retains
261
+ its data. Use `ls -l ~/.local/bin/rigscope` to check for a link to an older
262
+ checkout. Back up a confirmed old launcher before removing it, then repeat
263
+ `install` to create the new launcher. Older services with other names may need
264
+ separate cleanup; do not stop unrelated services.
414
265
 
415
- ```sh
416
- # On the collector host; the grant file must be root-owned and 0600.
417
- sudo install -m 0600 /dev/null /root/collector-grant
418
- sudoedit /root/collector-grant # paste the single-use grant, save, quit
419
- sudo node dist/system.cjs connect https://<hub-host> \
420
- --token-file /root/collector-grant --apply
421
- sudo rm /root/collector-grant
422
- ```
266
+ ### The hub keeps restarting
423
267
 
424
- `connect` stops only the collector while it enrolls, calls the hub's normal
425
- enrollment API, persists the issued credential under
426
- `/var/lib/rigscope/collector/state.json`, and starts the collector if it is
427
- enabled. The grant is never printed. Re-running `connect` on a configured
428
- collector is refused rather than replacing a remote destination.
268
+ Check `rigscope logs hub` and `rigscope doctor`. If port 8081 is already in use,
269
+ identify the listener before stopping anything. For a fresh install, choose an
270
+ unused port with `install --port 8086 --boot`, or use HTTPS mode with a private
271
+ socket. An existing installation refuses a different `--port` during reinstall;
272
+ reinstalling alone does not reset its settings.
429
273
 
430
- Status reports each component independently:
274
+ ## Hardware
431
275
 
432
- ```text
433
- Components:
434
- hub: installed, enabled, active, ready
435
- collector: installed, enabled, active, ready, 1 destination(s)
436
- ```
276
+ Collection supports Linux. CPU, memory and process readings come from procfs.
277
+ ARM and RISC-V CPU names are recognized; utilization uses per-core counters.
278
+
279
+ | Hardware | Available readings | Limit |
280
+ | --- | --- | --- |
281
+ | NVIDIA | Utilization, dedicated memory, temperature, power; compute-process memory | Requires `nvidia-smi` |
282
+ | AMD discrete GPU | Busy percentage, dedicated VRAM, temperature, power | Requires readable amdgpu sysfs/hwmon counters |
283
+ | AMD integrated GPU | Busy percentage and available hardware sensors | Reports only driver-provided VRAM; does not estimate shared memory |
284
+ | Intel discrete or integrated GPU | Available hwmon temperature/power and optional driver counters | Partial support; most utilization readings remain unavailable |
285
+ | ASPEED/other display adapters | Inventory | No telemetry backend |
286
+
287
+ On AMD APUs the reported power counter can include CPU/SoC power; it is not a
288
+ GPU-exclusive power measurement.
437
289
 
438
- `readiness` is `ready`, `stopped`, `unconfigured`, `awaiting-connection`,
439
- `invalid-config`, `invalid-state` or `missing`.
290
+ Drivers, permissions and kernel versions determine which readings are available.
291
+ Missing readings never become zeros. Intel temperature or power support does not
292
+ imply utilization or per-process GPU memory support. Inventory refresh detects
293
+ hotplug changes. AMD/Intel adapters use PCI-based IDs; NVIDIA uses GPU UUIDs.
440
294
 
441
- ### CPU package power
295
+ AMD uses the kernel's [amdgpu sysfs and hwmon interfaces](https://docs.kernel.org/gpu/amdgpu/thermal.html).
296
+ Physical checks cover an Ubuntu RTX 3090 rig and a laptop with an RTX 5060 and
297
+ Radeon 860M, including iGPU utilization, memory, temperature and power stored by
298
+ the hub. Intel sensors and ARM/RISC-V naming have fixture tests but still need
299
+ physical validation. macOS, Windows and Apple GPU collection are not supported.
442
300
 
443
- `collector/sampling/hwmon.ts` already reads top-level RAPL package counters,
444
- sums multiple sockets, handles wrap/reset and returns unavailable rather than
445
- zero. On hosts where `energy_uj` is root-only, system scope grants a narrow
446
- read path instead of elevating Node.
447
301
 
448
- ```sh
449
- node dist/system.cjs power status
450
- sudo node dist/system.cjs power grant --apply
451
- sudo node dist/system.cjs power revoke --apply
452
- ```
302
+ ## System installation
453
303
 
454
- Mechanism:
455
-
456
- - `/etc/sysusers.d/rigscope-rapl.conf` creates `rigscope-rapl` and adds only
457
- `rigscope-collector`; the hub is not a member.
458
- - A `powercap` udev rule matches only top-level `intel-rapl:N` devices named
459
- `package*` and changes only `energy_uj` and `max_energy_range_uj` to
460
- `0440 root:rigscope-rapl`. Subdomains, constraint files and power-limit
461
- writes are untouched.
462
- - `udevadm trigger --subsystem-match=powercap --action=change` applies the rule
463
- immediately. Because the rule lives in `/etc/udev/rules.d`, device
464
- recreation and boot reapply it.
465
- - The collector unit adds `SupplementaryGroups=rigscope-rapl`; it does not use
466
- file capabilities, ambient capabilities or a privileged Node helper.
467
- - Grant records each existing counter's original mode/uid/gid in
468
- `/var/lib/rigscope/power-access.json`. Revoke removes the rule and group
469
- membership and restores those recorded values (defaults `0400` for
470
- `energy_uj` and `0444` for `max_energy_range_uj` when no record exists).
471
- - `power status` reports driver modules, package domains, collector
472
- readability, persistence, world readability and every problem. A missing
473
- counter is reported unavailable, never as zero watts.
474
-
475
- Verify real watts in History after granting access and restarting the collector;
476
- do not treat a mocked value or a one-time manual `chmod` as installation
477
- evidence. Unsupported hardware remains unavailable.
304
+ For dedicated service accounts, system units and CPU package-power permissions,
305
+ see [System installation](system-installation.md). The default npm installation
306
+ above runs as your own user.