Repository navigation
feat: install script and nodkey update #88
Copy link
Copy link
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
Today an install takes many steps by hand (docs/setup.md section 2). You download the files, check the checksum and check the attestation with gh. Then you take nodkey out of the tarball and install it. An update repeats all of this (section 13). From a phone over SSH, this is slow and easy to get wrong.
Plan
install.shin the root of the repository installs the newest release, or--version X.Y.Z. You run it as root on the host itself: the broker host or an agent machine. It needs onlysh,curl,tar,gzip,sha256sum,install,mktempanduname.nodkey update [--version X.Y.Z]runs the same script, built into the binary withgo:embed. So the code that checks a new release comes from the build that is already installed and checked, not fresh from the network.go:embedcannot reach a parent directory, so the embed lives in a small package at the root of the module (or the implementer picks a better place).- Owner decision, 2026-10-17: run the install as root on each host, never as the agent's user. The agent cannot change what root downloads. The old way, where you download on a trusted machine and copy, stays in the guide as the second way.
Steps of the script
- Linux only, on amd64 or arm64.
- The version:
--version, or the newest release fromhttps://api.github.com/repos/code6x/nodkey/releases/latest, with no login. OnlyvX.Y.Zis accepted. - If that version is installed already, say so and stop. Install an older version than the installed one only with
--version. A build from the source (dev, or notX.Y.Z) counts as "unknown version". - Download the tarball for this machine,
SHA256SUMSand the bundle from ci: publish the attestation bundle with each release #87. Use HTTPS only and a new private temp directory. - Check the SHA-256 of the tarball against its own line in
SHA256SUMS. - Get
gh: download a pinned version, and check it against a SHA-256 written in the script, one per arch. With--gh PATH, use aghthat is installed already instead. It must be 2.93.0 or newer: older versions have known bugs inattestation verify(GHSA-fgw4-v983-mgp8, GHSA-8xvp-7hj6-mcj9). - Run
gh attestation verify --bundle ...with the identity of docs/releasing.md and--deny-self-hosted-runners. Use no login and an empty config: unsetGH_TOKEN,GITHUB_TOKEN,GH_HOST,GH_ENTERPRISE_TOKENandGITHUB_ENTERPRISE_TOKEN. PutHOME,GH_CONFIG_DIRand theXDG_*folders in the temp directory, and turn off gh's update notice and prompts. - Take only
nodkeyout of the tarball. Check thatnodkey versionof the new file prints the expected version. - Install it as
/usr/local/bin/nodkey(or--bin-dir DIR), mode 0755, owned by root when the script runs as root. Replace the old file in one step (a rename in the same directory), never half. - Say what to restart: the broker (
systemctl restart nodkey, which ends all grants) and eachnodkey ssh-agent. Restart nothing yourself. - Remove the temp directory, also after a failure.
Any failed step stops the script with a clear message and installs nothing. Write the script so that a half download through curl ... | sh runs nothing: all work in functions, and one call at the end.
nodkey update
- It runs only as root. If not, it says to run
sudo nodkey update. - It updates the file it runs from (its resolved path).
- It passes
--versionon, and adds nothing else from the environment.
Done when
-
install.shdoes steps 1 to 11. Every failure installs nothing. - The pinned gh is 2.93.0 or newer. Its SHA-256s match the official checksums file of that gh release, and that file passes
gh attestation verify --owner cli. The pull request says how this was checked. (The checksums file itself has no attestation. So both gh tarballs were checked withgh attestation verifyinstead, and their SHA-256s match the checksums file and GitHub's asset digests. See feat: install script and nodkey update #95.) -
nodkey updateruns the embedded script. A test checks that it is the same asinstall.sh. - Tests cover the happy path and each deny path, with no real network: a bad checksum, a missing line in
SHA256SUMS, a failed verify, a bad version from the API, the wrong version in the new binary, an older version without--version, a wrong OS and a wrong arch. For example, use a fakecurlonPATHand--ghwith a fakegh. - shellcheck checks
install.shin thelintjob of CI, with the tool pinned like the others. - docs/setup.md: section 2 offers the installer first, as root on each host, and the old way second. The rule in section 1 matches. Section 13 uses
nodkey update. The README quick start matches. - DESIGN.md (the command table in section 15, and section 18) and THREAT-MODEL.md are updated. The threat model says what the first install trusts (the script from
main), what an update trusts (the script in the installed binary, the attestation, the pinned gh), and what a stolen release App key can and cannot do now (T20). - After the next release,
install.shinstalls it on a clean Debian host with no GitHub login. Tick this after that release.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request
Activity
groupsky commentedon Oct 17, 2026
Done in #95 (cee02b8), except the last box. I reopen the issue until then: after the next release,
install.shmust install it on a clean Debian host with no GitHub login. The low points of the last review are in #94.groupsky commentedon Oct 17, 2026
Checked on 2026-10-17 with the 0.2.0 release, in a clean
debian:trixiecontainer, as root, with no GitHub login.install.shfrommaininstalled 0.2.0: it found the newest release, downloaded the files and the pinned gh 2.102.0, found the attestation valid, and installed/usr/local/bin/nodkeyas root:root, mode 0755.nodkey updatethen said "Nothing to do".nodkey update --reinstallran the full check again through the script inside the binary, and passed.nodkey versionon a terminal printednodkey: this is the newest release. Nothing was left in/tmp.