make Fleet Node enrollment one command - #989
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
The systemd enablement command in the UI (enable --now) appears inconsistent with the repo’s Fleet Node installer output, and should be reconciled to avoid operator-facing drift.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Updates the ProtoFleet “Enroll a node” UI to present a single copy/paste Fleet Node enrollment command that uses the packaged install paths and then enables the systemd unit after successful enrollment.
Changes:
- Build an enrollment command that runs the installed
/opt/fleetnode/fleetnodeas thefleetnodeservice user with--state-dir /var/lib/fleetnode. - Chain enrollment and systemd enablement into one command (
... enroll ... && sudo systemctl ...). - Update modal + unit tests to assert the new command output.
File summaries
| File | Description |
|---|---|
| client/src/protoFleet/features/settings/components/Nodes/enrollNodeCommand.ts | Builds the new packaged enrollment + systemd lifecycle command. |
| client/src/protoFleet/features/settings/components/Nodes/enrollNodeCommand.test.ts | Updates expectations for the command builder across HTTP/HTTPS and loopback/LAN cases. |
| client/src/protoFleet/features/settings/components/Nodes/EnrollNodeModal.test.tsx | Updates modal rendering test to expect the new command text. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Match the installer lifecycle by enabling the already-running service without restarting it. Keep the modal assertion focused on the command's required fragments while retaining exact builder coverage.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bb5893d321
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Enable and start the service after successful enrollment so a rebooted or stopped installation comes online from the single UI command.
🔐 Codex Security Review
Review SummaryOverall Risk: HIGH Findings[HIGH] Automated review incomplete
NotesHuman review is required because the bounded automated review was incomplete. Generated by Codex Security Review | |
Match the installer lifecycle by enabling the already-running service without restarting it. Keep the modal assertion focused on the command's required fragments while retaining exact builder coverage.
Enable and start the service after successful enrollment so a rebooted or stopped installation comes online from the single UI command.
7e083a6 to
1bb67fd
Compare
Match the installer lifecycle by enabling the already-running service without restarting it. Keep the modal assertion focused on the command's required fragments while retaining exact builder coverage.
Enable and start the service after successful enrollment so a rebooted or stopped installation comes online from the single UI command.
1bb67fd to
8c374f1
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8c374f167b
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Match the installer lifecycle by enabling the already-running service without restarting it. Keep the modal assertion focused on the command's required fragments while retaining exact builder coverage.
Enable and start the service after successful enrollment so a rebooted or stopped installation comes online from the single UI command.
543e3ce to
bb5fa98
Compare
Match the installer lifecycle by enabling the already-running service without restarting it. Keep the modal assertion focused on the command's required fragments while retaining exact builder coverage.
Enable and start the service after successful enrollment so a rebooted or stopped installation comes online from the single UI command.
bb5fa98 to
11a1cda
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 11a1cda59b
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
- resume partial enrollment and retry service activation - exercise the packaged helper without a live Fleet server - preserve unrelated enrollment helpers during uninstall
Match the installer lifecycle by enabling the already-running service without restarting it. Keep the modal assertion focused on the command's required fragments while retaining exact builder coverage.
Enable and start the service after successful enrollment so a rebooted or stopped installation comes online from the single UI command.
- resume partial enrollment and retry service activation - exercise the packaged helper without a live Fleet server - preserve unrelated enrollment helpers during uninstall
Stop the service before forced enrollment and reject retries whose requested server URL differs from persisted state.
23c5e2b to
803f689
Compare
Match the installer lifecycle by enabling the already-running service without restarting it. Keep the modal assertion focused on the command's required fragments while retaining exact builder coverage.
Enable and start the service after successful enrollment so a rebooted or stopped installation comes online from the single UI command.
Package a fleetnode-enroll helper that preserves the fleetnode service account and state directory details, then enables the service after successful enrollment. Use the helper in the operator UI and cover install, upgrade rollback, qualification, and removal behavior.
- resume partial enrollment and retry service activation - exercise the packaged helper without a live Fleet server - preserve unrelated enrollment helpers during uninstall
Stop the service before forced enrollment and reject retries whose requested server URL differs from persisted state.
803f689 to
2c1716b
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2c1716b266
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Reviewable diff: +84/-8 across 5 files (excludes generated, test, and story files).
Summary
Fleet Node enrollment is now a single copy/paste command:
sudo fleetnode-enroll --server-url=.... The packaged helper owns the service-account, state-directory, and systemd details, so operators no longer need the verbose internal command or a separate service-start step.Stack: #990 Make Fleet Node startup readiness explicit → #991 Complete the Fleet Node installer lifecycle → #992 Qualify Fleet Node release artifacts → #989 (this PR). This diff is relative to #992. The upstream PRs establish the service-readiness, transactional installer, and clean-host qualification contracts that this helper extends; broader release/distribution work remains outside this PR.
How it works
The release artifact includes
fleetnode-enroll, and the installer places a managed copy at/usr/local/bin/fleetnode-enroll. The operator UI builds the server URL exactly as before, but now displays the short helper command. The helper runs the installed Fleet Node binary as thefleetnodeservice account with/var/lib/fleetnodeas its state directory, then enables and startsfleet-node.serviceonly after enrollment succeeds.Installer upgrades treat the helper like the binary and unit: an existing managed copy is backed up and restored if installation fails, while an unrelated file at the global path is rejected rather than overwritten. Uninstall and purge remove the managed helper.
Diagrams
flowchart LR A["Operator copies sudo fleetnode-enroll command"] --> B["Managed helper in /usr/local/bin"] B --> C["Fleet Node runs as fleetnode user"] C --> D["Enrollment state is written to /var/lib/fleetnode"] D --> E["systemd enables and starts fleet-node.service"]Areas of the code involved
deployment-files/fleetnode/fleetnode-enrolldeployment-files/fleetnode/install-fleet-node.sh.github/workflows/client/.../Nodes/enrollNodeCommand.tsKey technical decisions & trade-offs
fleetnode-enrollhelper instead of placing the rawfleetnodebinary onPATH; this keeps the full CLI privilege model explicit while making the supported enrollment workflow concise.fleetnodeaccount; systemd enablement still has the privilege it requires./usr/local/bin/fleetnode-enrollinstead of overwriting it, trading automatic replacement for safe host ownership boundaries.Testing & validation
bash deployment-files/fleetnode/tests/test-install-fleetnode.shbash -nfor the helper, installer, installer tests, and package qualification scriptvitest --runforenrollNodeCommand.test.tsandEnrollNodeModal.test.tsx: 13 tests passedgit diff --checkpassed