Verified, offline-capable infrastructure for deploying the Determinate Systems nix-installer without the curl | sh security anti-pattern.
Running curl https://example.com/install.sh | sh is convenient but dangerous:
- No integrity check. The downloaded content is executed immediately; a compromised CDN, DNS hijack, or MITM attack silently executes arbitrary code as root.
- Non-deterministic. The script may change between runs, making deployments unreproducible.
- No audit trail. Nothing records what was executed.
This repository instead pins a specific version, provides the SHA256 checksums of every binary, and verifies the checksum before executing anything. The trust model is: verify first, run second.
Add the composite action to your workflow:
- name: Install Nix
uses: your-org/nix-installer/.github/actions/install-nix@main
with:
version: v0.31.0
sha256: <sha256-from-CHECKSUMS-file-for-x86_64-linux>
extra-conf: |
experimental-features = nix-command flakesThe action:
- Downloads the binary from GitHub Releases (or a mirror).
- Verifies the SHA256 checksum before executing anything.
- Installs Nix with telemetry disabled (
--diagnostic-endpoint=""). - Adds
/nix/var/nix/profiles/default/binto$PATH.
The .deb package bundles the verified nix-installer binary. The binary
itself downloads the Nix store from the internet during apt install.
For fully air-gapped environments, use the Ansible playbook with
--nix-package-url pointing to a locally-hosted Nix tarball.
# Download the package from the GitHub Actions artifact or a release
sudo dpkg -i determinate-nix-installer_0.31.0_amd64.deb
# Nix is now installed and nix-daemon.service is running.
nix --versionTo remove (preserving /nix):
sudo apt remove determinate-nix-installerTo remove and destroy /nix (WARNING: permanent):
sudo apt purge determinate-nix-installer# Install on all hosts in inventory.ini
ansible-playbook ansible/install-nix.yml \
-i inventory.ini \
-e nix_installer_sha256=<sha256-from-CHECKSUMS>
# Uninstall (requires explicit confirmation)
ansible-playbook ansible/uninstall-nix.yml \
-i inventory.ini \
-e confirm_uninstall=trueThe playbook is idempotent: it skips installation if /nix/receipt.json already exists.
# Build the image locally (requires a verified binary in ./artifacts/)
PUSH=false ./docker/build-and-push.sh
# Or use the pre-built image from GHCR
docker pull ghcr.io/your-org/nix-installer:v0.31.0GitHub Releases (Determinate Systems)
|
| HTTPS download
v
nix-installer binary
|
| SHA256 verification
| (against CHECKSUMS file in this repo)
v
Verified binary executed
The CHECKSUMS file in this repository is the single source of truth. Any change to it is visible in git history and triggers code review.
| Component | Verification method |
|---|---|
| nix-installer binary | SHA256 checksum against CHECKSUMS file |
| CHECKSUMS file | Git commit history + branch protection |
| Scripts | Source-controlled; reviewed via PR |
Prevented by this infrastructure:
- MITM attacks serving a malicious installer binary (checksum mismatch detected).
- CDN compromise serving tampered binaries.
- Version drift (pinned version in
VERSIONfile). - Silent changes to the installer script between runs.
Not addressed (out of scope / future enhancements):
- Compromise of the Determinate Systems signing key or GitHub account (you must trust the upstream publisher).
- Compromise of this repository itself (use branch protection and require PR reviews for changes to
CHECKSUMSandVERSION). - Post-installation tampering of the Nix store.
- Provenance verification: SHA256 proves integrity (not tampered in transit) but not authenticity (who built it). Consider adding Sigstore/cosign verification or GPG signature checks as a future enhancement.
- Partial install recovery: If the .deb postinst is interrupted (e.g., by a timeout or system crash), the Nix installation may be left in an inconsistent state. Use
nix-installer uninstallto clean up before retrying.
- Check the nix-installer releases page for the new version.
- Update
VERSIONto the new version string. - Download the binaries and compute their SHA256 checksums:
VERSION=v0.32.0 for arch in x86_64 aarch64; do curl -fLO "https://github.com/DeterminateSystems/nix-installer/releases/download/${VERSION}/nix-installer-${arch}-linux" sha256sum "nix-installer-${arch}-linux" done
- Update
CHECKSUMSwith the new values. - Open a pull request. The CI workflow will validate that the checksums work end-to-end before the PR can be merged.
# Download
VERSION=v0.31.0
curl -fLO "https://github.com/DeterminateSystems/nix-installer/releases/download/${VERSION}/nix-installer-x86_64-linux"
# Compute checksum
sha256sum nix-installer-x86_64-linux
# Compare with CHECKSUMS file
grep nix-installer-x86_64-linux CHECKSUMS# Extract and inspect the bundled binary
dpkg-deb --extract determinate-nix-installer_0.31.0_amd64.deb /tmp/deb-inspect
sha256sum /tmp/deb-inspect/usr/lib/nix-installer/nix-installer
grep nix-installer-x86_64-linux CHECKSUMSShell scripts in this repository should be executable. After cloning, restore permissions with:
chmod +x scripts/verify-and-download.sh
chmod +x scripts/build-deb.sh
chmod +x docker/build-and-push.shThe packaging scripts (packaging/postinst, packaging/prerm, packaging/postrm) are made executable automatically during the .deb build.
.
├── VERSION Pinned nix-installer version
├── CHECKSUMS SHA256 checksums for each binary
├── scripts/
│ ├── verify-and-download.sh Download + verify binary
│ └── build-deb.sh Build .deb package
├── packaging/
│ ├── postinst dpkg post-install: runs nix-installer
│ ├── prerm dpkg pre-remove: stops nix-daemon
│ └── postrm dpkg post-remove: purge-only uninstall
├── .github/
│ ├── actions/install-nix/
│ │ └── action.yml Composite GitHub Action
│ └── workflows/
│ └── build-artifacts.yml CI: builds .deb + Docker image
├── ansible/
│ ├── install-nix.yml Playbook: install Nix on servers
│ └── uninstall-nix.yml Playbook: remove Nix (requires confirmation)
└── docker/
├── Dockerfile Ubuntu 22.04 + Nix image
└── build-and-push.sh Build and push Docker image
- The
nix-installerbinary is developed and maintained by Determinate Systems, Inc. and distributed under the terms of their license. - The infrastructure in this repository (scripts, action, playbooks, Dockerfile) is provided under the MIT License.
- This project is not affiliated with or endorsed by Determinate Systems.