2021-05-13 13:07:44 -07:00
#!/bin/sh
2023-01-27 13:37:20 -08:00
# Copyright (c) Tailscale Inc & AUTHORS
# SPDX-License-Identifier: BSD-3-Clause
2021-05-13 13:07:44 -07:00
#
# This script detects the current operating system, and installs
# Tailscale according to that OS's conventions.
2025-12-02 09:57:21 -06:00
#
# Environment variables:
# TRACK: Set to "stable" or "unstable" (default: stable)
# TAILSCALE_VERSION: Pin to a specific version (e.g., "1.88.4")
#
# Examples:
# curl -fsSL https://tailscale.com/install.sh | sh
# curl -fsSL https://tailscale.com/install.sh | TAILSCALE_VERSION=1.88.4 sh
# curl -fsSL https://tailscale.com/install.sh | TRACK=unstable sh
2021-05-13 13:07:44 -07:00
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 = ""
2021-10-18 19:56:08 -07:00
APT_KEY_TYPE = "" # Only for apt-based distros
2021-12-16 12:33:41 -05:00
APT_SYSTEMCTL_START = false # Only needs to be true for Kali
2022-01-12 13:22:01 -08:00
TRACK = " ${ TRACK :- stable } "
2025-12-02 09:57:21 -06:00
TAILSCALE_VERSION = " ${ TAILSCALE_VERSION :- } "
2022-01-12 13:22:01 -08:00
case " $TRACK " in
stable| unstable)
; ;
*)
echo " unsupported track $TRACK "
exit 1
; ;
esac
2021-05-13 13:07:44 -07:00
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")
2022-05-24 21:38:39 -07:00
# - UBUNTU_CODENAME: if it exists, use instead of VERSION_CODENAME
2021-05-13 13:07:44 -07:00
. /etc/os-release
2025-11-14 12:05:48 -08:00
VERSION_MAJOR = " ${ VERSION_ID :- } "
VERSION_MAJOR = " ${ VERSION_MAJOR %%.* } "
2021-05-13 13:07:44 -07:00
case " $ID " in
2024-02-07 12:18:05 +11:00
ubuntu| pop| neon| zorin| tuxedo)
2021-10-16 17:08:57 -07:00
OS = "ubuntu"
2022-05-24 21:38:39 -07:00
if [ " ${ UBUNTU_CODENAME :- } " != "" ] ; then
VERSION = " $UBUNTU_CODENAME "
else
VERSION = " $VERSION_CODENAME "
fi
2021-05-13 13:07:44 -07:00
PACKAGETYPE = "apt"
2021-10-18 19:56:08 -07:00
# Third-party keyrings became the preferred method of
# installation in Ubuntu 20.04.
2025-11-14 12:05:48 -08:00
if [ " $VERSION_MAJOR " -lt 20 ] ; then
2021-10-18 19:56:08 -07:00
APT_KEY_TYPE = "legacy"
2025-11-14 12:05:48 -08:00
else
APT_KEY_TYPE = "keyring"
2021-10-18 19:56:08 -07:00
fi
2021-05-13 13:07:44 -07:00
; ;
debian)
OS = " $ID "
VERSION = " $VERSION_CODENAME "
PACKAGETYPE = "apt"
2021-10-18 19:56:08 -07:00
# Third-party keyrings became the preferred method of
# installation in Debian 11 (Bullseye).
2022-10-29 09:45:41 -07:00
if [ -z " ${ VERSION_ID :- } " ] ; then
# rolling release. If you haven't kept current, that's on you.
APT_KEY_TYPE = "keyring"
2024-12-30 17:22:48 +00:00
# Parrot Security is a special case that uses ID=debian
elif [ " $NAME " = "Parrot Security" ] ; then
# All versions new enough to have this behaviour prefer keyring
# and their VERSION_ID is not consistent with Debian.
APT_KEY_TYPE = "keyring"
# They don't specify the Debian version they're based off in os-release
# but Parrot 6 is based on Debian 12 Bookworm.
VERSION = bookworm
2025-11-14 12:05:48 -08:00
elif [ " $VERSION_MAJOR " -lt 11 ] ; then
2021-10-18 19:56:08 -07:00
APT_KEY_TYPE = "legacy"
else
APT_KEY_TYPE = "keyring"
fi
2021-05-13 13:07:44 -07:00
; ;
2022-04-16 17:17:14 -07:00
linuxmint)
if [ " ${ UBUNTU_CODENAME :- } " != "" ] ; then
OS = "ubuntu"
VERSION = " $UBUNTU_CODENAME "
elif [ " ${ DEBIAN_CODENAME :- } " != "" ] ; then
OS = "debian"
VERSION = " $DEBIAN_CODENAME "
else
OS = "ubuntu"
VERSION = " $VERSION_CODENAME "
fi
PACKAGETYPE = "apt"
2025-11-14 12:05:48 -08:00
if [ " $VERSION_MAJOR " -lt 5 ] ; then
2022-04-16 17:17:14 -07:00
APT_KEY_TYPE = "legacy"
else
APT_KEY_TYPE = "keyring"
fi
; ;
2022-05-24 21:38:39 -07:00
elementary)
OS = "ubuntu"
VERSION = " $UBUNTU_CODENAME "
PACKAGETYPE = "apt"
2025-11-14 12:05:48 -08:00
if [ " $VERSION_MAJOR " -lt 6 ] ; then
2022-05-24 21:38:39 -07:00
APT_KEY_TYPE = "legacy"
else
APT_KEY_TYPE = "keyring"
fi
; ;
2025-09-18 15:50:01 +01:00
industrial-os)
OS = "debian"
PACKAGETYPE = "apt"
2025-11-14 12:05:48 -08:00
if [ " $VERSION_MAJOR " -lt 5 ] ; then
2025-09-18 15:50:01 +01:00
VERSION = "buster"
APT_KEY_TYPE = "legacy"
else
VERSION = "bullseye"
APT_KEY_TYPE = "keyring"
fi
; ;
2023-02-11 09:38:22 -08:00
parrot| mendel)
2022-04-16 15:55:00 -07:00
OS = "debian"
PACKAGETYPE = "apt"
2025-11-14 12:05:48 -08:00
if [ " $VERSION_MAJOR " -lt 5 ] ; then
2022-04-16 15:55:00 -07:00
VERSION = "buster"
APT_KEY_TYPE = "legacy"
else
VERSION = "bullseye"
APT_KEY_TYPE = "keyring"
fi
; ;
2023-02-18 14:44:32 -08:00
galliumos)
OS = "ubuntu"
PACKAGETYPE = "apt"
VERSION = "bionic"
APT_KEY_TYPE = "legacy"
; ;
2023-08-23 23:11:10 -07:00
pureos| kaisen)
2023-03-01 14:05:53 -08:00
OS = "debian"
PACKAGETYPE = "apt"
VERSION = "bullseye"
APT_KEY_TYPE = "keyring"
; ;
2021-05-13 13:07:44 -07:00
raspbian)
OS = " $ID "
VERSION = " $VERSION_CODENAME "
PACKAGETYPE = "apt"
2021-10-18 19:56:08 -07:00
# Third-party keyrings became the preferred method of
# installation in Raspbian 11 (Bullseye).
2025-11-14 12:05:48 -08:00
if [ " $VERSION_MAJOR " -lt 11 ] ; then
2021-10-18 19:56:08 -07:00
APT_KEY_TYPE = "legacy"
else
APT_KEY_TYPE = "keyring"
fi
2021-05-13 13:07:44 -07:00
; ;
2021-12-04 17:17:46 -08:00
kali)
OS = "debian"
PACKAGETYPE = "apt"
APT_SYSTEMCTL_START = true
# Third-party keyrings became the preferred method of
# installation in Debian 11 (Bullseye), which Kali switched
# to in roughly 2021.x releases
2025-11-14 12:05:48 -08:00
if [ " $VERSION_MAJOR " -lt 2021 ] ; then
2021-12-04 17:17:46 -08:00
# Kali VERSION_ID is "kali-rolling", which isn't distinguishing
VERSION = "buster"
APT_KEY_TYPE = "legacy"
else
VERSION = "bullseye"
APT_KEY_TYPE = "keyring"
fi
; ;
2024-12-23 16:47:55 +00:00
Deepin| deepin) # https://github.com/tailscale/tailscale/issues/7862
2023-04-19 20:36:23 -07:00
OS = "debian"
PACKAGETYPE = "apt"
2025-11-14 12:05:48 -08:00
if [ " $VERSION_MAJOR " -lt 20 ] ; then
2023-04-19 20:36:23 -07:00
APT_KEY_TYPE = "legacy"
2023-08-12 07:16:27 -07:00
VERSION = "buster"
2023-04-19 20:36:23 -07:00
else
APT_KEY_TYPE = "keyring"
2023-08-12 07:16:27 -07:00
VERSION = "bullseye"
2023-04-19 20:36:23 -07:00
fi
; ;
2024-12-23 12:53:54 +00:00
pika)
PACKAGETYPE = "apt"
# All versions of PikaOS are new enough to prefer keyring
APT_KEY_TYPE = "keyring"
# Older versions of PikaOS are based on Ubuntu rather than Debian
2025-11-14 12:05:48 -08:00
if [ " $VERSION_MAJOR " -lt 4 ] ; then
2024-12-23 12:53:54 +00:00
OS = "ubuntu"
VERSION = " $UBUNTU_CODENAME "
else
OS = "debian"
VERSION = " $DEBIAN_CODENAME "
fi
; ;
2025-02-20 18:22:08 +00:00
sparky)
OS = "debian"
PACKAGETYPE = "apt"
VERSION = " $DEBIAN_CODENAME "
APT_KEY_TYPE = "keyring"
; ;
2021-10-19 19:39:49 -07:00
centos)
2021-05-13 13:07:44 -07:00
OS = " $ID "
2025-11-14 12:05:48 -08:00
VERSION = " $VERSION_MAJOR "
2021-05-13 13:07:44 -07:00
PACKAGETYPE = "dnf"
2021-10-19 19:39:49 -07:00
if [ " $VERSION " = "7" ] ; then
PACKAGETYPE = "yum"
fi
; ;
ol)
OS = "oracle"
2025-11-14 12:05:48 -08:00
VERSION = " $VERSION_MAJOR "
2021-10-19 19:39:49 -07:00
PACKAGETYPE = "dnf"
if [ " $VERSION " = "7" ] ; then
2021-05-13 13:07:44 -07:00
PACKAGETYPE = "yum"
fi
; ;
2025-04-14 16:54:51 +01:00
rhel| miraclelinux)
2021-05-13 13:07:44 -07:00
OS = " $ID "
2025-04-14 16:54:51 +01:00
if [ " $ID " = "miraclelinux" ] ; then
OS = "rhel"
fi
2025-11-14 12:05:48 -08:00
VERSION = " $VERSION_MAJOR "
2021-05-13 13:07:44 -07:00
PACKAGETYPE = "dnf"
2022-10-29 15:10:41 -07:00
if [ " $VERSION " = "7" ] ; then
PACKAGETYPE = "yum"
fi
2021-05-13 13:07:44 -07:00
; ;
fedora)
OS = " $ID "
VERSION = ""
PACKAGETYPE = "dnf"
; ;
2023-08-23 23:11:10 -07:00
rocky| almalinux| nobara| openmandriva| sangoma| risios| cloudlinux| alinux| fedora-asahi-remix)
2021-12-04 17:17:46 -08:00
OS = "fedora"
VERSION = ""
PACKAGETYPE = "dnf"
; ;
2021-05-13 13:07:44 -07:00
amzn)
OS = "amazon-linux"
VERSION = " $VERSION_ID "
PACKAGETYPE = "yum"
; ;
2022-05-14 19:54:26 -07:00
xenenterprise)
OS = "centos"
2025-11-14 12:05:48 -08:00
VERSION = " $VERSION_MAJOR "
2022-05-14 19:54:26 -07:00
PACKAGETYPE = "yum"
; ;
2022-12-23 22:15:30 -08:00
opensuse-leap| sles)
2021-05-13 13:07:44 -07:00
OS = "opensuse"
VERSION = " leap/ $VERSION_ID "
PACKAGETYPE = "zypper"
; ;
opensuse-tumbleweed)
OS = "opensuse"
VERSION = "tumbleweed"
PACKAGETYPE = "zypper"
; ;
2023-02-18 08:25:33 -08:00
sle-micro-rancher)
OS = "opensuse"
VERSION = "leap/15.4"
PACKAGETYPE = "zypper"
; ;
2024-12-23 17:53:06 +00:00
arch| archarm| endeavouros| blendos| garuda| archcraft| cachyos)
2022-07-28 20:13:45 -07:00
OS = "arch"
2021-05-13 13:07:44 -07:00
VERSION = "" # rolling release
PACKAGETYPE = "pacman"
; ;
2025-02-06 22:19:16 +00:00
manjaro| manjaro-arm| biglinux)
2022-07-28 20:13:45 -07:00
OS = "manjaro"
2021-05-13 13:07:44 -07:00
VERSION = "" # rolling release
PACKAGETYPE = "pacman"
; ;
alpine)
OS = " $ID "
VERSION = " $VERSION_ID "
PACKAGETYPE = "apk"
; ;
2023-02-17 05:03:20 -08:00
postmarketos)
OS = "alpine"
VERSION = " $VERSION_ID "
PACKAGETYPE = "apk"
; ;
2021-05-13 13:07:44 -07:00
nixos)
echo "Please add Tailscale to your NixOS configuration directly:"
echo
echo "services.tailscale.enable = true;"
exit 1
; ;
2025-08-05 18:24:32 +01:00
bazzite)
echo "Bazzite comes with Tailscale installed by default."
echo "Please enable Tailscale by running the following commands as root:"
echo
echo "ujust enable-tailscale"
echo "tailscale up"
exit 1
; ;
2021-05-13 13:07:44 -07:00
void)
OS = " $ID "
VERSION = "" # rolling release
PACKAGETYPE = "xbps"
; ;
gentoo)
OS = " $ID "
VERSION = "" # rolling release
PACKAGETYPE = "emerge"
; ;
freebsd)
OS = " $ID "
2025-11-14 12:05:48 -08:00
VERSION = " $VERSION_MAJOR "
2021-05-13 13:07:44 -07:00
PACKAGETYPE = "pkg"
; ;
2022-08-27 21:46:03 -07:00
osmc)
OS = "debian"
PACKAGETYPE = "apt"
VERSION = "bullseye"
APT_KEY_TYPE = "keyring"
; ;
2023-03-22 14:23:30 -07:00
photon)
OS = "photon"
2025-11-14 12:05:48 -08:00
VERSION = " $VERSION_MAJOR "
2023-03-22 14:23:30 -07:00
PACKAGETYPE = "tdnf"
; ;
2022-08-27 21:46:03 -07:00
2021-05-13 13:07:44 -07:00
# 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
2023-01-27 19:51:24 +00:00
# Ideally we want to use curl, but on some installs we
# only have wget. Detect and use what's available.
CURL =
if type curl >/dev/null; then
CURL = "curl -fsSL"
elif type wget >/dev/null; then
CURL = "wget -q -O-"
fi
if [ -z " $CURL " ] ; then
echo "The installer needs either curl or wget to download files."
echo "Please install either curl or wget to proceed."
exit 1
fi
2023-04-28 13:47:03 +01:00
TEST_URL = "https://pkgs.tailscale.com/"
RC = 0
TEST_OUT = $( $CURL " $TEST_URL " 2>& 1) || RC = $?
if [ $RC != 0 ] ; then
echo " The installer cannot reach $TEST_URL "
echo "Please make sure that your machine has internet access."
echo "Test output:"
echo $TEST_OUT
exit 1
fi
2021-05-13 13:07:44 -07:00
# Step 2: having detected an OS we support, is it one of the
# versions we support?
OS_UNSUPPORTED =
case " $OS " in
2023-03-25 17:00:46 -07:00
ubuntu| debian| raspbian| centos| oracle| rhel| amazon-linux| opensuse| photon)
2023-01-27 19:51:24 +00:00
# Check with the package server whether a given version is supported.
URL = " https://pkgs.tailscale.com/ $TRACK / $OS / $VERSION /installer-supported "
$CURL " $URL " 2> /dev/null | grep -q OK || OS_UNSUPPORTED = 1
2021-05-13 13:07:44 -07:00
; ;
2021-11-01 12:29:48 -04:00
fedora)
# All versions supported, no version checking required.
; ;
2021-05-13 13:07:44 -07:00
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" ] && \
2025-02-06 16:32:51 +00:00
[ " $VERSION " != "13" ] && \
2025-08-06 03:38:50 +02:00
[ " $VERSION " != "14" ] && \
[ " $VERSION " != "15" ]
2021-05-13 13:07:44 -07:00
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:"
2022-01-12 13:22:01 -08:00
echo " https://pkgs.tailscale.com/ $TRACK /#static "
2021-05-13 13:07:44 -07:00
; ;
"" )
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
2021-05-14 14:11:50 -07:00
2021-05-14 14:13:31 -07:00
# Step 4: run the installation.
2023-04-28 13:44:54 +01:00
OSVERSION = " $OS "
[ " $VERSION " != "" ] && OSVERSION = " $OSVERSION $VERSION "
2025-12-02 09:57:21 -06:00
# Prepare package name with optional version
PACKAGE_NAME = "tailscale"
if [ -n " $TAILSCALE_VERSION " ] ; then
echo " Installing Tailscale $TAILSCALE_VERSION for $OSVERSION , using method $PACKAGETYPE "
else
echo " Installing Tailscale for $OSVERSION , using method $PACKAGETYPE "
fi
2021-05-13 13:07:44 -07:00
case " $PACKAGETYPE " in
apt)
2022-01-11 09:03:51 -08:00
export DEBIAN_FRONTEND = noninteractive
2022-03-16 21:03:07 -04:00
if [ " $APT_KEY_TYPE " = "legacy" ] && ! type gpg >/dev/null; then
2022-02-14 15:55:46 -05:00
$SUDO apt-get update
$SUDO apt-get install -y gnupg
2021-10-18 19:56:08 -07:00
fi
2021-05-14 14:11:50 -07:00
2021-05-13 13:07:44 -07:00
set -x
2021-10-18 19:56:08 -07:00
$SUDO mkdir -p --mode= 0755 /usr/share/keyrings
case " $APT_KEY_TYPE " in
legacy)
2022-01-12 13:22:01 -08:00
$CURL " https://pkgs.tailscale.com/ $TRACK / $OS / $VERSION .asc " | $SUDO apt-key add -
$CURL " https://pkgs.tailscale.com/ $TRACK / $OS / $VERSION .list " | $SUDO tee /etc/apt/sources.list.d/tailscale.list
2025-03-02 10:22:15 -08:00
$SUDO chmod 0644 /etc/apt/sources.list.d/tailscale.list
2021-10-18 19:56:08 -07:00
; ;
keyring)
2022-01-12 13:22:01 -08:00
$CURL " https://pkgs.tailscale.com/ $TRACK / $OS / $VERSION .noarmor.gpg " | $SUDO tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
2025-03-02 10:22:15 -08:00
$SUDO chmod 0644 /usr/share/keyrings/tailscale-archive-keyring.gpg
2022-01-12 13:22:01 -08:00
$CURL " https://pkgs.tailscale.com/ $TRACK / $OS / $VERSION .tailscale-keyring.list " | $SUDO tee /etc/apt/sources.list.d/tailscale.list
2025-03-02 10:22:15 -08:00
$SUDO chmod 0644 /etc/apt/sources.list.d/tailscale.list
2021-10-18 19:56:08 -07:00
; ;
esac
2021-05-13 13:07:44 -07:00
$SUDO apt-get update
2025-12-02 09:57:21 -06:00
if [ -n " $TAILSCALE_VERSION " ] ; then
$SUDO apt-get install -y " tailscale= $TAILSCALE_VERSION " tailscale-archive-keyring
else
$SUDO apt-get install -y tailscale tailscale-archive-keyring
fi
2021-12-04 17:17:46 -08:00
if [ " $APT_SYSTEMCTL_START " = "true" ] ; then
$SUDO systemctl enable --now tailscaled
$SUDO systemctl start tailscaled
fi
2021-05-13 13:07:44 -07:00
set +x
; ;
yum)
set -x
2022-08-15 07:56:20 -07:00
$SUDO yum install yum-utils -y
2022-01-17 11:26:01 -05:00
$SUDO yum-config-manager -y --add-repo " https://pkgs.tailscale.com/ $TRACK / $OS / $VERSION /tailscale.repo "
2025-12-02 09:57:21 -06:00
if [ -n " $TAILSCALE_VERSION " ] ; then
$SUDO yum install " tailscale- $TAILSCALE_VERSION " -y
else
$SUDO yum install tailscale -y
fi
2021-05-13 13:07:44 -07:00
$SUDO systemctl enable --now tailscaled
set +x
; ;
dnf)
2024-10-17 14:12:31 -04:00
# DNF 5 has a different argument format; determine which one we have.
DNF_VERSION = "3"
2025-03-28 12:04:49 +01:00
if LANG = C.UTF-8 dnf --version | grep -q '^dnf5 version' ; then
2024-10-17 14:12:31 -04:00
DNF_VERSION = "5"
fi
# The 'config-manager' plugin wasn't implemented when
# DNF5 was released; detect that and use the old
# version if necessary.
if [ " $DNF_VERSION " = "5" ] ; then
set -x
$SUDO dnf install -y 'dnf-command(config-manager)' && DNF_HAVE_CONFIG_MANAGER = 1 || DNF_HAVE_CONFIG_MANAGER = 0
set +x
if [ " $DNF_HAVE_CONFIG_MANAGER " != "1" ] ; then
if type dnf-3 >/dev/null; then
DNF_VERSION = "3"
else
echo "dnf 5 detected, but 'dnf-command(config-manager)' not available and dnf-3 not found"
exit 1
fi
fi
fi
2021-05-13 13:07:44 -07:00
set -x
2024-10-17 14:12:31 -04:00
if [ " $DNF_VERSION " = "3" ] ; then
$SUDO dnf install -y 'dnf-command(config-manager)'
$SUDO dnf config-manager --add-repo " https://pkgs.tailscale.com/ $TRACK / $OS / $VERSION /tailscale.repo "
elif [ " $DNF_VERSION " = "5" ] ; then
# Already installed config-manager, above.
$SUDO dnf config-manager addrepo --from-repofile= " https://pkgs.tailscale.com/ $TRACK / $OS / $VERSION /tailscale.repo "
else
echo " unexpected: unknown dnf version $DNF_VERSION "
exit 1
fi
2025-12-02 09:57:21 -06:00
if [ -n " $TAILSCALE_VERSION " ] ; then
$SUDO dnf install -y " tailscale- $TAILSCALE_VERSION "
else
$SUDO dnf install -y tailscale
fi
2021-05-13 13:07:44 -07:00
$SUDO systemctl enable --now tailscaled
set +x
; ;
2023-03-22 14:23:30 -07:00
tdnf)
set -x
curl -fsSL " https://pkgs.tailscale.com/ $TRACK / $OS / $VERSION /tailscale.repo " > /etc/yum.repos.d/tailscale.repo
2025-12-02 09:57:21 -06:00
if [ -n " $TAILSCALE_VERSION " ] ; then
$SUDO tdnf install -y " tailscale- $TAILSCALE_VERSION "
else
$SUDO tdnf install -y tailscale
fi
2023-03-22 14:23:30 -07:00
$SUDO systemctl enable --now tailscaled
set +x
; ;
2021-05-13 13:07:44 -07:00
zypper)
set -x
2024-04-10 18:58:35 -05:00
$SUDO rpm --import " https://pkgs.tailscale.com/ $TRACK / $OS / $VERSION /repo.gpg "
2023-04-28 13:44:54 +01:00
$SUDO zypper --non-interactive ar -g -r " https://pkgs.tailscale.com/ $TRACK / $OS / $VERSION /tailscale.repo "
$SUDO zypper --non-interactive --gpg-auto-import-keys refresh
2025-12-02 09:57:21 -06:00
if [ -n " $TAILSCALE_VERSION " ] ; then
$SUDO zypper --non-interactive install " tailscale= $TAILSCALE_VERSION "
else
$SUDO zypper --non-interactive install tailscale
fi
2021-05-13 13:07:44 -07:00
$SUDO systemctl enable --now tailscaled
set +x
; ;
pacman)
set -x
2025-12-02 09:57:21 -06:00
if [ -n " $TAILSCALE_VERSION " ] ; then
echo "Warning: Arch Linux maintains their own Tailscale package. Version pinning may not work as expected, as the target version may no longer be available."
$SUDO pacman -S " tailscale= $TAILSCALE_VERSION " --noconfirm
else
$SUDO pacman -S tailscale --noconfirm
fi
2021-05-13 13:07:44 -07:00
$SUDO systemctl enable --now tailscaled
set +x
; ;
2022-06-20 08:43:07 +02:00
pkg)
set -x
2025-12-02 09:57:21 -06:00
if [ -n " $TAILSCALE_VERSION " ] ; then
echo "Warning: FreeBSD maintains their own Tailscale package. Version pinning may not work as expected, as the target version may no longer be available."
$SUDO pkg install --yes " tailscale- $TAILSCALE_VERSION "
else
$SUDO pkg install --yes tailscale
fi
2022-06-20 08:43:07 +02:00
$SUDO service tailscaled enable
$SUDO service tailscaled start
set +x
; ;
2021-05-13 13:07:44 -07:00
apk)
set -x
2024-05-01 10:09:10 -07:00
if ! grep -Eq '^http.*/community$' /etc/apk/repositories; then
2024-04-29 12:23:46 -07:00
if type setup-apkrepos >/dev/null; then
$SUDO setup-apkrepos -c -1
else
echo "installing tailscale requires the community repo to be enabled in /etc/apk/repositories"
exit 1
fi
fi
2025-12-02 09:57:21 -06:00
if [ -n " $TAILSCALE_VERSION " ] ; then
echo "Warning: Alpine Linux maintains their own Tailscale package. Version pinning may not work as expected, as the target version may no longer be available."
$SUDO apk add " tailscale= $TAILSCALE_VERSION "
else
$SUDO apk add tailscale
fi
2021-05-13 13:07:44 -07:00
$SUDO rc-update add tailscale
2024-02-27 09:17:12 -05:00
$SUDO rc-service tailscale start
2021-05-13 13:07:44 -07:00
set +x
; ;
xbps)
set -x
2025-12-02 09:57:21 -06:00
if [ -n " $TAILSCALE_VERSION " ] ; then
echo "Warning: Void Linux maintains their own Tailscale package. Version pinning may not work as expected, as the target version may no longer be available."
$SUDO xbps-install " tailscale- $TAILSCALE_VERSION " -y
else
$SUDO xbps-install tailscale -y
fi
2021-05-13 13:07:44 -07:00
set +x
; ;
emerge)
set -x
2025-12-02 09:57:21 -06:00
if [ -n " $TAILSCALE_VERSION " ] ; then
echo "Warning: Gentoo maintains their own Tailscale package. Version pinning may not work as expected, as the target version may no longer be available."
$SUDO emerge --ask= n " =net-vpn/tailscale- $TAILSCALE_VERSION "
else
$SUDO emerge --ask= n net-vpn/tailscale
fi
2021-05-13 13:07:44 -07:00
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