diff options
| author | Mike Kramlich <groglogic@gmail.com> | 2020-12-06 18:54:18 -0700 |
|---|---|---|
| committer | Mike Kramlich <groglogic@gmail.com> | 2021-02-24 02:09:39 -0700 |
| commit | d2eeba5adb7f399c570f3b6b2c2cfb9835ee5748 (patch) | |
| tree | f04e99798bcc9c9b831c622ce4b258e3537cfabf | |
| parent | e9e4f1063d84f865b263141bbbb6128b3ab7c32a (diff) | |
| download | tailscale-mkramlich/macos-brew.tar.xz tailscale-mkramlich/macos-brew.zip | |
Homebrew packaging of the non-IPNExtension, unsandboxed tailscale{d} releases for macOS/darwin.mkramlich/macos-brew
So the public can "brew install" tailscale and start it as a global boot daemon via brew services.
supported: Homebrew 3.0, go1.15 darwin/amd64, macOS Catalina 10.15.3, Intel 64-bit
probably also but unconfirmed: BigSur 11 and Apple M1 ARM64
NOTE: lots of upgrades and polish since 1st squashed WIP PR, and applies most prior feedback
Part of #177. (WIP)
Signed-off-by: Mike Kramlich <groglogic@gmail.com>
| -rw-r--r-- | brew/.gitignore | 1 | ||||
| -rw-r--r-- | brew/README.md | 96 | ||||
| -rwxr-xr-x | brew/dl-tarball-sha.sh | 10 | ||||
| -rwxr-xr-x | brew/generate-formula.sh | 109 | ||||
| -rwxr-xr-x | brew/generate-formulae.sh | 19 | ||||
| -rwxr-xr-x | brew/install-start-with-checks.sh | 102 | ||||
| -rwxr-xr-x | brew/make-test-source-tarball.sh | 17 | ||||
| -rwxr-xr-x | brew/search-interesting.sh | 6 | ||||
| -rwxr-xr-x | brew/serve-tarball.sh | 14 | ||||
| -rwxr-xr-x | brew/status.sh | 83 | ||||
| -rwxr-xr-x | brew/stop-uninstall-wipe.sh | 33 | ||||
| -rw-r--r-- | brew/tailscale.commit-pin.rb | 87 | ||||
| -rw-r--r-- | brew/tailscale.rb | 87 | ||||
| -rw-r--r-- | brew/tailscale.tb-github.rb | 86 | ||||
| -rw-r--r-- | brew/tailscale.tb-local.rb | 86 | ||||
| -rwxr-xr-x | brew/test.sh | 39 | ||||
| -rwxr-xr-x | brew/up.sh | 6 | ||||
| -rwxr-xr-x | brew/vars.sh | 23 | ||||
| -rw-r--r-- | control/controlclient/direct.go | 2 |
19 files changed, 905 insertions, 1 deletions
diff --git a/brew/.gitignore b/brew/.gitignore new file mode 100644 index 000000000..51b4cfda1 --- /dev/null +++ b/brew/.gitignore @@ -0,0 +1 @@ +local/ diff --git a/brew/README.md b/brew/README.md new file mode 100644 index 000000000..9364255a4 --- /dev/null +++ b/brew/README.md @@ -0,0 +1,96 @@ +# Tailscale Mac Homebrew Maintainer Guide + + +*********** +*** WIP *** +*********** + + +Homebrew packaging of the non-IPNExtension, unsandboxed tailscale{d} releases for macOS/darwin. + +So the public can "brew install" tailscale and start it as a global boot daemon via brew services. + + +## Platforms Supported + +These platform versions and permutations have been tested and are known to work well: + +| role | brew | golang | os | arch | repo | +| ----------- | --------------------------- | --------------------- | ---------------------- | ------------------ | ---------- | +| maintainer: | Homebrew 3.0.1-120-g5ca03ab | go1.15.8 darwin/amd64 | macOS Catalina 10.15.3 | Intel 64-bit | | +| | | | macOS Big Sur 11.x (?) | Apple M1 ARM64 (?) | | +| | | | | | | +| | | | | | | +| pkg target: | Homebrew 3.0.1-120-g5ca03ab | go1.15.8 darwin/amd64 | macOS Catalina 10.15.3 | Intel 64-bit | tailscale: | +| | | | macOS Big Sur 11.x (?) | Apple M1 ARM64 (?) | 188bb14269 | +| | | | | | HEAD | +| | | | | | likely 1.5 | + + +## Directory Contents + +| type | name | purpose | +| ------------------ | ---------------------------- | -------------------------------------------------------------- | +| formulae | tailscale.rb | The default packaging "formula" in Ruby, based on a | +| | | a pinned commit from the tailscale/tailscale GitHub repo | +| | | | +| | tailscale.*.rb | Alternate formulae (mainly used for testing now, | +| | | and includes some variants based on tagged release source | +| | | tarballs, and local test standin candidates) | +| | | | +| maintainer scripts | vars.sh | role for brew like version/version.sh for build_dist.sh | +| | generate-formulae.sh | regenerates all formulae (default, plus some alternates) | +| | generate-formula.sh | generates formula from an embedded template, to stdout | +| | make-test-source-tarball.sh | | +| | serve-tarball.sh | | +| | dl-tarball-sha.sh | | +| | search-interesting.sh | nice to keep these on maintainer's radar | +| | test.sh | tests all supported permutations | +| | install-start-with-checks.sh | install test run for maintainer | +| | up.sh | | +| | status.sh | | +| | stop-uninstall-wipe.sh | closing counterpart to the install*.sh script | +| | | | +| subdirs | brew/local/ | .gitignored tree created and used during brew maintenance work | + + +## Use Cases + +For the ultimate endusers (ONLY ONCE READY & AVAIL)... + +``` +brew install tailscale +sudo brew services start tailscale +``` + +TODO(mkramlich): add context, details, variants to the above + +For an early adopter who wants to try an unofficial sneak preview of a local brew install of the WIP formula: + +``` +git clone https://github.com/mkramlich/tailscale +cd tailscale +git switch mkramlich/macos-brew +brew install --formula brew/tailscale.rb # default formula draws from a recent good commit from tailscale/tailscale +sudo brew services start tailscale +# tailscaled is now running and registered as a global boot daemon (via launchctl/launchd) +brew/up.sh # then do your auth +# tailscaled is now authorized and providing normal service to your VPN +``` + +For maintainers... + +All scripts assume you are in the cloned repo root, just above brew/ + (EXCEPT make-test-source-tarball.sh, TODO) + +To edit the formula source, regen and retest: + +``` +# modify the template fragments inside generate-formula.sh +# and/or the var values in brew/vars.sh or brew/generate-formulae.sh +brew/generate-formulae.sh +brew/serve-tarball.sh # ensure running in background; only needed for the local source tarball test in test.sh +brew/test.sh # this is very WIP, but generally the goal is if it exits 0 then the tests are green +``` + +TODO(mkramlich): flesh out much further; topics: formula vs bottle, sudo vs not, prefix diffs, local vs public ts tap vs core, testing, submission and bumping diff --git a/brew/dl-tarball-sha.sh b/brew/dl-tarball-sha.sh new file mode 100755 index 000000000..cf0184007 --- /dev/null +++ b/brew/dl-tarball-sha.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env sh +set -eu + +eval $(brew/vars.sh) + +#URLBASE=https://github.com +URLBASE=http://localhost +TARBALL=v$TS_VER.tar.gz +curl -OL $URLBASE/tailscale/tailscale/archive/$TARBALL +shasum -a256 ./$TARBALL # TODO(mkramlich): not the proper point in lifecycle to calc this diff --git a/brew/generate-formula.sh b/brew/generate-formula.sh new file mode 100755 index 000000000..cd0dd0ea1 --- /dev/null +++ b/brew/generate-formula.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env sh +#set -u # TODO(mkramlich): recreate + +# TODO(mkramlich): in form where the url is a .git, the url can also have a tag arg, like: tag: "v1.5.0" + +cat <<TEMPLATE +# typed: false +# frozen_string_literal: true + +# Homebrew formula for Tailscale +class Tailscale < Formula + desc "Easiest, secure, crossplatform WireGuard Go-based VPN w/oauth2, 2FA/SSO" + homepage "https://www.tailscale.com" +TEMPLATE + +if [ "$FORMULA_TYPE" = "tarball" ]; then + cat <<TEMPLATE2 + url "$URL" + sha256 "$SHA256" +TEMPLATE2 +elif [ "$FORMULA_TYPE" = "commit" ]; then + cat <<TEMPLATE3 + url "$URL", + revision: "$REVISION" + version "$VERSION" # TODO(mkramlich): WIP, so not necessarily; brew required a version +TEMPLATE3 +else + exit 1 +fi + +cat <<TEMPLATE4 + license "BSD-3-Clause" + head "$HEAD", + branch: "$BRANCH" + + depends_on "go" => :build + + def install + ENV["GOPATH"] = buildpath + tailscale_path = buildpath/"src/github.com/tailscale/tailscale" + tailscale_path.install buildpath.children + cd tailscale_path do + # TODO(mkramlich): refactor down the 'version.sh to ENV sets': + output = Utils.safe_popen_read("./version/version.sh") + lines = output.split("\n") + lines.each do |line| + parts = line.split("=") + key = parts.at(0) + val = parts.at(1) + system "echo adding to ENV for go builds: key #{key}, val #{val}" + ENV[key] = val + end + # TODO(mkramlich): make brew audit happy again + # TODO(mkramlich): lose the breaking quotes around the vals in the #{ENV["FOO"]} renders in the go builds + # go builds equiv to how done by tailscale repo's build_dist.sh: + system "go", "build", "-o", ".", "-tags", "xversion", "-ldflags", "\"-X tailscale.com/version.Long=#{ENV["VERSION_LONG"]} -X tailscale.com/version.Short=#{ENV["VERSION_SHORT"]} -X tailscale.com/version.GitCommit=#{ENV["VERSION_GIT_HASH"]}\"", "tailscale.com/cmd/tailscale" + system "go", "build", "-o", ".", "-tags", "xversion", "-ldflags", "\"-X tailscale.com/version.Long=#{ENV["VERSION_LONG"]} -X tailscale.com/version.Short=#{ENV["VERSION_SHORT"]} -X tailscale.com/version.GitCommit=#{ENV["VERSION_GIT_HASH"]}\"", "tailscale.com/cmd/tailscaled" + bin.install "tailscale" + bin.install "tailscaled" + end + end + + def post_install + (var/"run/tailscale").mkpath + (var/"lib/tailscale").mkpath + end + + plist_options manual: "sudo tailscaled --socket=#{HOMEBREW_PREFIX}/run/tailscale/tailscaled.sock --state=#{HOMEBREW_PREFIX}/lib/tailscale/tailscaled.state" + + def plist + <<~EOS + <?xml version="1.0" encoding="UTF-8"?> + <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> + <plist version="1.0"> + <dict> + <key>KeepAlive</key> + <dict> + <key>SuccessfulExit</key> + <false/> + <key>NetworkState</key> + <true/> + </dict> + <key>Label</key> + <string>#{plist_name}</string> + <key>ProgramArguments</key> + <array> + <string>#{opt_bin}/tailscaled</string> + <string>--socket=#{var}/run/tailscale/tailscaled.sock</string> + <string>--state=#{var}/lib/tailscale/tailscaled.state</string> + </array> + <key>RunAtLoad</key> + <true/> + <key>WorkingDirectory</key> + <string>#{var}/lib/tailscale</string> + <key>StandardErrorPath</key> + <string>#{var}/log/tailscale/tailscaled-stderr.log</string> + <key>StandardOutPath</key> + <string>#{var}/log/tailscale/tailscaled-stdout.log</string> + </dict> + </plist> + EOS + end + + test do + system bin/"tailscale", "--version" + system bin/"tailscale", "netcheck" + end +end +TEMPLATE4 diff --git a/brew/generate-formulae.sh b/brew/generate-formulae.sh new file mode 100755 index 000000000..a0244e806 --- /dev/null +++ b/brew/generate-formulae.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env sh +set -eu + +eval $(brew/vars.sh) + +GIT_URL=https://github.com/tailscale/tailscale.git +BRANCH=main +VERSION=$TS_VER # TODO(mkramlich): WIP. do this right + +# default formula (pinned against a commmit in the Tailscale GitHub repo) +FORMULA_TYPE=commit URL=$GIT_URL BRANCH=$BRANCH REVISION=$TS_COMMIT_PIN HEAD=$GIT_URL BRANCH=$BRANCH VERSION=$VERSION brew/generate-formula.sh > brew/tailscale.commit-pin.rb + +# alt formula using local HTTP source tarball of a release standin/mock +FORMULA_TYPE=tarball URL="http://localhost:$TS_TARBALL_PORT/tailscale/tailscale/archive/v1.5.0.tar.gz" SHA256="a62caf2eb5c84d2d1775cd8a17eeb0e8ad3b8dbc9453399862d908227e0af721" HEAD=$GIT_URL BRANCH=$BRANCH VERSION=$VERSION brew/generate-formula.sh > brew/tailscale.tb-local.rb + +# alt formula using Tailscale GitHub HTTPS source tarball of a release tag -- the LATEST tag +FORMULA_TYPE=tarball URL="https://github.com/tailscale/tailscale/archive/v1.4.4.tar.gz" SHA256="5312c6d075a32049912e0932a89269869def9ac8ea9d0fdccc6b41db60fc2d4c" HEAD=$GIT_URL BRANCH=$BRANCH VERSION=$VERSION brew/generate-formula.sh > brew/tailscale.tb-github.rb + +cp brew/tailscale{.commit-pin,}.rb diff --git a/brew/install-start-with-checks.sh b/brew/install-start-with-checks.sh new file mode 100755 index 000000000..b9a4ed8ca --- /dev/null +++ b/brew/install-start-with-checks.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env sh +set -eu + +eval $(brew/vars.sh) + +echo +echo SUDO is $SUDO + +echo +echo versions... +brew --version +brew config +go version +echo maintainer VERSION.txt: `cat VERSION.TXT` +echo maintainer script version/version.sh exec: +version/version.sh # we don't truly use this (yet?), just print here as helpful info for later analysis +# TODO(mkramlich) make distinction clear between maintainer script source ver and target package vers + +echo +echo brew doctor... +set +e # to turn -e off (relax this only for time being) +brew doctor # TODO(mkramlich): for brew maintainer, best if have no findings and exit 0 +set -e # to turn back on + +echo +echo audit formula... +# requires Internet access for some audit checks: +set +e # TODO(mkramlich): tmp allow a nonclean formula audit until build_dist fixes/refactor done +brew audit --strict --online --formula $TS_FORMULA # keep this run output blank and exit 0 +set -e + +echo +echo installing... +#brew install -v --build-from-source $TS_FORMULA +brew install -v --formula $TS_FORMULA + +echo +echo checking exe location and diffs... +diff $TS_BIN/tailscale $TS_CELLAR/$TS_VER/bin/tailscale # TODO(mkramlich): FIXME in test case global,tb-github; want 1.5.0, got 1.4.4, SHOULD want 1.4.4 cuz 1.4.4 correct +diff $TS_BIN/tailscaled $TS_CELLAR/$TS_VER/bin/tailscaled + +echo +echo check if brew has formula... +brew list tailscale + +echo +echo check if installed formula matches orig... +diff $TS_FORMULA $TS_CELLAR/$TS_VER/.$TS_FORMULA + +echo +echo lint of the generated launchctl plist for homebrew tailscale... +# should print "<filepath>: OK" and exit 0; brew services (or launchctl) below +# might reject (or silently allow) any given !0 case so better to catch an issue +# early/wider than not, and automate extra clues for maintainer +plutil -lint $TS_CELLAR/$TS_VER/$TS_PLIST + +echo +echo brew test before starting... +brew test $TS_FORMULA + +echo +echo starting... +$SUDO brew services start tailscale + +echo +echo pausing as tailscaled starts... +sleep 8 + +echo +echo checking that our registered Global Daemons plist matches expected... +diff $TS_CELLAR/$TS_VER/$TS_PLIST $INSTALLED_PLIST_DIR/$TS_PLIST + +echo +echo brew service shows tailscale as started... +$SUDO brew services list | grep tailscale + +echo +echo launchctl lists tailscale... +$SUDO launchctl list | grep tailscale + +echo +echo tailscale version... +$TS_BIN/tailscale --version # should be found, executable and exit 0 + +echo +echo tailscale netcheck... +$TS_BIN/tailscale netcheck # should be found, executable and exit 0 + +echo +echo tailscale up \(and wait for human to do the auth dance if needed\)... +brew/up.sh # this will block, displaying the auth url, if it needs to auth. then/or proceed once happy + +echo +echo list all tailscale files installed or generated... +$SUDO find $BREW | grep -i tailscale + +echo +echo pausing to give tailscaled enough time to finish post-auth setup... +sleep 15 # otherwise some of my early status pings sometimes fail (esp hello.ipn.dev; then work on all subsequent attempts) +echo +echo status... +brew/status.sh diff --git a/brew/make-test-source-tarball.sh b/brew/make-test-source-tarball.sh new file mode 100755 index 000000000..abaa747ae --- /dev/null +++ b/brew/make-test-source-tarball.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env sh +set -eu + +# does not create an official release source tarball per GitHub. creates a standin for it, for brew test purposes only + +eval $(tailscale/brew/vars.sh) # TODO(mkramlich): doc the path deviance or automate away + +TARBALL_ARCHIVE=tailscale/brew/local/tarball-serve-root/tailscale/tailscale/archive + +mkdir -p $TARBALL_ARCHIVE + +TARBALL=$TARBALL_ARCHIVE/v$TS_VER.tar.gz + +# assume a repo is cloned at that dir tree location, and its file state is what we want +echo making $TARBALL +tar -czf $TARBALL tailscale-$TS_VER/.gitignore tailscale-$TS_VER/.github/* tailscale-$TS_VER/.gitattributes tailscale-$TS_VER/* +shasum -a256 ./$TARBALL diff --git a/brew/search-interesting.sh b/brew/search-interesting.sh new file mode 100755 index 000000000..4d5ab850d --- /dev/null +++ b/brew/search-interesting.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh + +brew search tailscale +brew search wireguard +brew search vpn +brew search golang diff --git a/brew/serve-tarball.sh b/brew/serve-tarball.sh new file mode 100755 index 000000000..059d797ca --- /dev/null +++ b/brew/serve-tarball.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env sh +set -eu + +# only for Tailscale brew maintainer, to local-only serve a source tarball standin, during brew testing + +eval $(brew/vars.sh) + +python3 -m http.server --directory brew/local/tarball-serve-root --bind localhost $TS_TARBALL_PORT + +# why the above? during one formula/release test brew may expect to fetch a tarball from (w/version varying): +# http://localhost:$TS_TARBALL_PORT/tailscale/tailscale/archive/v$TS_VER.tar.gz +# where $TS_VER is like 1.5.0 +# therefore under tarball-serve-root/ that file should be in: +# tailscale/tailscale/archive/ diff --git a/brew/status.sh b/brew/status.sh new file mode 100755 index 000000000..61b2724f0 --- /dev/null +++ b/brew/status.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env sh +set -u + +eval $(brew/vars.sh) + +# everything you see below is not expected to be rigorous, or decisive or even always relevant, +# but gives useful data and a nice smoke test of a candidate install for the brew maintainer + +echo file checks \(exes, state, socket\)... +ls -la $TS_BIN/tailscale* +ls -l $TS_STATE +ls -l $TS_SOCK + +echo +$TS_BIN/tailscale version + +echo +$TS_BIN/tailscale netcheck + +echo +echo tailscale status: +sudo $TS_BIN/tailscale -socket=$TS_SOCK status + +echo +ifconfig -r en0 + +# TODO(mkramlich): learn the utun<NUM> it picked and handle tun/gateway right everywhere below + +echo +ifconfig -r utun5 + +echo Routing\\n + +echo \(Destination Gateway Flags Netif Expire\): +netstat -r -n -f inet | grep utun + +echo IPv4 routes: +netstat -r -n -f inet -ll +echo IPv4 route stats: +netstat -r -n -f inet -s +echo IPv6 routes: +netstat -r -n -f inet6 -ll +echo IPv6 route stats: +netstat -r -n -f inet6 -s + +echo +echo checking if host IP forwarding is enabled... +sysctl -a | grep forward + +echo +echo pinging the TS login/coord server... +ping -c1 login.tailscale.com # only to help rule out other issues during a brew test + +echo +echo pinging the TS log server... +ping -c1 log.tailscale.io + +echo +echo pinging the common hello node by name... +ping -c1 hello.ipn.dev # a nice smoke test +echo ... by tailscale ping DNS... +sudo $TS_BIN/tailscale -socket=$TS_SOCK ping -c 1 hello.ipn.dev +echo ... by ping IPv4... +ping -c1 100.101.102.103 +echo ... by tailscale ping IPv4... +sudo $TS_BIN/tailscale -socket=$TS_SOCK ping -c 1 100.101.102.103 +echo ... by ping6 IPv6... +ping6 -c1 fd7a:115c:a1e0:ab12:4843:cd96:6265:6667 # TODO(mkramlich): do right or drop + +# TODO(mkramlich): below is personal node Ts addr, so either drop or make overridable by maintainer +echo +echo pinging my android node... +ping -c1 100.119.147.125 +sudo $TS_BIN/tailscale -socket=$TS_SOCK ping -c 1 100.119.147.125 +ping6 -c1 fd7a:115c:a1e0:ab12:4843:cd96:6277:937d + +echo +echo check stderr log for any recent error, warn, fail, missing or weird... +# NOTE we dont do a 'set -e' style fail assert on this error log tail here because this is for human consumption, +# plus, not quite sure/ready about what specifc messages are scary enough to potentially fail a test +#sudo grep -i -e error -e warn -e fail -e missing -e weird $TS_LOG_DIR/tailscaled-stderr.log +sudo tail -100 $TS_LOG_DIR/tailscaled-stderr.log | grep -i -e error -e warn -e fail -e missing -e weird + diff --git a/brew/stop-uninstall-wipe.sh b/brew/stop-uninstall-wipe.sh new file mode 100755 index 000000000..132b9ce0a --- /dev/null +++ b/brew/stop-uninstall-wipe.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env sh +set -u # also -e? + +eval $(brew/vars.sh) + +echo +echo SUDO is $SUDO + +echo +echo stopping... +$SUDO brew services stop tailscale +$SUDO brew services list | grep tailscale +ps -ef | grep tailscaled | grep -v "grep tailscaled" # TODO(mkramlich): do better +# TODO(mkramlich): the installed plist is gone? + +echo +echo uninstalling... +brew uninstall --force tailscale +$SUDO brew services list | grep tailscale + +echo +echo deleting... +$SUDO rm -rf $TS_CELLAR/$TS_VER +$SUDO rm -f $BREW/var/lib/tailscale/* +$SUDO rm -f $TS_LOG_DIR/* +rmdir $BREW/var/lib/tailscale +rmdir $TS_LOG_DIR +rmdir $BREW/var/run/tailscale +rm $BREW/opt/tailscale # was symlink to $TS_CELLAR/$TS_VER +rmdir $TS_CELLAR +find $BREW | grep -i tailscale +find /opt | grep -i tailscale +# TODO(mkramlich): wipeout brew git checkout cache and/or add test for with-vs-without diff --git a/brew/tailscale.commit-pin.rb b/brew/tailscale.commit-pin.rb new file mode 100644 index 000000000..c7e6e7eb4 --- /dev/null +++ b/brew/tailscale.commit-pin.rb @@ -0,0 +1,87 @@ +# typed: false +# frozen_string_literal: true + +# Homebrew formula for Tailscale +class Tailscale < Formula + desc "Easiest, secure, crossplatform WireGuard Go-based VPN w/oauth2, 2FA/SSO" + homepage "https://www.tailscale.com" + url "https://github.com/tailscale/tailscale.git", + revision: "188bb142691c8b97673a9cb2aebd9f1521e9bb12" + version "1.5.0" # TODO(mkramlich): WIP, so not necessarily; brew required a version + license "BSD-3-Clause" + head "https://github.com/tailscale/tailscale.git", + branch: "main" + + depends_on "go" => :build + + def install + ENV["GOPATH"] = buildpath + tailscale_path = buildpath/"src/github.com/tailscale/tailscale" + tailscale_path.install buildpath.children + cd tailscale_path do + # TODO(mkramlich): refactor down the 'version.sh to ENV sets': + output = Utils.safe_popen_read("./version/version.sh") + lines = output.split("\n") + lines.each do |line| + parts = line.split("=") + key = parts.at(0) + val = parts.at(1) + system "echo adding to ENV for go builds: key #{key}, val #{val}" + ENV[key] = val + end + # TODO(mkramlich): make brew audit happy again + # TODO(mkramlich): lose the breaking quotes around the vals in the #{ENV["FOO"]} renders in the go builds + # go builds equiv to how done by tailscale repo's build_dist.sh: + system "go", "build", "-o", ".", "-tags", "xversion", "-ldflags", "\"-X tailscale.com/version.Long=#{ENV["VERSION_LONG"]} -X tailscale.com/version.Short=#{ENV["VERSION_SHORT"]} -X tailscale.com/version.GitCommit=#{ENV["VERSION_GIT_HASH"]}\"", "tailscale.com/cmd/tailscale" + system "go", "build", "-o", ".", "-tags", "xversion", "-ldflags", "\"-X tailscale.com/version.Long=#{ENV["VERSION_LONG"]} -X tailscale.com/version.Short=#{ENV["VERSION_SHORT"]} -X tailscale.com/version.GitCommit=#{ENV["VERSION_GIT_HASH"]}\"", "tailscale.com/cmd/tailscaled" + bin.install "tailscale" + bin.install "tailscaled" + end + end + + def post_install + (var/"run/tailscale").mkpath + (var/"lib/tailscale").mkpath + end + + plist_options manual: "sudo tailscaled --socket=#{HOMEBREW_PREFIX}/run/tailscale/tailscaled.sock --state=#{HOMEBREW_PREFIX}/lib/tailscale/tailscaled.state" + + def plist + <<~EOS + <?xml version="1.0" encoding="UTF-8"?> + <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> + <plist version="1.0"> + <dict> + <key>KeepAlive</key> + <dict> + <key>SuccessfulExit</key> + <false/> + <key>NetworkState</key> + <true/> + </dict> + <key>Label</key> + <string>#{plist_name}</string> + <key>ProgramArguments</key> + <array> + <string>#{opt_bin}/tailscaled</string> + <string>--socket=#{var}/run/tailscale/tailscaled.sock</string> + <string>--state=#{var}/lib/tailscale/tailscaled.state</string> + </array> + <key>RunAtLoad</key> + <true/> + <key>WorkingDirectory</key> + <string>#{var}/lib/tailscale</string> + <key>StandardErrorPath</key> + <string>#{var}/log/tailscale/tailscaled-stderr.log</string> + <key>StandardOutPath</key> + <string>#{var}/log/tailscale/tailscaled-stdout.log</string> + </dict> + </plist> + EOS + end + + test do + system bin/"tailscale", "--version" + system bin/"tailscale", "netcheck" + end +end diff --git a/brew/tailscale.rb b/brew/tailscale.rb new file mode 100644 index 000000000..c7e6e7eb4 --- /dev/null +++ b/brew/tailscale.rb @@ -0,0 +1,87 @@ +# typed: false +# frozen_string_literal: true + +# Homebrew formula for Tailscale +class Tailscale < Formula + desc "Easiest, secure, crossplatform WireGuard Go-based VPN w/oauth2, 2FA/SSO" + homepage "https://www.tailscale.com" + url "https://github.com/tailscale/tailscale.git", + revision: "188bb142691c8b97673a9cb2aebd9f1521e9bb12" + version "1.5.0" # TODO(mkramlich): WIP, so not necessarily; brew required a version + license "BSD-3-Clause" + head "https://github.com/tailscale/tailscale.git", + branch: "main" + + depends_on "go" => :build + + def install + ENV["GOPATH"] = buildpath + tailscale_path = buildpath/"src/github.com/tailscale/tailscale" + tailscale_path.install buildpath.children + cd tailscale_path do + # TODO(mkramlich): refactor down the 'version.sh to ENV sets': + output = Utils.safe_popen_read("./version/version.sh") + lines = output.split("\n") + lines.each do |line| + parts = line.split("=") + key = parts.at(0) + val = parts.at(1) + system "echo adding to ENV for go builds: key #{key}, val #{val}" + ENV[key] = val + end + # TODO(mkramlich): make brew audit happy again + # TODO(mkramlich): lose the breaking quotes around the vals in the #{ENV["FOO"]} renders in the go builds + # go builds equiv to how done by tailscale repo's build_dist.sh: + system "go", "build", "-o", ".", "-tags", "xversion", "-ldflags", "\"-X tailscale.com/version.Long=#{ENV["VERSION_LONG"]} -X tailscale.com/version.Short=#{ENV["VERSION_SHORT"]} -X tailscale.com/version.GitCommit=#{ENV["VERSION_GIT_HASH"]}\"", "tailscale.com/cmd/tailscale" + system "go", "build", "-o", ".", "-tags", "xversion", "-ldflags", "\"-X tailscale.com/version.Long=#{ENV["VERSION_LONG"]} -X tailscale.com/version.Short=#{ENV["VERSION_SHORT"]} -X tailscale.com/version.GitCommit=#{ENV["VERSION_GIT_HASH"]}\"", "tailscale.com/cmd/tailscaled" + bin.install "tailscale" + bin.install "tailscaled" + end + end + + def post_install + (var/"run/tailscale").mkpath + (var/"lib/tailscale").mkpath + end + + plist_options manual: "sudo tailscaled --socket=#{HOMEBREW_PREFIX}/run/tailscale/tailscaled.sock --state=#{HOMEBREW_PREFIX}/lib/tailscale/tailscaled.state" + + def plist + <<~EOS + <?xml version="1.0" encoding="UTF-8"?> + <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> + <plist version="1.0"> + <dict> + <key>KeepAlive</key> + <dict> + <key>SuccessfulExit</key> + <false/> + <key>NetworkState</key> + <true/> + </dict> + <key>Label</key> + <string>#{plist_name}</string> + <key>ProgramArguments</key> + <array> + <string>#{opt_bin}/tailscaled</string> + <string>--socket=#{var}/run/tailscale/tailscaled.sock</string> + <string>--state=#{var}/lib/tailscale/tailscaled.state</string> + </array> + <key>RunAtLoad</key> + <true/> + <key>WorkingDirectory</key> + <string>#{var}/lib/tailscale</string> + <key>StandardErrorPath</key> + <string>#{var}/log/tailscale/tailscaled-stderr.log</string> + <key>StandardOutPath</key> + <string>#{var}/log/tailscale/tailscaled-stdout.log</string> + </dict> + </plist> + EOS + end + + test do + system bin/"tailscale", "--version" + system bin/"tailscale", "netcheck" + end +end diff --git a/brew/tailscale.tb-github.rb b/brew/tailscale.tb-github.rb new file mode 100644 index 000000000..33b420885 --- /dev/null +++ b/brew/tailscale.tb-github.rb @@ -0,0 +1,86 @@ +# typed: false +# frozen_string_literal: true + +# Homebrew formula for Tailscale +class Tailscale < Formula + desc "Easiest, secure, crossplatform WireGuard Go-based VPN w/oauth2, 2FA/SSO" + homepage "https://www.tailscale.com" + url "https://github.com/tailscale/tailscale/archive/v1.4.4.tar.gz" + sha256 "5312c6d075a32049912e0932a89269869def9ac8ea9d0fdccc6b41db60fc2d4c" + license "BSD-3-Clause" + head "https://github.com/tailscale/tailscale.git", + branch: "main" + + depends_on "go" => :build + + def install + ENV["GOPATH"] = buildpath + tailscale_path = buildpath/"src/github.com/tailscale/tailscale" + tailscale_path.install buildpath.children + cd tailscale_path do + # TODO(mkramlich): refactor down the 'version.sh to ENV sets': + output = Utils.safe_popen_read("./version/version.sh") + lines = output.split("\n") + lines.each do |line| + parts = line.split("=") + key = parts.at(0) + val = parts.at(1) + system "echo adding to ENV for go builds: key #{key}, val #{val}" + ENV[key] = val + end + # TODO(mkramlich): make brew audit happy again + # TODO(mkramlich): lose the breaking quotes around the vals in the #{ENV["FOO"]} renders in the go builds + # go builds equiv to how done by tailscale repo's build_dist.sh: + system "go", "build", "-o", ".", "-tags", "xversion", "-ldflags", "\"-X tailscale.com/version.Long=#{ENV["VERSION_LONG"]} -X tailscale.com/version.Short=#{ENV["VERSION_SHORT"]} -X tailscale.com/version.GitCommit=#{ENV["VERSION_GIT_HASH"]}\"", "tailscale.com/cmd/tailscale" + system "go", "build", "-o", ".", "-tags", "xversion", "-ldflags", "\"-X tailscale.com/version.Long=#{ENV["VERSION_LONG"]} -X tailscale.com/version.Short=#{ENV["VERSION_SHORT"]} -X tailscale.com/version.GitCommit=#{ENV["VERSION_GIT_HASH"]}\"", "tailscale.com/cmd/tailscaled" + bin.install "tailscale" + bin.install "tailscaled" + end + end + + def post_install + (var/"run/tailscale").mkpath + (var/"lib/tailscale").mkpath + end + + plist_options manual: "sudo tailscaled --socket=#{HOMEBREW_PREFIX}/run/tailscale/tailscaled.sock --state=#{HOMEBREW_PREFIX}/lib/tailscale/tailscaled.state" + + def plist + <<~EOS + <?xml version="1.0" encoding="UTF-8"?> + <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> + <plist version="1.0"> + <dict> + <key>KeepAlive</key> + <dict> + <key>SuccessfulExit</key> + <false/> + <key>NetworkState</key> + <true/> + </dict> + <key>Label</key> + <string>#{plist_name}</string> + <key>ProgramArguments</key> + <array> + <string>#{opt_bin}/tailscaled</string> + <string>--socket=#{var}/run/tailscale/tailscaled.sock</string> + <string>--state=#{var}/lib/tailscale/tailscaled.state</string> + </array> + <key>RunAtLoad</key> + <true/> + <key>WorkingDirectory</key> + <string>#{var}/lib/tailscale</string> + <key>StandardErrorPath</key> + <string>#{var}/log/tailscale/tailscaled-stderr.log</string> + <key>StandardOutPath</key> + <string>#{var}/log/tailscale/tailscaled-stdout.log</string> + </dict> + </plist> + EOS + end + + test do + system bin/"tailscale", "--version" + system bin/"tailscale", "netcheck" + end +end diff --git a/brew/tailscale.tb-local.rb b/brew/tailscale.tb-local.rb new file mode 100644 index 000000000..6c0c2d540 --- /dev/null +++ b/brew/tailscale.tb-local.rb @@ -0,0 +1,86 @@ +# typed: false +# frozen_string_literal: true + +# Homebrew formula for Tailscale +class Tailscale < Formula + desc "Easiest, secure, crossplatform WireGuard Go-based VPN w/oauth2, 2FA/SSO" + homepage "https://www.tailscale.com" + url "http://localhost:8901/tailscale/tailscale/archive/v1.5.0.tar.gz" + sha256 "a62caf2eb5c84d2d1775cd8a17eeb0e8ad3b8dbc9453399862d908227e0af721" + license "BSD-3-Clause" + head "https://github.com/tailscale/tailscale.git", + branch: "main" + + depends_on "go" => :build + + def install + ENV["GOPATH"] = buildpath + tailscale_path = buildpath/"src/github.com/tailscale/tailscale" + tailscale_path.install buildpath.children + cd tailscale_path do + # TODO(mkramlich): refactor down the 'version.sh to ENV sets': + output = Utils.safe_popen_read("./version/version.sh") + lines = output.split("\n") + lines.each do |line| + parts = line.split("=") + key = parts.at(0) + val = parts.at(1) + system "echo adding to ENV for go builds: key #{key}, val #{val}" + ENV[key] = val + end + # TODO(mkramlich): make brew audit happy again + # TODO(mkramlich): lose the breaking quotes around the vals in the #{ENV["FOO"]} renders in the go builds + # go builds equiv to how done by tailscale repo's build_dist.sh: + system "go", "build", "-o", ".", "-tags", "xversion", "-ldflags", "\"-X tailscale.com/version.Long=#{ENV["VERSION_LONG"]} -X tailscale.com/version.Short=#{ENV["VERSION_SHORT"]} -X tailscale.com/version.GitCommit=#{ENV["VERSION_GIT_HASH"]}\"", "tailscale.com/cmd/tailscale" + system "go", "build", "-o", ".", "-tags", "xversion", "-ldflags", "\"-X tailscale.com/version.Long=#{ENV["VERSION_LONG"]} -X tailscale.com/version.Short=#{ENV["VERSION_SHORT"]} -X tailscale.com/version.GitCommit=#{ENV["VERSION_GIT_HASH"]}\"", "tailscale.com/cmd/tailscaled" + bin.install "tailscale" + bin.install "tailscaled" + end + end + + def post_install + (var/"run/tailscale").mkpath + (var/"lib/tailscale").mkpath + end + + plist_options manual: "sudo tailscaled --socket=#{HOMEBREW_PREFIX}/run/tailscale/tailscaled.sock --state=#{HOMEBREW_PREFIX}/lib/tailscale/tailscaled.state" + + def plist + <<~EOS + <?xml version="1.0" encoding="UTF-8"?> + <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> + <plist version="1.0"> + <dict> + <key>KeepAlive</key> + <dict> + <key>SuccessfulExit</key> + <false/> + <key>NetworkState</key> + <true/> + </dict> + <key>Label</key> + <string>#{plist_name}</string> + <key>ProgramArguments</key> + <array> + <string>#{opt_bin}/tailscaled</string> + <string>--socket=#{var}/run/tailscale/tailscaled.sock</string> + <string>--state=#{var}/lib/tailscale/tailscaled.state</string> + </array> + <key>RunAtLoad</key> + <true/> + <key>WorkingDirectory</key> + <string>#{var}/lib/tailscale</string> + <key>StandardErrorPath</key> + <string>#{var}/log/tailscale/tailscaled-stderr.log</string> + <key>StandardOutPath</key> + <string>#{var}/log/tailscale/tailscaled-stdout.log</string> + </dict> + </plist> + EOS + end + + test do + system bin/"tailscale", "--version" + system bin/"tailscale", "netcheck" + end +end diff --git a/brew/test.sh b/brew/test.sh new file mode 100755 index 000000000..b4f72e6d4 --- /dev/null +++ b/brew/test.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env sh +set -eu + +# TODO(mkramlich): +# dl-tarball-sha.sh +# make-test-source-tarball.sh + + +echo test variant: global, tb-local +#TODO(mkramlich): for the tb-local tests, server-tarball.sh should be running, with tarball in place +cp brew/tailscale{.tb-local,}.rb +# brew services (via launchd) start as a global boot daemon (in /Library/LaunchDaemons), running as root +# TODO(mkramlich): confirm at reboot starts & works +SUDO="sudo" INSTALLED_PLIST_DIR=/Library/LaunchDaemons brew/install-start-with-checks.sh +SUDO="sudo" INSTALLED_PLIST_DIR=/Library/LaunchDaemons brew/stop-uninstall-wipe.sh + + +echo test variant: global, tb-github +cp brew/tailscale{.tb-github,}.rb +# brew services (via launchd) start as a global boot daemon (in /Library/LaunchDaemons), running as root +# TODO(mkramlich): confirm at reboot starts & works +SUDO="sudo" INSTALLED_PLIST_DIR=/Library/LaunchDaemons brew/install-start-with-checks.sh +SUDO="sudo" INSTALLED_PLIST_DIR=/Library/LaunchDaemons brew/stop-uninstall-wipe.sh + + +echo test variant: global, commit-pin +cp brew/tailscale{.commit-pin,}.rb +# brew services (via launchd) start as a global boot daemon (in /Library/LaunchDaemons), running as root +# TODO(mkramlich): confirm at reboot starts & works +SUDO="sudo" INSTALLED_PLIST_DIR=/Library/LaunchDaemons brew/install-start-with-checks.sh +SUDO="sudo" INSTALLED_PLIST_DIR=/Library/LaunchDaemons brew/stop-uninstall-wipe.sh + + +##################################### + +# brew services (via launchd) start as a user login agent (in ~/Library/LaunchAgents), BUT runs as sudo +# TODO(mkramlich): just a WIP POC, much lower priority than boot perm, might drop +#SUDO="" INSTALLED_PLIST_DIR=~/Library/LaunchAgents brew/install-start-with-checks.sh +#SUDO="" INSTALLED_PLIST_DIR=~/Library/LaunchAgents brew/stop-uninstall-wipe.sh diff --git a/brew/up.sh b/brew/up.sh new file mode 100755 index 000000000..efff5a661 --- /dev/null +++ b/brew/up.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh +set -eu + +eval $(brew/vars.sh) + +sudo $TS_BIN/tailscale -socket=$TS_SOCK up diff --git a/brew/vars.sh b/brew/vars.sh new file mode 100755 index 000000000..5234c44e6 --- /dev/null +++ b/brew/vars.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu + +# TODO(mkramlich): elim redundancy with or otherwise maybe take advantage of version/version.sh + +BREW=`brew --prefix` # because varies; /usr/local on Intel, /opt/homebrew on ARM64/M1/AppleSilicon + +# TODO(mkramlich): Cellar + +cat <<EOF +TS_VER=1.5.0 +TS_COMMIT_PIN=188bb142691c8b97673a9cb2aebd9f1521e9bb12 +TS_BIN=$BREW/bin +TS_SOCK=$BREW/var/run/tailscale/tailscaled.sock +TS_STATE=$BREW/var/lib/tailscale/tailscaled.state +TS_LOG_DIR=$BREW/var/log/tailscale +TS_CELLAR=$BREW/Cellar/tailscale +TS_PLIST=homebrew.mxcl.tailscale.plist +TS_TARBALL_PORT=8901 +TS_FORMULA=brew/tailscale.rb +BREW=$BREW +INSTALLED_PLIST_DIR=/Library/LaunchDaemons +EOF diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index be04e143c..119f630ee 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -187,7 +187,7 @@ func packageType() string { } case "darwin": // Using tailscaled or IPNExtension? - exe, _ := os.Executable() + exe, _ := os.Executable() // TODO(mkramlich): for tailscaled, distinguish if brew return filepath.Base(exe) } return "" |
