From a7f05c6bb0fed3f060435f0828625f705839d56d Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sat, 24 Dec 2022 12:07:41 -0800 Subject: [PATCH] flake.nix: init to ship unstable tailscale packages. With this, you can import "github:tailscale/tailscale" as a nix flake, and get access to the "tailscale-unstable" package. Updates #6845. Signed-off-by: David Anderson --- flake.lock | 60 ++++++++++++++++++ flake.nix | 154 +++++++++++++++++++++++++++++++++++++++++++++++ go.mod.sri | 1 + go.toolchain.sri | 1 + shell.nix | 58 ++++-------------- 5 files changed, 227 insertions(+), 47 deletions(-) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 go.mod.sri create mode 100644 go.toolchain.sri diff --git a/flake.lock b/flake.lock new file mode 100644 index 000000000..ab84dad27 --- /dev/null +++ b/flake.lock @@ -0,0 +1,60 @@ +{ + "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1668681692, + "narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "009399224d5e398d03b22badca40a37ac85412a1", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1671848398, + "narHash": "sha256-cJIIPd1kvCI6ne/S0facbiBNH7sZUzk405GfdSJPwZE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "bb0359be0a1a08c8d74412fe8c69aa2ffb3f477e", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 000000000..f99946c0d --- /dev/null +++ b/flake.nix @@ -0,0 +1,154 @@ +# flake.nix describes a Nix source repository that provides +# development builds of Tailscale and the fork of the Go compiler +# toolchain that Tailscale maintains. It also provides a development +# environment for working on tailscale, for use with "nix develop". +# +# For more information about this and why this file is useful, see: +# https://nixos.wiki/wiki/Flakes +# +# Also look into direnv: https://direnv.net/, this can make it so that you can +# automatically get your environment set up when you change folders into the +# project. +# +# WARNING: currently, the packages provided by this flake are brittle, +# and importing this flake into your own Nix configs is likely to +# leave you with broken builds periodically. +# +# The issue is that building Tailscale binaries uses the buildGoModule +# helper from nixpkgs. This helper demands to know the content hash of +# all of the Go dependencies of this repo, in the form of a Nix SRI +# hash. This hash isn't automatically kept in sync with changes made +# to go.mod yet, and so every time we update go.mod while hacking on +# Tailscale, this flake ends up with a broken build due to hash +# mismatches. +# +# Right now, this flake is intended for use by Tailscale developers, +# who are aware of this mismatch and willing to live with it. At some +# point, we'll add automation to keep the hashes more in sync, at +# which point this caveat should go away. +# +# See https://github.com/tailscale/tailscale/issues/6845 for tracking +# how to fix this mismatch. +{ + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + # Used by shell.nix as a compat shim. + flake-compat = { + url = "github:edolstra/flake-compat"; + flake = false; + }; + }; + + outputs = { self, nixpkgs, flake-utils, flake-compat }: let + # Grab a helper func out of the Nix language libraries. Annoyingly + # these are only accessible through legacyPackages right now, + # which forces us to indirect through a platform-specific + # path. The x86_64-linux in here doesn't really matter, since all + # we're grabbing is a pure Nix string manipulation function that + # doesn't build any software. + fileContents = nixpkgs.legacyPackages.x86_64-linux.lib.fileContents; + + tailscale-go-rev = fileContents ./go.toolchain.rev; + tailscale-go-sri = fileContents ./go.toolchain.sri; + + # pkgsWithTailscaleGo takes a nixpkgs package set, and replaces + # its Go 1.19 compiler with tailscale's fork. + # + # We need to do this because the buildGoModule helper function is + # constructed with legacy nix imports, so we cannot construct a + # buildGoModule variant that uses tailscale's toolchain. Instead, + # we have to replace the toolchain in nixpkgs, and let lazy + # evaluation propagate it into the nixpkgs instance of + # buildGoModule. + # + # This is a bit roundabout, but there doesn't seem to be a more + # elegant way of resolving the impedance mismatch between legacy + # nixpkgs style imports and flake semantics, unless upstream + # nixpkgs exposes the buildGoModule constructor func explicitly. + pkgsWithTailscaleGo = pkgs: pkgs.extend (final: prev: rec { + tailscale_go = prev.lib.overrideDerivation prev.go_1_19 (attrs: rec { + name = "tailscale-go-${version}"; + version = tailscale-go-rev; + src = pkgs.fetchFromGitHub { + owner = "tailscale"; + repo = "go"; + rev = tailscale-go-rev; + sha256 = tailscale-go-sri; + }; + nativeBuildInputs = attrs.nativeBuildInputs ++ [ pkgs.git ]; + # Remove dependency on xcbuild as that causes iOS/macOS builds to fail. + propagatedBuildInputs = []; + checkPhase = ""; + TAILSCALE_TOOLCHAIN_REV = tailscale-go-rev; + }); + # Override go_1_19 so that buildGo119Module below uses + # tailscale's toolchain as well. + go_1_19 = tailscale_go; + }); + + # tailscaleRev is the git commit at which this flake was imported, + # or the empty string when building from a local checkout of the + # tailscale repo. + tailscaleRev = if builtins.hasAttr "rev" self then self.rev else ""; + # tailscaleUnstable takes a nixpkgs package set, and builds + # Tailscale from the same commit as this flake. IOW, it provides + # "tailscale built from HEAD", where HEAD is "whatever commit you + # imported the flake at". + # + # This is currently unfortunately brittle, because we have to + # specify vendorSha256, and that sha changes any time we alter + # go.mod. We don't want to force a nix dependency on everyone + # hacking on Tailscale, so this flake is likely to have broken + # builds periodically until somoene comes through and manually + # fixes them up. I sure wish there was a way to express "please + # just trust the local go.mod, vendorSha256 has no benefit here", + # but alas. + # + # So really, this flake is for tailscale devs to dogfood with, if + # you're an end user you should be prepared for this flake to not + # build periodically. + tailscaleUnstable = pkgs: pkgs.buildGo119Module rec { + name = "tailscale-unstable"; + + src = ./.; + vendorSha256 = fileContents ./go.mod.sri; + nativeBuildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [ pkgs.makeWrapper pkgs.git ]; + ldflags = ["-X tailscale.com/version.GitCommit=${tailscaleRev}"]; + CGO_ENABLED = 0; + subPackages = [ "cmd/tailscale" "cmd/tailscaled" ]; + doCheck = false; + postInstall = pkgs.lib.optionalString pkgs.stdenv.isLinux '' + wrapProgram $out/bin/tailscaled --prefix PATH : ${pkgs.lib.makeBinPath [ pkgs.iproute2 pkgs.iptables pkgs.getent pkgs.shadow ]} + wrapProgram $out/bin/tailscale --suffix PATH : ${pkgs.lib.makeBinPath [ pkgs.procps ]} + + sed -i -e "s#/usr/sbin#$out/bin#" -e "/^EnvironmentFile/d" ./cmd/tailscaled/tailscaled.service + install -D -m0444 -t $out/lib/systemd/system ./cmd/tailscaled/tailscaled.service + ''; + }; + + # This whole blob makes the tailscale package available for all + # OS/CPU combos that nix supports, as well as a dev shell so that + # "nix develop" and "nix-shell" give you a dev env. + flakeForSystem = nixpkgs: system: let + upstreamPkgs = nixpkgs.legacyPackages.${system}; + pkgs = pkgsWithTailscaleGo upstreamPkgs; + ts = tailscaleUnstable pkgs; + in { + packages = { + tailscale-go = pkgs.tailscale-go; + tailscale-unstable = ts; + }; + devShell = pkgs.mkShell { + packages = with upstreamPkgs; [ + pkgs.tailscale_go + git + gotools + gopls + graphviz + ]; + }; + }; + in + flake-utils.lib.eachDefaultSystem (system: flakeForSystem nixpkgs system); +} diff --git a/go.mod.sri b/go.mod.sri new file mode 100644 index 000000000..8410b7f96 --- /dev/null +++ b/go.mod.sri @@ -0,0 +1 @@ +sha256-+5icFKDHXt3JMbUjLQGes4R+GeUi48xRgGd0yPKVrw0= diff --git a/go.toolchain.sri b/go.toolchain.sri new file mode 100644 index 000000000..8040b4a6f --- /dev/null +++ b/go.toolchain.sri @@ -0,0 +1 @@ +sha256-BvwZ/90izw0Ip3lh8eNkJvU46LKnOOhEXF0axkBi/Es= diff --git a/shell.nix b/shell.nix index f65559ce0..a1cdad3eb 100644 --- a/shell.nix +++ b/shell.nix @@ -1,7 +1,5 @@ -# This is a shell.nix file used to describe the environment that tailscale needs -# for development. This includes a lot of the basic tools that you need in order -# to get started. We hope this file will be useful for users of Nix on macOS or -# Linux. +# This is a shell.nix file used to describe the environment that +# tailscale needs for development. # # For more information about this and why this file is useful, see here: # https://nixos.org/guides/nix-pills/developing-with-nix-shell.html @@ -10,46 +8,12 @@ # automatically get your environment set up when you change folders into the # project. -{ - pkgs ? import {}, - tailscale-go-rev ? "fabd769a3703c88780c5a7fb543577992d5074d1", - tailscale-go-sha ? "sha256-BvwZ/90izw0Ip3lh8eNkJvU46LKnOOhEXF0axkBi/Es=", -}: -let - tailscale-go = pkgs.lib.overrideDerivation pkgs.go_1_18 (attrs: rec { - name = "tailscale-go-${version}"; - version = tailscale-go-rev; - src = pkgs.fetchFromGitHub { - owner = "tailscale"; - repo = "go"; - rev = tailscale-go-rev; - sha256 = tailscale-go-sha; - }; - nativeBuildInputs = attrs.nativeBuildInputs ++ [ pkgs.git ]; - # Remove dependency on xcbuild as that causes iOS/macOS builds to fail. - propagatedBuildInputs = []; - # Remove custom nix patches, which are all related to fixing up - # tests. Some don't apply cleanly in 1.19. - # TODO: revert this once nix upstream has formal 1.19 support. - patches = []; - checkPhase = ""; - # Our forked tailscale reads this env var to embed the git hash - # into the Go build version. - TAILSCALE_TOOLCHAIN_REV = tailscale-go-rev; - }); -in - pkgs.mkShell { - # This specifies the tools that are needed for people to get started with - # development. These tools include: - # - The Go compiler toolchain (and all additional tooling with it) - # - gotools for goimports, a robust formatting tool for Go source code - # - gopls, the language server for Go to increase editor integration - # - git, the version control program (used in some scripts) - # - graphviz, for 'go tool pprof' - buildInputs = [ - pkgs.git - pkgs.gotools pkgs.gopls - tailscale-go - pkgs.graphviz - ]; - } +(import ( + let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + in fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; } +) { + src = ./.; +}).shellNix