Daily-refreshed Nix flake mirroring upstream Go and Go tooling. Use it when nixpkgs lags an upstream security patch or tool release.
| Tool | Source | Pinning | Refresh |
|---|---|---|---|
go |
go.dev/dl/?mode=json |
published SHA256 | daily |
golangci-lint |
GitHub releases | per-release <name>-checksums.txt |
daily |
goreleaser |
GitHub releases | per-release checksums.txt |
daily |
gofumpt |
GitHub releases | per-asset API digest field |
daily |
govulncheck |
GitHub git tags | source tarball + vendor SHA256 | daily |
gopls |
GitHub git tags | source tarball + vendor SHA256 | daily |
delve |
GitHub git tags | source tarball (vendored) | daily |
staticcheck |
GitHub git tags | source tarball + vendor SHA256 | daily |
For the binary mirrors, every (os, arch) the upstream actually publishes is
mirrored — coverage is sparse per tool, since a tool appears on a system only
if its upstream ships a binary for that arch. govulncheck, gopls, delve,
and staticcheck are the exceptions: none of them ship upstream binaries for
Linux/Darwin/FreeBSD that we'd want to mirror, so the flake builds them from
source via buildGoModule and exposes them on every system the flake spans.
All four are compiled against this flake's own latest Go rather than
nixpkgs' Go — gopls and staticcheck misbehave when built with a Go minor
older than the project they're analyzing, and delve needs to track Go's
binary symbol format. Pinning the toolchain to the latest mirrored Go is what
makes the "no nixpkgs lag" guarantee hold for these tools too.
delve's release tarballs ship a vendor/ directory, so its data file
records vendor = null; rather than a vendor SRI hash — buildGoModule uses
the bundled vendor tree directly.
{
"packages": {
"go": "github:openserbia/go-flake#go",
"golangci-lint": "github:openserbia/go-flake#golangci-lint",
"goreleaser": "github:openserbia/go-flake#goreleaser",
"gofumpt": "github:openserbia/go-flake#gofumpt",
"govulncheck": "github:openserbia/go-flake#govulncheck",
"gopls": "github:openserbia/go-flake#gopls",
"delve": "github:openserbia/go-flake#delve",
"staticcheck": "github:openserbia/go-flake#staticcheck"
}
}Pin a specific version with _<major>_<minor>_<patch>, e.g. #go_1_26_3.
nix run github:openserbia/go-flake#go -- version
nix shell github:openserbia/go-flake#golangci-lint
nix build github:openserbia/go-flake#gofumpt_0_10_0The Go package installs under $out/share/go/ (matching the nixpkgs
layout), with $out/bin/{go,gofmt} as symlinks into it. devbox merges the
package into its profile, so just point GoLand / IntelliJ's Go SDK at
<project>/.devbox/nix/profile/default/share/go — it has bin/, src/,
and VERSION at the top level, which is what the IDE validates against.
The github: URL scheme hits the GitHub API to resolve refs, which has a low
unauthenticated rate limit. For CI or shared environments that hit it, swap in
the tarball+codeload URL — same content, served via the codeload CDN:
{
"packages": {
"go": "tarball+https://codeload.github.com/openserbia/go-flake/tar.gz/main#go_1_26_3"
}
}nix flake show github:openserbia/go-flakeOr browse the data files directly:
versions.nix— Gogolangci-lint-versions.nixgoreleaser-versions.nixgofumpt-versions.nixgovulncheck-versions.nixgopls-versions.nixdelve-versions.nixstaticcheck-versions.nix
Attribute naming: <tool>_<major>_<minor>_<patch> (dots → underscores). The
bare attribute <tool> is an alias for the newest version available on the
current system. default (and go) point at the latest Go.
Coverage matches each upstream's published artifacts; the flake exposes a tool on a Nix system iff that system maps to a platform key in the data file. Currently exposed systems:
| Linux | Darwin | FreeBSD |
|---|---|---|
x86_64-linux |
x86_64-darwin |
x86_64-freebsd |
aarch64-linux |
aarch64-darwin |
|
i686-linux |
||
armv6l-linux |
||
armv7l-linux |
||
riscv64-linux |
||
powerpc64le-linux |
Run nix flake show on your system to see which tools and versions resolve.
A daily self-hosted GitHub Actions workflow
(.github/workflows/update-versions.yml)
runs five idempotent updater scripts, then commits any diff straight to main:
| Script | Updates | Trust source |
|---|---|---|
scripts/update-versions.py |
versions.nix |
go.dev JSON's sha256 field |
scripts/update-github-tool.py --tool golangci-lint |
golangci-lint-versions.nix |
per-release golangci-lint-<ver>-checksums.txt |
scripts/update-github-tool.py --tool goreleaser |
goreleaser-versions.nix |
per-release checksums.txt |
scripts/update-github-tool.py --tool gofumpt |
gofumpt-versions.nix |
GitHub asset API digest: sha256:… field |
scripts/update-source-tool.py --tool govulncheck |
govulncheck-versions.nix |
nix-prefetch-url --unpack + buildGoModule vendor discovery |
scripts/update-source-tool.py --tool gopls |
gopls-versions.nix |
nix-prefetch-url --unpack + buildGoModule vendor discovery |
scripts/update-source-tool.py --tool delve |
delve-versions.nix |
nix-prefetch-url --unpack (vendor=null; bundled vendor/) |
scripts/update-source-tool.py --tool staticcheck |
staticcheck-versions.nix |
nix-prefetch-url --unpack + buildGoModule vendor discovery |
Each script supports --check (exit non-zero if its data file is stale, no
write). All three updaters accept --min-version to lower the floor;
gofumpt's floor is fixed at 0.9.0 because GitHub only populates asset
digests for releases uploaded after mid-2024.
Trust chain for the binary mirrors: SHA256 comes from the channel above, then
Nix's own fetchurl verifies the downloaded archive against that hash at
build time — no intermediate proxy, URLs point at go.dev and
github.com/<repo>/releases/download/... directly. For govulncheck the
chain is two-step: the source tarball SHA pins the GitHub archive, and the
vendor hash pins the resolved Go module set against go.sum at build time.
When CVEs land in the Go stdlib (DNS resolver, net/mail, HTTP/2, etc.),
upstream ships a patch within days. nixpkgs maintainers usually follow within a
week, but production builds can be left exposed in the interim. The same lag
hits major tool releases (golangci-lint, gofumpt) and frequently slips on Go
sub-minor cadence. This flake mirrors upstream exactly, so a one-line data-file
change is enough to be back on a clean stdlib or a current linter.
This flake is MIT. Each mirrored binary is licensed by its upstream project (Go: BSD-3-Clause; golangci-lint: GPL-3.0-or-later; goreleaser: MIT; gofumpt: BSD-3-Clause; govulncheck: BSD-3-Clause).