From fe58fb9d957febc6efb87f0f461fe5659893e209 Mon Sep 17 00:00:00 2001 From: Moses Narrow <36607567+0pcom@users.noreply.github.com> Date: Sat, 2 May 2026 16:54:33 -0500 Subject: [PATCH 1/6] nix: Nix derivations for source-build (static musl) and prebuilt-binary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drops three files under nix/ packaging skywire for Nix in the same two flavors the AUR does: nix/skywire.nix — pkgsStatic.buildGoModule, mirrors the upstream `make build-static` recipe: CC=musl-gcc, -linkmode external -extldflags "-static" -buildid=. Fully static binary, identical in shape to the release tarballs. nix/skywire-bin.nix — fetchurl the upstream release tarball for the host arch (amd64/arm64/386/armhf/arm/ riscv64) and install. No autoPatchelf — upstream releases are already static-musl, so they run on any glibc/musl host. nix/flake.nix — exposes packages.{skywire,skywire-bin,default}, apps.{skywire,skywire-cli,skywire-visor, skywire-bin}, and a devShells.default with go + musl + make for iterating on the build itself. Both packages produce the same on-disk layout the AUR does: $out/bin/skywire — merged binary (cmd/skywire) $out/bin/skywire-cli — shim → skywire cli $out/bin/skywire-visor — shim → skywire visor $out/share/skywire/apps/ — shims for skychat, skysocks, vpn-server, vpn-client, skynet-srv, skynet-client, skysocks-client. Point the visor at this dir via --apps-dir / launcher.bin_path. skywire.nix's source defaults to ../. (build the local working tree, the common "iterating on a branch" case); flake-input or override gets a tagged release. skywire-bin.nix takes a `hashes` attrset (one sha256 per arch) that's left as lib.fakeHash placeholders by default — first build will fail with the expected hash for the host arch and you fill it in. A NixOS module (services.skywire.{enable,services.tpd,…} mirroring the AUR systemd units + skywire-autoconfig.service) is the natural follow-up; this drop is the package-only path so `nix build` and `nix run github:0pcom/skywire` work today. Includes nix/README.md with usage notes (build paths, hash-fill flow, --apps-dir, the static-binary sanity check). --- nix/README.md | 96 +++++++++++++++++++++++++++ nix/flake.nix | 85 ++++++++++++++++++++++++ nix/skywire-bin.nix | 148 ++++++++++++++++++++++++++++++++++++++++++ nix/skywire.nix | 154 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 483 insertions(+) create mode 100644 nix/README.md create mode 100644 nix/flake.nix create mode 100644 nix/skywire-bin.nix create mode 100644 nix/skywire.nix diff --git a/nix/README.md b/nix/README.md new file mode 100644 index 0000000000..812c027db4 --- /dev/null +++ b/nix/README.md @@ -0,0 +1,96 @@ +# Skywire — Nix packaging + +Two derivations, mirroring the AUR `skywire` and `skywire-bin` +packages: + +- **`skywire.nix`** — source build. Uses `pkgsStatic.buildGoModule` + (musl-based stdenv), with the same `-linkmode external -extldflags + "-static" -buildid=` ldflags as the upstream `make build-static` + recipe. Produces a fully-static binary identical in shape to the + release tarballs. + +- **`skywire-bin.nix`** — install the prebuilt release tarball from + GitHub releases. Faster build, trusts the upstream binary. + +Both produce the same layout: + + $out/bin/skywire # merged binary + $out/bin/skywire-cli # shim → skywire cli + $out/bin/skywire-visor # shim → skywire visor + $out/share/skywire/apps/ # shims for skychat, skysocks, vpn-*, etc. + +## Quick start + +From a checkout of this repo: + + cd nix + nix build .#skywire # source build (static musl) + nix build .#skywire-bin # download prebuilt + nix run .#skywire -- --bv + +Or as a flake input from somewhere else: + + { + inputs.skywire.url = "github:0pcom/skywire/nix/packaging"; + # … + outputs = { self, nixpkgs, skywire, ... }: { + # nixosConfigurations / systemPackages / etc. + environment.systemPackages = [ + skywire.packages.${system}.skywire + ]; + }; + } + +## First-time hashes + +`skywire-bin.nix` ships with `lib.fakeHash` placeholders for every +arch's release tarball. The first `nix build .#skywire-bin` will +fail and print the expected hash for the arch you're on; copy it +into the `hashes` attrset in `flake.nix` and rebuild. Repeat for +each arch you want to support. + +`skywire.nix` defaults to building from the **local working tree** +(handy for iterating on a branch). To build a tagged release from +upstream instead, pass `rev` and `version`: + + nix build .#skywire \ + --argstr rev v1.3.50 --argstr version 1.3.50 + +The first such build will fail with the expected `hash` for +`fetchFromGitHub`; copy it into the call in `flake.nix` (or pass +`--argstr hash …` if invoking the file directly). + +## Visor app discovery + +The visor launches `skychat`, `skysocks`, `vpn-server`, etc. as +separate processes. Both packages install dispatcher shims under +`$out/share/skywire/apps/`. Point the visor at that directory: + + skywire visor --apps-dir ${skywire}/share/skywire/apps … + +or, in a config file, set `launcher.bin_path` to the same path. + +## NixOS module — TODO + +A `nixosModules.skywire` exposing `services.skywire.enable`, +service-tree toggles (sn / sd / tpd / dmsg / ar / rf), and the +autoconfig wiring is the natural follow-up. Not in this initial +drop. Once it lands, you'll be able to: + + services.skywire = { + enable = true; + package = pkgs.skywire; # or skywire-bin + services.tpd.enable = true; + # … + }; + +## Validating the build + +To sanity-check the source build is actually static: + + nix build .#skywire + file ./result/bin/skywire + # → ELF 64-bit LSB executable, x86-64, statically linked, … + +If `file` reports `dynamically linked`, the build's `postInstall` +guard already would have failed. diff --git a/nix/flake.nix b/nix/flake.nix new file mode 100644 index 0000000000..e1533cc79a --- /dev/null +++ b/nix/flake.nix @@ -0,0 +1,85 @@ +{ + description = "Skywire packaged for Nix — source build (static musl) and prebuilt-binary variants"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + + # Pin the version once for both packages. Bump this when + # cutting a new release — the source build picks the matching + # git tag (or the working tree, the default), and the + # binary build expects upstream tarballs at v${version}. + version = "1.3.50"; + + skywire = pkgs.callPackage ./skywire.nix { + inherit version; + # Default: build from the local working tree (../..). To + # build a tagged release from upstream instead, override: + # + # nix build .#skywire \ + # --override-input src \ + # 'github:skycoin/skywire/v1.3.50' + }; + + skywire-bin = pkgs.callPackage ./skywire-bin.nix { + inherit version; + # Fill in real hashes here once the release is cut. First + # `nix build .#skywire-bin` will print the expected hash + # for whichever arch you're on; copy it in. + # + # hashes = { + # "linux-amd64" = "sha256-..."; + # "linux-arm64" = "sha256-..."; + # "linux-386" = "sha256-..."; + # "linux-armhf" = "sha256-..."; + # "linux-arm" = "sha256-..."; + # "linux-riscv64" = "sha256-..."; + # }; + }; + in { + packages = { + inherit skywire skywire-bin; + default = skywire; + }; + + # `nix run .#skywire-cli ...` etc. without typing the bin path. + apps = { + skywire = { + type = "app"; + program = "${skywire}/bin/skywire"; + }; + skywire-cli = { + type = "app"; + program = "${skywire}/bin/skywire-cli"; + }; + skywire-visor = { + type = "app"; + program = "${skywire}/bin/skywire-visor"; + }; + skywire-bin = { + type = "app"; + program = "${skywire-bin}/bin/skywire"; + }; + default = self.apps.${system}.skywire; + }; + + # `nix develop` drops you into a shell with the toolchain + # the source build needs (Go, musl, the standard CLI deps), + # mirroring `make build-static` requirements. + devShells.default = pkgs.mkShell { + packages = with pkgs; [ + go + musl + pkg-config + gnumake + git + ]; + }; + }); +} diff --git a/nix/skywire-bin.nix b/nix/skywire-bin.nix new file mode 100644 index 0000000000..942f0a6eeb --- /dev/null +++ b/nix/skywire-bin.nix @@ -0,0 +1,148 @@ +{ + lib, + stdenvNoCC, + fetchurl, + runtimeShell, + version ? "1.3.50", + hashes ? null, +}: + +# skywire-bin — install the statically-linked release binary +# Skycoin publishes on GitHub. Mirrors the AUR `skywire-bin/PKGBUILD`: +# fetch tarball for the current arch, drop the `skywire` binary into +# $out/bin, and create the same wrapper shims. +# +# Release binaries are built static-musl upstream (same recipe as +# `skywire.nix`), so no autoPatchelfHook is needed — they run on +# any glibc/musl host. +# +# `hashes` is an attrset keyed by the `linux-` suffix used in +# the release filename: +# +# { +# "linux-amd64" = "sha256-..."; +# "linux-arm64" = "sha256-..."; +# "linux-386" = "sha256-..."; +# "linux-armhf" = "sha256-..."; +# "linux-arm" = "sha256-..."; +# "linux-riscv64" = "sha256-..."; +# } +# +# When omitted, defaults to `lib.fakeHash` for every arch — first +# real build will fail with the correct expected hash, fill them +# in. The flake at nix/flake.nix exposes a single `skywire-bin` +# package per system; this file is the per-system derivation. + +let + # Map nixpkgs `system` strings to the suffix Skycoin uses in + # release filenames. Returns null on systems with no published + # binary so the caller can short-circuit (we evaluate to a + # broken-package on those rather than failing eval). + archSuffixFor = system: + { + "x86_64-linux" = "linux-amd64"; + "aarch64-linux" = "linux-arm64"; + "i686-linux" = "linux-386"; + "armv7l-linux" = "linux-armhf"; + "armv6l-linux" = "linux-arm"; + "riscv64-linux" = "linux-riscv64"; + }.${system} or null; + + archSuffix = archSuffixFor stdenvNoCC.hostPlatform.system; + + effectiveHashes = + if hashes != null then hashes + else { + "linux-amd64" = lib.fakeHash; + "linux-arm64" = lib.fakeHash; + "linux-386" = lib.fakeHash; + "linux-armhf" = lib.fakeHash; + "linux-arm" = lib.fakeHash; + "linux-riscv64" = lib.fakeHash; + }; + + hash = + if archSuffix == null + then null + else effectiveHashes.${archSuffix} or lib.fakeHash; + + apps = [ + "skychat" + "skysocks" + "skysocks-client" + "vpn-server" + "vpn-client" + "skynet-srv" + "skynet-client" + ]; +in + +if archSuffix == null then + throw "skywire-bin: no upstream release binary published for ${stdenvNoCC.hostPlatform.system}" +else + +stdenvNoCC.mkDerivation { + pname = "skywire-bin"; + inherit version; + + src = fetchurl { + url = "https://github.com/skycoin/skywire/releases/download/v${version}/skywire-v${version}-${archSuffix}.tar.gz"; + inherit hash; + }; + + # Tarball is a single `skywire` binary at the top level — no + # subdir, so unpack stripping zero leading path components. + sourceRoot = "."; + + dontConfigure = true; + dontBuild = true; + + # Static-musl binary — patchelf has nothing to patch, and trying + # would fail. Skip stripping too in case Skycoin shipped any + # symbol info we'd want for debugging. + dontPatchELF = true; + dontStrip = true; + + installPhase = '' + runHook preInstall + + install -Dm755 skywire $out/bin/skywire + + cat > $out/bin/skywire-cli < $out/bin/skywire-visor < $out/share/skywire/apps/${app} < — shims for each native app +# (skywire app ) so the +# visor can launch them with the +# legacy "external apps directory" +# layout. +# +# The visor's BinPath defaults to "./apps" relative to its working +# directory; point it at $out/share/skywire/apps with +# visor.binPath = "${pkgs.skywire}/share/skywire/apps" +# in the NixOS module (or `--apps-dir` on the command line). + +let + selfSrc = + if src != null + then src + else if rev != null + then + fetchFromGitHub { + owner = "skycoin"; + repo = "skywire"; + inherit rev; + # Replace with `nix-prefetch-github skycoin skywire --rev `. + hash = lib.fakeHash; + } + else + # Default: build from the local working tree so `nix build` + # in this checkout exercises the current branch's code. + ../.; + + # Apps that the visor launches as separate binaries; the merged + # `skywire` exposes each as `skywire app `. We install + # shim scripts under $out/share/skywire/apps/ so the visor + # can find them by the legacy filename. + apps = [ + "skychat" + "skysocks" + "skysocks-client" + "vpn-server" + "vpn-client" + "skynet-srv" + "skynet-client" + ]; +in +pkgsStatic.buildGoModule { + pname = "skywire"; + inherit version; + src = selfSrc; + + # The repo vendors all dependencies (`vendor/`); skip the module + # download phase and use them directly. If vendor/ is removed + # upstream, replace with a real `vendorHash`. + vendorHash = null; + + # `cmd/skywire/skywire.go` is the merged-binary entrypoint; the + # repo root has no `package main`. Same target the AUR builds: + # go install github.com/skycoin/skywire/cmd/skywire@v… + subPackages = [ "cmd/skywire" ]; + + # Static-link via musl + the same -extldflags '-static' the + # upstream Makefile uses. CGO_ENABLED is forced on because the + # external linker only fires when cgo is in play. + env.CGO_ENABLED = "1"; + + ldflags = [ + "-s" + "-w" + "-linkmode" "external" + "-extldflags" "-static" + "-buildid=" + "-X" "github.com/skycoin/skywire/pkg/buildinfo.version=v${version}" + "-X" "github.com/skycoin/skywire/pkg/visor.BuildTag=nix_static" + ]; + + # `go build .` produces a binary named after the repo dir + # (`skywire`) — keep it; the AUR shims expect `skywire` too. + postInstall = '' + # Sanity-check the binary actually came out static. Static + # ELFs lack a PT_INTERP segment; readelf reports "Requesting + # program interpreter" only on dynamic executables. Anything + # dynamic here would silently break portability of the closure. + if ${pkgsStatic.buildPackages.binutils-unwrapped}/bin/readelf -l $out/bin/skywire \ + | grep -q 'Requesting program interpreter'; then + echo "skywire binary is dynamically linked — static build failed" >&2 + exit 1 + fi + + # CLI / visor wrapper shims (mirrors AUR layout). + cat > $out/bin/skywire-cli < $out/bin/skywire-visor <`. + install -d $out/share/skywire/apps + '' + lib.concatMapStringsSep "\n" (app: '' + cat > $out/share/skywire/apps/${app} < Date: Sat, 2 May 2026 17:02:54 -0500 Subject: [PATCH 2/6] nix/skywire: build from repo root (matches release binaries) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The merged-binary entrypoint is ./skywire.go at the repo root — package main with both skywire and skycoin command trees attached. The upstream Makefile's build-static recipe uses `go build .` from the root, and the released tarballs come from there. cmd/skywire/skywire.go is a leaner skywire-only main; unused for the release flow. Switch subPackages from "cmd/skywire" to "." so the Nix build produces the same merged binary the release ships. --- nix/skywire.nix | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nix/skywire.nix b/nix/skywire.nix index f257b0b18c..df23bd59ff 100644 --- a/nix/skywire.nix +++ b/nix/skywire.nix @@ -80,10 +80,11 @@ pkgsStatic.buildGoModule { # upstream, replace with a real `vendorHash`. vendorHash = null; - # `cmd/skywire/skywire.go` is the merged-binary entrypoint; the - # repo root has no `package main`. Same target the AUR builds: - # go install github.com/skycoin/skywire/cmd/skywire@v… - subPackages = [ "cmd/skywire" ]; + # The repo root's `skywire.go` is the merged-binary entrypoint + # (skywire + skycoin subtrees); same target the upstream + # Makefile's `build-static` recipe builds with `go build .`. + # `cmd/skywire/` is a leaner skywire-only package not used here. + subPackages = [ "." ]; # Static-link via musl + the same -extldflags '-static' the # upstream Makefile uses. CGO_ENABLED is forced on because the From 67f372e30af35543b845dc1930d57b1d589537b0 Mon Sep 17 00:00:00 2001 From: Moses Narrow <36607567+0pcom@users.noreply.github.com> Date: Sat, 2 May 2026 17:25:25 -0500 Subject: [PATCH 3/6] docs(README): mention Nix flake alongside AUR install paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nix/ packaging only had its own README — top-level README didn't advertise it, so a casual visitor wouldn't know it exists. Add a short subsection ("NixOS / Nix flake") right after the Arch Linux AUR section, with the build/run commands and a flake-input snippet. TOC entry too. --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/README.md b/README.md index 11063d9a7d..51d85c6489 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,7 @@ Table of Contents - [Linux Packages](#linux-packages) - [Debian packages](#debian-packages) - [Arch Linux AUR packages](#arch-linux-aur-packages) + - [NixOS / Nix flake](#nixos--nix-flake) - [Docker](#docker) - [How to create a GitHub release](#how-to-create-a-github-release) - [Dependency Graph](#dependency-graph) @@ -1064,6 +1065,32 @@ Build the skywire Arch Linux package from git sources to the latest commits on t yay --mflags " -p git.PKGBUILD " -S skywire ``` +### NixOS / Nix flake + +Two derivations under [`nix/`](/nix/) — same flavors as the AUR +packages: `skywire` (source build, static-musl, mirrors +`make build-static`) and `skywire-bin` (the upstream release +tarball). + +From a checkout: +``` +cd nix +nix build .#skywire # source, static musl +nix build .#skywire-bin # prebuilt tarball +nix run .#skywire -- --bv +``` + +Or as a flake input from elsewhere: +```nix +inputs.skywire.url = "github:skycoin/skywire?dir=nix"; +# ... +environment.systemPackages = [ skywire.packages.${system}.skywire ]; +``` + +See [`nix/README.md`](/nix/README.md) for the per-arch hash-fill +flow on `skywire-bin`, the visor's `--apps-dir` integration, and +the static-binary sanity check. + ## Docker For docker-specific documentation, see: [DOCKER.md](/DOCKER.md) From 1baf4108947353b59c3a881663d9fed599ac32b0 Mon Sep 17 00:00:00 2001 From: Moses Narrow <36607567+0pcom@users.noreply.github.com> Date: Sat, 2 May 2026 17:29:35 -0500 Subject: [PATCH 4/6] ci: add Nix build workflow for the source-build (static-musl) path GitHub Actions workflow that runs on PRs touching nix/, Go source, or vendored deps: - cachix/install-nix-action installs Nix on ubuntu-latest with flakes enabled. - DeterminateSystems/magic-nix-cache-action populates /nix/store from previous runs (free shared cache). - `nix build .#skywire` exercises the pkgsStatic.buildGoModule recipe end-to-end. - smoke-test runs --bv on the produced binary and --help on the CLI/visor shims. skywire-bin is intentionally skipped: its derivation needs per-arch sha256 values for upstream release tarballs, which won't be filled until a real release runs through this branch. A follow-up workflow gated on release-tag pushes can validate it then. --- .github/workflows/nix.yml | 61 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 .github/workflows/nix.yml diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml new file mode 100644 index 0000000000..0916b26707 --- /dev/null +++ b/.github/workflows/nix.yml @@ -0,0 +1,61 @@ +on: + pull_request: + paths: + - 'nix/**' + - 'go.mod' + - 'go.sum' + - 'vendor/**' + - 'skywire.go' + - 'cmd/**' + - 'pkg/**' + - 'internal/**' + - '.github/workflows/nix.yml' + push: + branches: + - develop + paths: + - 'nix/**' + - 'go.mod' + - 'go.sum' + - 'vendor/**' + - 'skywire.go' + - 'cmd/**' + - 'pkg/**' + - 'internal/**' + - '.github/workflows/nix.yml' + +name: Nix + +jobs: + build-source: + name: Build skywire (static musl) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - uses: cachix/install-nix-action@v27 + with: + extra_nix_config: | + experimental-features = nix-command flakes + accept-flake-config = true + + # Free shared Nix cache; speeds up consecutive runs from cold + # to warm by populating /nix/store from previous runs of this + # workflow (across branches/PRs). + - uses: DeterminateSystems/magic-nix-cache-action@main + + # Build the source-only target. skywire-bin is intentionally + # skipped here — it wants per-arch sha256s for upstream + # release tarballs; until those land in nix/flake.nix it + # would always fail. A separate workflow can validate it once + # release-time hashes are populated. + - name: nix build .#skywire + working-directory: nix + run: nix build .#skywire --print-build-logs + + - name: smoke-test the binary + working-directory: nix + run: | + ./result/bin/skywire --bv + ./result/bin/skywire-cli --help >/dev/null + ./result/bin/skywire-visor --help >/dev/null From 4e151b869702e2380677e90624c8fff3f9784d80 Mon Sep 17 00:00:00 2001 From: Moses Narrow <36607567+0pcom@users.noreply.github.com> Date: Sat, 2 May 2026 17:32:16 -0500 Subject: [PATCH 5/6] nix/flake: whitelist skywire/skywire-bin past the unfree gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The repo has no LICENSE file (the AUR PKGBUILD tags it "license-free", meaning "no license declared"), so the meta in both derivations is `licenses.unfree`. Stock nixpkgs refuses to evaluate unfree packages by default — the CI run failed at eval with error: Refusing to evaluate package 'skywire-1.3.50' … because it has an unfree license Set `config.allowUnfreePredicate` on the flake's nixpkgs import to allow exactly skywire + skywire-bin (nothing else from nixpkgs gets the bypass). `nix build` and `nix run` now work on a stock install without `NIXPKGS_ALLOW_UNFREE=1` / `--impure` exports. The "Git tree is dirty" warning the CI also printed is unrelated and harmless — it's flake.lock being generated on first invocation; build continues past it. --- nix/flake.nix | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/nix/flake.nix b/nix/flake.nix index e1533cc79a..f9a86890a6 100644 --- a/nix/flake.nix +++ b/nix/flake.nix @@ -9,7 +9,20 @@ outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system: let - pkgs = import nixpkgs { inherit system; }; + # Skywire ships without an explicit LICENSE file (the AUR + # PKGBUILD tags it "license-free"), so Nix's policy treats + # it as unfree by default and refuses to build it without an + # opt-in. Whitelist exactly skywire + skywire-bin here so + # `nix build` works on a stock Nix installation without + # exporting NIXPKGS_ALLOW_UNFREE=1 / --impure. + pkgs = import nixpkgs { + inherit system; + config.allowUnfreePredicate = pkg: + builtins.elem (nixpkgs.lib.getName pkg) [ + "skywire" + "skywire-bin" + ]; + }; # Pin the version once for both packages. Bump this when # cutting a new release — the source build picks the matching From a36131f9a879fdfa5b063d91c082d9bb6d88aca2 Mon Sep 17 00:00:00 2001 From: Moses Narrow <36607567+0pcom@users.noreply.github.com> Date: Sat, 2 May 2026 17:35:41 -0500 Subject: [PATCH 6/6] nix/skywire: rename src param to dodge nixpkgs callPackage collision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Eval fails on current nixpkgs (post-2025-11) with error: The "src" package has been renamed to "simple-revision-control". callPackage auto-binds function args to attrs in pkgs; an `src` parameter hits the alias-throw before our `? null` default applies. Renamed to `srcOverride` (intent stays clear; no other callers in tree). Also dropped `-buildid=` from ldflags — buildGoModule sets it already and warns if redundantly passed: trace: evaluation warning: `-buildid=` is set by default as ldflag by buildGoModule --- nix/README.md | 14 +++++++++----- nix/skywire.nix | 18 ++++++++++++++---- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/nix/README.md b/nix/README.md index 812c027db4..99ed3ab0d5 100644 --- a/nix/README.md +++ b/nix/README.md @@ -51,14 +51,18 @@ each arch you want to support. `skywire.nix` defaults to building from the **local working tree** (handy for iterating on a branch). To build a tagged release from -upstream instead, pass `rev` and `version`: +upstream instead, override `rev` and `version` when calling it from +the flake (the parameter for an explicit src tree is `srcOverride`, +to dodge a `pkgs.src` callPackage auto-bind collision in nixpkgs): - nix build .#skywire \ - --argstr rev v1.3.50 --argstr version 1.3.50 + pkgs.callPackage ./skywire.nix { + rev = "v1.3.50"; + version = "1.3.50"; + } The first such build will fail with the expected `hash` for -`fetchFromGitHub`; copy it into the call in `flake.nix` (or pass -`--argstr hash …` if invoking the file directly). +`fetchFromGitHub`; copy it into the `hash = lib.fakeHash` line in +`skywire.nix`. ## Visor app discovery diff --git a/nix/skywire.nix b/nix/skywire.nix index df23bd59ff..687cfc114f 100644 --- a/nix/skywire.nix +++ b/nix/skywire.nix @@ -6,7 +6,12 @@ runtimeShell, rev ? null, version ? "1.3.50", - src ? null, + # Renamed from `src` because callPackage auto-binding hits the + # nixpkgs `pkgs.src` throw alias (renamed to + # `simple-revision-control` in 2025-11) before applying our + # default — eval fails with a confusing "src has been renamed" + # error. Picking a non-colliding name avoids the autobind. + srcOverride ? null, }: # skywire — static musl source build of the merged binary. @@ -40,8 +45,8 @@ let selfSrc = - if src != null - then src + if srcOverride != null + then srcOverride else if rev != null then fetchFromGitHub { @@ -91,12 +96,17 @@ pkgsStatic.buildGoModule { # external linker only fires when cgo is in play. env.CGO_ENABLED = "1"; + # buildGoModule already passes `-buildid=` by default; supplying + # it here would just produce a warning. Keep the rest: -s/-w + # strip the symbol table, -linkmode external + -extldflags + # -static is what musl-gcc-driven static linking needs, and the + # -X injections populate the same buildinfo vars the upstream + # Makefile sets. ldflags = [ "-s" "-w" "-linkmode" "external" "-extldflags" "-static" - "-buildid=" "-X" "github.com/skycoin/skywire/pkg/buildinfo.version=v${version}" "-X" "github.com/skycoin/skywire/pkg/visor.BuildTag=nix_static" ];