tailscale/scripts/installer.sh
David Anderson 01a359cec9 scripts: add an install script.
The script detects one of the supported OS/version combos, and issues
the right install instructions for it.

Co-authored-by: Christine Dodrill <xe@tailscale.com>
Signed-off-by: David Anderson <danderson@tailscale.com>
2021-05-14 13:40:41 -07:00

385 lines
8.5 KiB
Bash
Executable File

#!/bin/sh
# Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.
#
# This script detects the current operating system, and installs
# Tailscale according to that OS's conventions.
set -eu
# All the code is wrapped in a main function that gets called at the
# bottom of the file, so that a truncated partial download doesn't end
# up executing half a script.
main() {
# Step 1: detect the current linux distro, version, and packaging system.
#
# We rely on a combination of 'uname' and /etc/os-release to find
# an OS name and version, and from there work out what
# installation method we should be using.
#
# The end result of this step is that the following three
# variables are populated, if detection was successful.
OS=""
VERSION=""
PACKAGETYPE=""
if [ -f /etc/os-release ]; then
# /etc/os-release populates a number of shell variables. We care about the following:
# - ID: the short name of the OS (e.g. "debian", "freebsd")
# - VERSION_ID: the numeric release version for the OS, if any (e.g. "18.04")
# - VERSION_CODENAME: the codename of the OS release, if any (e.g. "buster")
. /etc/os-release
case "$ID" in
ubuntu)
OS="$ID"
VERSION="$VERSION_ID"
PACKAGETYPE="apt"
;;
debian)
OS="$ID"
VERSION="$VERSION_CODENAME"
PACKAGETYPE="apt"
;;
raspbian)
OS="$ID"
VERSION="$VERSION_CODENAME"
PACKAGETYPE="apt"
;;
centos)
OS="$ID"
VERSION="$VERSION_ID"
PACKAGETYPE="dnf"
if [ "$VERSION" = "7" ]; then
PACKAGETYPE="yum"
fi
;;
rhel)
OS="$ID"
VERSION="$(echo "$VERSION_ID" | cut -f1 -d.)"
PACKAGETYPE="dnf"
;;
fedora)
OS="$ID"
VERSION=""
PACKAGETYPE="dnf"
;;
amzn)
OS="amazon-linux"
VERSION="$VERSION_ID"
PACKAGETYPE="yum"
;;
opensuse-leap)
OS="opensuse"
VERSION="leap/$VERSION_ID"
PACKAGETYPE="zypper"
;;
opensuse-tumbleweed)
OS="opensuse"
VERSION="tumbleweed"
PACKAGETYPE="zypper"
;;
arch)
OS="$ID"
VERSION="" # rolling release
PACKAGETYPE="pacman"
;;
manjaro)
OS="$ID"
VERSION="" # rolling release
PACKAGETYPE="pacman"
;;
alpine)
OS="$ID"
VERSION="$VERSION_ID"
PACKAGETYPE="apk"
;;
nixos)
echo "Please add Tailscale to your NixOS configuration directly:"
echo
echo "services.tailscale.enable = true;"
exit 1
;;
void)
OS="$ID"
VERSION="" # rolling release
PACKAGETYPE="xbps"
;;
gentoo)
OS="$ID"
VERSION="" # rolling release
PACKAGETYPE="emerge"
;;
freebsd)
OS="$ID"
VERSION="$(echo "$VERSION_ID" | cut -f1 -d.)"
PACKAGETYPE="pkg"
;;
# TODO: wsl?
# TODO: synology? qnap?
esac
fi
# If we failed to detect something through os-release, consult
# uname and try to infer things from that.
if [ -z "$OS" ]; then
if type uname >/dev/null 2>&1; then
case "$(uname)" in
FreeBSD)
# FreeBSD before 12.2 doesn't have
# /etc/os-release, so we wouldn't have found it in
# the os-release probing above.
OS="freebsd"
VERSION="$(freebsd-version | cut -f1 -d.)"
PACKAGETYPE="pkg"
;;
OpenBSD)
OS="openbsd"
VERSION="$(uname -r)"
PACKAGETYPE=""
;;
Darwin)
OS="macos"
VERSION="$(sw_vers -productVersion | cut -f1-2 -d.)"
PACKAGETYPE="appstore"
;;
Linux)
OS="other-linux"
VERSION=""
PACKAGETYPE=""
;;
esac
fi
fi
# Step 2: having detected an OS we support, is it one of the
# versions we support?
OS_UNSUPPORTED=
case "$OS" in
ubuntu)
if [ "$VERSION" != "16.04" ] && \
[ "$VERSION" != "18.04" ] && \
[ "$VERSION" != "19.10" ] && \
[ "$VERSION" != "20.04" ] && \
[ "$VERSION" != "20.10" ] && \
[ "$VERSION" != "21.04" ]
then
OS_UNSUPPORTED=1
fi
;;
debian)
if [ "$VERSION" != "stretch" ] && \
[ "$VERSION" != "buster" ] && \
[ "$VERSION" != "bullseye" ] && \
[ "$VERSION" != "sid" ]
then
OS_UNSUPPORTED=1
fi
;;
raspbian)
if [ "$VERSION" != "buster" ]
then
OS_UNSUPPORTED=1
fi
;;
centos)
if [ "$VERSION" != "7" ] && \
[ "$VERSION" != "8" ]
then
OS_UNSUPPORTED=1
fi
;;
rhel)
if [ "$VERSION" != "8" ]
then
OS_UNSUPPORTED=1
fi
;;
amazon-linux)
if [ "$VERSION" != "2" ]
then
OS_UNSUPPORTED=1
fi
;;
opensuse)
if [ "$VERSION" != "leap/15.1" ] && \
[ "$VERSION" != "leap/15.2" ] && \
[ "$VERSION" != "tumbleweed" ]
then
OS_UNSUPPORTED=1
fi
;;
arch)
# Rolling release, no version checking needed.
;;
manjaro)
# Rolling release, no version checking needed.
;;
alpine)
# All versions supported, no version checking needed.
# TODO: is that true? When was tailscale packaged?
;;
void)
# Rolling release, no version checking needed.
;;
gentoo)
# Rolling release, no version checking needed.
;;
freebsd)
if [ "$VERSION" != "12" ] && \
[ "$VERSION" != "13" ]
then
OS_UNSUPPORTED=1
fi
;;
openbsd)
OS_UNSUPPORTED=1
;;
macos)
# We delegate macOS installation to the app store, it will
# perform version checks for us.
;;
other-linux)
OS_UNSUPPORTED=1
;;
*)
OS_UNSUPPORTED=1
;;
esac
if [ "$OS_UNSUPPORTED" = "1" ]; then
case "$OS" in
other-linux)
echo "Couldn't determine what kind of Linux is running."
echo "You could try the static binaries at:"
echo "https://pkgs.tailscale.com/stable/#static"
;;
"")
echo "Couldn't determine what operating system you're running."
;;
*)
echo "$OS $VERSION isn't supported by this script yet."
;;
esac
echo
echo "If you'd like us to support your system better, please email support@tailscale.com"
echo "and tell us what OS you're running."
echo
echo "Please include the following information we gathered from your system:"
echo
echo "OS=$OS"
echo "VERSION=$VERSION"
echo "PACKAGETYPE=$PACKAGETYPE"
if type uname >/dev/null 2>&1; then
echo "UNAME=$(uname -a)"
else
echo "UNAME="
fi
echo
if [ -f /etc/os-release ]; then
cat /etc/os-release
else
echo "No /etc/os-release"
fi
exit 1
fi
# Step 3: work out if we can run privileged commands, and if so,
# how.
CAN_ROOT=
SUDO=
if [ "$(id -u)" = 0 ]; then
CAN_ROOT=1
SUDO=""
elif type sudo >/dev/null; then
CAN_ROOT=1
SUDO="sudo"
elif type doas >/dev/null; then
CAN_ROOT=1
SUDO="doas"
fi
if [ "$CAN_ROOT" != "1" ]; then
echo "This installer needs to run commands as root."
echo "We tried looking for 'sudo' and 'doas', but couldn't find them."
echo "Either re-run this script as root, or set up sudo/doas."
exit 1
fi
# Step 3: run the installation.
echo "Installing Tailscale for $OS $VERSION, using method $PACKAGETYPE"
case "$PACKAGETYPE" in
apt)
# TODO: use newfangled per-repo signature scheme
set -x
curl -fsSL "https://pkgs.tailscale.com/stable/$OS/$VERSION.gpg" | $SUDO apt-key add -
curl -fsSL "https://pkgs.tailscale.com/stable/$OS/$VERSION.list" | $SUDO tee /etc/apt/sources.list.d/tailscale.list
$SUDO apt-get update
$SUDO apt-get install tailscale
set +x
;;
yum)
set -x
$SUDO yum install yum-utils
$SUDO yum-config-manager --add-repo "https://pkgs.tailscale.com/stable/$OS/$VERSION/tailscale.repo"
$SUDO yum install tailscale
$SUDO systemctl enable --now tailscaled
set +x
;;
dnf)
set -x
$SUDO dnf config-manager --add-repo "https://pkgs.tailscale.com/stable/$OS/$VERSION/tailscale.repo"
$SUDO dnf install tailscale
$SUDO systemctl enable --now tailscaled
set +x
;;
zypper)
set -x
$SUDO zypper ar -g -r "https://pkgs.tailscale.com/stable/$OS/$VERSION/tailscale.repo"
$SUDO zypper ref
$SUDO zypper in tailscale
$SUDO systemctl enable --now tailscaled
set +x
;;
pacman)
set -x
$SUDO pacman -S tailscale
$SUDO systemctl enable --now tailscaled
set +x
;;
apk)
set -x
$SUDO apk add tailscale
$SUDO rc-update add tailscale
set +x
;;
xbps)
set -x
$SUDO xbps-install tailscale
set +x
;;
emerge)
set -x
$SUDO emerge net-vpn/tailscale
set +x
;;
appstore)
set -x
open "https://apps.apple.com/us/app/tailscale/id1475387142"
set +x
;;
*)
echo "unexpected: unknown package type $PACKAGETYPE"
exit 1
;;
esac
echo "Installation complete! Log in to start using Tailscale by running:"
echo
if [ -z "$SUDO" ]; then
echo "tailscale up"
else
echo "$SUDO tailscale up"
fi
}
main