#!/bin/sh # mf1-join: sets up this computer for MF1 (the tailnet, the MF DEV Root CA). # # curl -fsSL https://join.mf1.mediafactory.dev | sh # curl -fsSL https://join.mf1.mediafactory.dev | sh -s -- --help # # This script only picks the mf1-join program for this computer (Linux x64 or # arm64, macOS arm64 or x64), downloads it and SHA256SUMS from the same site # into a private temporary directory, checks its SHA-256 and runs it with the # given options, reading from the terminal. The directory is removed on exit. # The whole script is one function, so a cut-off download runs nothing. # The site this copy is served from: roles/headscale writes it into each copy # it publishes (https://join.mf1.mediafactory.dev, and # https://headscale.mf1.mediafactory.dev/join). MF1_JOIN_BASE_URL replaces it # in tests. served_from=https://join.mf1.mediafactory.dev main() { set -eu base=${MF1_JOIN_BASE_URL:-$served_from} case $base in https://*) proto='=https' ;; *) proto='=http,https' ;; esac case $(uname -s) in Linux) os=linux ;; Darwin) os=darwin ;; *) fail "mf1-join runs on Linux and macOS only." ;; esac case $(uname -m) in x86_64 | amd64) arch=x64 ;; aarch64 | arm64) arch=arm64 ;; *) fail "mf1-join has no build for $(uname -m)." ;; esac # A shell under Rosetta reports x86_64 on an Apple silicon Mac. if [ "$os" = darwin ] && [ "$(sysctl -n sysctl.proc_translated 2>/dev/null || echo 0)" = 1 ]; then arch=arm64 fi if [ "$os" = linux ] && ldd --version 2>&1 | grep -qi musl; then fail "mf1-join needs a glibc-based Linux; musl distributions such as Alpine are not supported." fi command -v curl >/dev/null 2>&1 || fail "curl is missing." if command -v sha256sum >/dev/null 2>&1; then sha256() { sha256sum "$1" | cut -d' ' -f1; } elif command -v shasum >/dev/null 2>&1; then sha256() { shasum -a 256 "$1" | cut -d' ' -f1; } else fail "Neither sha256sum nor shasum is installed." fi name=mf1-join-$os-$arch umask 077 tmp=$(mktemp -d "${TMPDIR:-/tmp}/mf1-join.XXXXXX") || fail "Could not create a temporary directory." trap 'rm -rf "$tmp"' EXIT trap 'exit 130' INT trap 'exit 143' TERM echo "Downloading $name from $base..." curl -fsSL --proto "$proto" -o "$tmp/SHA256SUMS" "$base/SHA256SUMS" || fail "Could not download $base/SHA256SUMS." curl -fsSL --proto "$proto" -o "$tmp/$name" "$base/$name" || fail "Could not download $base/$name." expected=$(awk -v file="$name" '$2 == file || $2 == "*" file { print $1 }' "$tmp/SHA256SUMS") [ -n "$expected" ] || fail "SHA256SUMS lists no $name." [ "$(sha256 "$tmp/$name")" = "$expected" ] || fail "$name does not match its SHA-256 in SHA256SUMS. Nothing was changed." chmod 700 "$tmp/$name" # macOS runs only signed programs on Apple silicon: sign it ad hoc if needed. if [ "$os" = darwin ] && ! codesign -v "$tmp/$name" >/dev/null 2>&1; then codesign -s - --force "$tmp/$name" >/dev/null 2>&1 || true fi status=0 # Prompts read from the terminal, so `curl ... | sh` works. if (: /dev/null; then "$tmp/$name" "$@" &2 exit 1 } main "$@"