diff --git a/debian/13-trixie-luks/scripts/crowdsec-configuration.sh b/debian/13-trixie-luks/scripts/crowdsec-configuration.sh new file mode 100644 index 0000000..6ac3f7a --- /dev/null +++ b/debian/13-trixie-luks/scripts/crowdsec-configuration.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euf -o pipefail + +export DEBIAN_FRONTEND=noninteractive + +# Enable write-ahead-logging (wal -- allowing more concurrency in SQLite that will improve performances in most scenarios.) +sed -i -E '/^db_config:/,/^[^[:space:]]/{s/^([[:space:]]*)type:[[:space:]]*sqlite$/&\ +\1use_wal: true/}' /etc/crowdsec/config.yaml diff --git a/debian/13-trixie-luks/scripts/crowdsec-repo-setup.sh b/debian/13-trixie-luks/scripts/crowdsec-repo-setup.sh new file mode 100644 index 0000000..7b2e815 --- /dev/null +++ b/debian/13-trixie-luks/scripts/crowdsec-repo-setup.sh @@ -0,0 +1,370 @@ +#!/bin/sh +# +# Inspired from packagecloud installation scripts +# +# #MIT License +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: + +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. + +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# Crowdsec repositories installation script +# +# This script: +# - Requires `root` or `sudo` privileges to run +# - Attempts to detect your Linux distribution and version and configure your +# package management system for you. +# - Installs dependencies and recommendations without asking for confirmation. +# - Is POSIX compliant and can be run using bash or any POSIX-compliant shell + + +unknown_os() { + echo "Unfortunately, your operating system distribution and version are not supported by this script." + echo + echo "You can override the OS detection by setting os= and dist= prior to running this script." + echo "You can find a list of supported OSes and distributions on our website: https://packagecloud.io/docs#os_distro_version" + echo + echo "For example, to force Ubuntu Trusty: os=ubuntu dist=trusty ./script.sh" + echo + echo "Please file an issue at https://github.com/crowdsecurity/crowdsec" + exit 1 +} + +detect_os() { + if [ -z "$os" ] && [ -z "$dist" ]; then + if [ -e /etc/os-release ]; then + . /etc/os-release + os=$ID + if [ "$os" = "poky" ]; then + dist="$VERSION_ID" + elif [ "$os" = "sles" ]; then + dist="$VERSION_ID" + os=opensuse + elif [ "$os" = "opensuse" ]; then + dist="$VERSION_ID" + elif [ "$os" = "opensuse-leap" ]; then + os=opensuse + dist="$VERSION_ID" + elif [ "$os" = "amzn" ]; then + dist="$VERSION_ID" + else + dist=$(echo "$VERSION_ID" | awk -F '.' '{ print $1 }') + fi + + elif command -v lsb_release >/dev/null; then + # get major version (e.g. '5' or '6') + dist=$(lsb_release -r | cut -f2 | awk -F '.' '{ print $1 }') + + # get os (e.g. 'centos', 'redhatenterpriseserver', etc) + os=$(lsb_release -i | cut -f2 | awk '{ print tolower($1) }') + + elif [ -e /etc/oracle-release ]; then + dist=$(cut -f5 --delimiter=' ' /etc/oracle-release | awk -F '.' '{ print $1 }') + os='ol' + + elif [ -e /etc/fedora-release ]; then + dist=$(cut -f3 --delimiter=' ' /etc/fedora-release) + os='fedora' + + elif [ -e /etc/redhat-release ]; then + os_hint=$(awk '{ print tolower($1) }' /etc/redhat-release) + if [ "$os_hint" = "centos" ]; then + dist=$(awk '{ print $3 }' /etc/redhat-release | awk -F '.' '{ print $1 }') + os='centos' + elif [ "$os_hint" = "scientific" ]; then + dist=$(awk '{ print $4 }' /etc/redhat-release | awk -F '.' '{ print $1 }') + os='scientific' + else + dist=$(awk '{ print tolower($7) }' /etc/redhat-release | cut -f1 --delimiter='.') + os='redhatenterpriseserver' + fi + + elif grep -q Amazon /etc/issue; then + dist='6' + os='aws' + else + unknown_os + fi + fi + + # remove whitespace from OS and dist name and transform to lowercase + os=$(echo "$os" | tr -d ' ' | tr '[:upper:]' '[:lower:]') + dist=$(echo "$dist" | tr -d ' ' | tr '[:upper:]' '[:lower:]') + + if [ -z "$dist" ]; then + echo "Detected operating system as $os." + else + echo "Detected operating system as $os/$dist." + fi + + if [ "$os" = "ol" ] || [ "$os" = "el" ] && [ "$dist" -gt 7 ]; then + _skip_pygpgme=1 + else + _skip_pygpgme=0 + fi + +} + +gpg_check_deb() { + echo "Checking for gpg..." + if command -v gpg >/dev/null; then + echo "Detected gpg..." + else + echo "Installing gnupg for GPG verification..." + if ! apt-get install -y gnupg; then + echo "Unable to install GPG! Your base system has a problem; please check your default OS's package repositories because GPG should work." + echo "Repository installation aborted." + echo + echo "Please file an issue at https://github.com/crowdsecurity/crowdsec" + exit 1 + fi + fi +} + +curl_check_deb() { + echo "Checking for curl..." + if command -v curl >/dev/null; then + echo "Detected curl..." + else + echo "Installing curl..." + + if apt-get install -q -y curl; then + echo "Unable to install curl! Your base system has a problem; please check your default OS's package repositories because curl should work." + echo "Repository installation aborted." + echo + echo "Please file an issue at https://github.com/crowdsecurity/crowdsec" + exit 1 + fi + fi +} + +curl_check_rpm() { + echo "Checking for curl..." + if command -v curl >/dev/null; then + echo "Detected curl..." + else + echo "Installing curl..." + yum install -d0 -e0 -y curl + fi +} + +curl_check_zypper() { + echo "Checking for curl..." + if command -v curl >/dev/null; then + echo "Detected curl..." + else + echo "Installing curl..." + zypper install curl + fi +} + +finalize_yum_repo() { + if [ "$_skip_pygpgme" = 0 ]; then + echo "Installing pygpgme to verify GPG signatures..." + yum install -y pygpgme --disablerepo="crowdsec_${repo}" + if ! rpm -qa | grep -qw pygpgme; then + echo + echo "WARNING: " + echo "The pygpgme package could not be installed. This means GPG verification is not possible for any RPM installed on your system. " + echo "To fix this, add a repository with pygpgme. Usually, the EPEL repository for your system will have this. " + echo "More information: https://fedoraproject.org/wiki/EPEL#How_can_I_use_these_extra_packages.3F" + echo + + # set the repo_gpgcheck option to 0 + sed -i'' 's/repo_gpgcheck=1/repo_gpgcheck=0/' "/etc/yum.repos.d/crowdsec_${repo}.repo" + fi + fi + + echo "Installing yum-utils..." + yum install -y yum-utils --disablerepo="crowdsec_${repo}" + if ! rpm -qa | grep -qw yum-utils; then + echo + echo "WARNING: " + echo "The yum-utils package could not be installed. This means you may not be able to install source RPMs or use other yum features." + echo + fi + + echo "Generating yum cache for crowdsec..." + yum -q makecache -y --disablerepo='*' --enablerepo="crowdsec_${repo}" +} + +install_debian_keyring() { + if [ "$os" = "debian" ]; then + echo "Installing debian-archive-keyring which is needed for installing " + echo "apt-transport-https on many Debian systems." + apt-get install -y debian-archive-keyring >/dev/null 2>&1 + fi +} + +detect_apt_version() { + apt_version_full=$(apt-get -v | head -1 | awk '{ print $2 }') + apt_version_major=$(echo "$apt_version_full" | cut -d. -f1) + apt_version_minor=$(echo "$apt_version_full" | cut -d. -f2) + apt_version_modified="${apt_version_major}${apt_version_minor}0" + + echo "Detected apt version as $apt_version_full" +} + +main() { + if [ -z "$repo" ]; then + repo="crowdsec" + fi + + detect_os + case $os in + ubuntu | debian | raspbian | linuxmint) + detect_apt_version + gpg_check_deb + curl_check_deb + apt_source_path="/etc/apt/sources.list.d/crowdsec_${repo}.list" + pre_reqs="apt-transport-https ca-certificates curl" + if [ -f "$apt_source_path" ]; then + echo + echo "The file $apt_source_path already exists: overwriting it." + echo + fi + # needed dependencies + apt-get update -qq >/dev/null + #shellcheck disable=SC2086 + DEBIAN_FRONTEND=noninteractive apt-get install -y -qq $pre_reqs >/dev/null + # gpg keys + gpg_key_url="https://packagecloud.io/crowdsec/${repo}/gpgkey" + apt_keyrings_dir="/etc/apt/keyrings" + gpg_keyring_path="$apt_keyrings_dir/crowdsec_${repo}-archive-keyring.gpg" + gpg_key_path_old="/etc/apt/trusted.gpg.d/crowdsec_${repo}.gpg" + echo + echo "Importing packagecloud gpg key... " + echo + + # move gpg key to old path if apt version is older than 1.1 + if [ "$apt_version_modified" -lt 110 ]; then + curl -fsSL "$gpg_key_url" | gpg --dearmor >"$gpg_key_path_old" + # grant 644 permisions to gpg key path old + chmod 0644 "$gpg_key_path_old" + + # deletes the keyrings directory if it is empty + echo "Packagecloud gpg key imported to $gpg_key_path_old" + else + if [ ! -d "$apt_keyrings_dir" ]; then + install -d -m 0755 "$apt_keyrings_dir" + fi + # import the gpg key + curl -fsSL "$gpg_key_url" | gpg --dearmor >"$gpg_keyring_path" + # grant 644 permisions to gpg keyring path + chmod 0644 "$gpg_keyring_path" + + echo "Packagecloud gpg key imported to $gpg_keyring_path" + fi + echo + echo "Installing ${apt_source_path}..." + echo + echo "deb [signed-by=/etc/apt/keyrings/crowdsec_${repo}-archive-keyring.gpg] https://packagecloud.io/crowdsec/${repo}/any/ any main" >"$apt_source_path" + echo "deb-src [signed-by=/etc/apt/keyrings/crowdsec_${repo}-archive-keyring.gpg] https://packagecloud.io/crowdsec/${repo}/any/ any main" >>"$apt_source_path" + apt-get update -qq >/dev/null + + ;; + centos | rhel | fedora | redhatentrepriseserver | amzn | cloudlinux | almalinux | rocky | opensuse | ol) + if [ "$os" = "ol" ] && [ "$dist" = "7" ] || [ "$os" = "amzn" ] && [ "$dist" = "2" ]; then + rpm_repo_config_url="https://packagecloud.io/install/repositories/crowdsec/${repo}/config_file.repo?os=${os}&dist=${dist}&source=script" + else + rpm_repo_config_url="https://packagecloud.io/install/repositories/crowdsec/${repo}/config_file.repo?os=rpm_any&dist=rpm_any&source=script" + fi + if [ "$os" = "opensuse" ]; then + curl_check_zypper + rpm_repo_path=/etc/zypp/repos.d/crowdsec_${repo}.repo + else + curl_check_rpm + rpm_repo_path=/etc/yum.repos.d/crowdsec_${repo}.repo + fi + + echo "Downloading repository file: $rpm_repo_config_url" + + curl -sSf "$rpm_repo_config_url" >"$rpm_repo_path" + curl_exit_code=$? + if [ "$curl_exit_code" = "22" ]; then + echo + echo + echo "Unable to download repo config from: " + echo "$rpm_repo_config_url" + echo + echo "This usually happens if your operating system is not supported by " + echo "packagecloud.io, or this script's OS detection failed." + echo + echo "You can override the OS detection by setting os= and dist= prior to running this script." + echo "You can find a list of supported OSes and distributions on our website: https://packagecloud.io/docs#os_distro_version" + echo + echo "For example, to force CentOS 6: os=el dist=6 ./script.sh" + echo + echo "If you are running a supported OS, please file an issue at https://github.com/crowdsecurity/crowdsec." + [ -e "$rpm_repo_path" ] && rm "$rpm_repo_path" + exit 1 + elif [ "$curl_exit_code" = "35" ] || [ "$curl_exit_code" = "60" ]; then + echo + echo "curl is unable to connect to packagecloud.io over TLS when running: " + echo " curl $rpm_repo_config_url" + echo + echo "This is usually due to one of two things:" + echo + echo " 1.) Missing CA root certificates (make sure the ca-certificates package is installed)" + echo " 2.) An old version of libssl. Try upgrading libssl on your system to a more recent version" + echo + echo "Contact support@crowdsec.net with information about your system for help." + [ -e "$rpm_repo_path" ] && rm "$rpm_repo_path" + exit 1 + elif [ "$curl_exit_code" -gt "0" ]; then + echo + echo "Unable to run: " + echo " curl $rpm_repo_config_url" + echo + echo "Double check your curl installation and try again." + echo + echo "Please file an issue at https://github.com/crowdsecurity/crowdsec if you think the behavior is not intended" + [ -e "$rpm_repo_path" ] && rm "$rpm_repo_path" + exit 1 + else + echo "done." + fi + if [ "$os" = "opensuse" ]; then + zypper --gpg-auto-import-keys refresh "crowdsec_${repo}" + zypper --gpg-auto-import-keys refresh "crowdsec_${repo}-source" + else + echo "$os" + finalize_yum_repo + fi + ;; + *) + echo "Error This system is not supported (yet) by this script." + echo "Please have a look at documentation https://docs.crowdsec.net/ or" + echo "file an issue at https://github.com/crowdsecurity/crowdsec if you think" + echo "the behavior is not intended" + + exit 1 + ;; + esac + + echo +} + +if [ "$(id -u)" -ne 0 ]; then + echo "This script must be run as root" + echo + echo "file an issue at https://github.com/crowdsecurity/crowdsec if you think" + echo "the behavior is not intended" + exit 1 +fi + +main diff --git a/debian/13-trixie-luks/scripts/tailscale.sh b/debian/13-trixie-luks/scripts/tailscale.sh new file mode 100644 index 0000000..8ffd3f5 --- /dev/null +++ b/debian/13-trixie-luks/scripts/tailscale.sh @@ -0,0 +1,726 @@ +#!/bin/sh +# Copyright (c) Tailscale Inc & contributors +# SPDX-License-Identifier: BSD-3-Clause +# +# This script detects the current operating system, and installs +# Tailscale according to that OS's conventions. +# +# 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 + +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="" + APT_KEY_TYPE="" # Only for apt-based distros + APT_SYSTEMCTL_START=false # Only needs to be true for Kali + TRACK="${TRACK:-stable}" + TAILSCALE_VERSION="${TAILSCALE_VERSION:-}" + + case "$TRACK" in + stable|unstable) + ;; + *) + echo "unsupported track $TRACK" + exit 1 + ;; + esac + + 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") + # - UBUNTU_CODENAME: if it exists, use instead of VERSION_CODENAME + . /etc/os-release + VERSION_MAJOR="${VERSION_ID:-}" + VERSION_MAJOR="${VERSION_MAJOR%%.*}" + case "$ID" in + ubuntu|pop|neon|zorin|tuxedo) + OS="ubuntu" + if [ "${UBUNTU_CODENAME:-}" != "" ]; then + VERSION="$UBUNTU_CODENAME" + else + VERSION="$VERSION_CODENAME" + fi + PACKAGETYPE="apt" + # Third-party keyrings became the preferred method of + # installation in Ubuntu 20.04. + if [ "$VERSION_MAJOR" -lt 20 ]; then + APT_KEY_TYPE="legacy" + else + APT_KEY_TYPE="keyring" + fi + ;; + debian) + OS="$ID" + VERSION="$VERSION_CODENAME" + PACKAGETYPE="apt" + # Third-party keyrings became the preferred method of + # installation in Debian 11 (Bullseye). + if [ -z "${VERSION_ID:-}" ]; then + # rolling release. If you haven't kept current, that's on you. + APT_KEY_TYPE="keyring" + # 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 + elif [ "$VERSION_MAJOR" -lt 11 ]; then + APT_KEY_TYPE="legacy" + else + APT_KEY_TYPE="keyring" + fi + ;; + 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" + if [ "$VERSION_MAJOR" -lt 5 ]; then + APT_KEY_TYPE="legacy" + else + APT_KEY_TYPE="keyring" + fi + ;; + elementary) + OS="ubuntu" + VERSION="$UBUNTU_CODENAME" + PACKAGETYPE="apt" + if [ "$VERSION_MAJOR" -lt 6 ]; then + APT_KEY_TYPE="legacy" + else + APT_KEY_TYPE="keyring" + fi + ;; + industrial-os) + OS="debian" + PACKAGETYPE="apt" + if [ "$VERSION_MAJOR" -lt 5 ]; then + VERSION="buster" + APT_KEY_TYPE="legacy" + else + VERSION="bullseye" + APT_KEY_TYPE="keyring" + fi + ;; + parrot|mendel) + OS="debian" + PACKAGETYPE="apt" + if [ "$VERSION_MAJOR" -lt 5 ]; then + VERSION="buster" + APT_KEY_TYPE="legacy" + else + VERSION="bullseye" + APT_KEY_TYPE="keyring" + fi + ;; + galliumos) + OS="ubuntu" + PACKAGETYPE="apt" + VERSION="bionic" + APT_KEY_TYPE="legacy" + ;; + pureos|kaisen) + OS="debian" + PACKAGETYPE="apt" + VERSION="bullseye" + APT_KEY_TYPE="keyring" + ;; + raspbian) + OS="$ID" + VERSION="$VERSION_CODENAME" + PACKAGETYPE="apt" + # Third-party keyrings became the preferred method of + # installation in Raspbian 11 (Bullseye). + if [ "$VERSION_MAJOR" -lt 11 ]; then + APT_KEY_TYPE="legacy" + else + APT_KEY_TYPE="keyring" + fi + ;; + 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 + if [ "$VERSION_MAJOR" -lt 2021 ]; then + # Kali VERSION_ID is "kali-rolling", which isn't distinguishing + VERSION="buster" + APT_KEY_TYPE="legacy" + else + VERSION="bullseye" + APT_KEY_TYPE="keyring" + fi + ;; + Deepin|deepin) # https://github.com/tailscale/tailscale/issues/7862 + OS="debian" + PACKAGETYPE="apt" + if [ "$VERSION_MAJOR" -lt 20 ]; then + APT_KEY_TYPE="legacy" + VERSION="buster" + else + APT_KEY_TYPE="keyring" + VERSION="bullseye" + fi + ;; + 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 + if [ "$VERSION_MAJOR" -lt 4 ]; then + OS="ubuntu" + VERSION="$UBUNTU_CODENAME" + else + OS="debian" + VERSION="$DEBIAN_CODENAME" + fi + ;; + sparky) + OS="debian" + PACKAGETYPE="apt" + VERSION="$DEBIAN_CODENAME" + APT_KEY_TYPE="keyring" + ;; + centos) + OS="$ID" + VERSION="$VERSION_MAJOR" + PACKAGETYPE="dnf" + if [ "$VERSION" = "7" ]; then + PACKAGETYPE="yum" + fi + ;; + ol) + OS="oracle" + VERSION="$VERSION_MAJOR" + PACKAGETYPE="dnf" + if [ "$VERSION" = "7" ]; then + PACKAGETYPE="yum" + fi + ;; + rhel|miraclelinux) + OS="$ID" + if [ "$ID" = "miraclelinux" ]; then + OS="rhel" + fi + VERSION="$VERSION_MAJOR" + PACKAGETYPE="dnf" + if [ "$VERSION" = "7" ]; then + PACKAGETYPE="yum" + fi + ;; + fedora) + OS="$ID" + VERSION="" + PACKAGETYPE="dnf" + ;; + rocky|almalinux|nobara|openmandriva|sangoma|risios|cloudlinux|alinux|fedora-asahi-remix|ultramarine) + OS="fedora" + VERSION="" + PACKAGETYPE="dnf" + ;; + amzn) + OS="amazon-linux" + VERSION="$VERSION_ID" + PACKAGETYPE="yum" + ;; + xenenterprise) + OS="centos" + VERSION="$VERSION_MAJOR" + PACKAGETYPE="yum" + ;; + opensuse-leap|sles) + OS="opensuse" + VERSION="leap/$VERSION_ID" + PACKAGETYPE="zypper" + ;; + opensuse-tumbleweed) + OS="opensuse" + VERSION="tumbleweed" + PACKAGETYPE="zypper" + ;; + sle-micro-rancher) + OS="opensuse" + VERSION="leap/15.4" + PACKAGETYPE="zypper" + ;; + arch|archarm|endeavouros|blendos|garuda|archcraft|cachyos) + OS="arch" + VERSION="" # rolling release + PACKAGETYPE="pacman" + ;; + manjaro|manjaro-arm|biglinux) + OS="manjaro" + VERSION="" # rolling release + PACKAGETYPE="pacman" + ;; + alpine) + OS="$ID" + VERSION="$VERSION_ID" + PACKAGETYPE="apk" + ;; + postmarketos) + OS="alpine" + VERSION="$VERSION_ID" + PACKAGETYPE="apk" + ;; + nixos) + echo "Please add Tailscale to your NixOS configuration directly:" + echo + echo "services.tailscale.enable = true;" + exit 1 + ;; + 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 + ;; + void) + OS="$ID" + VERSION="" # rolling release + PACKAGETYPE="xbps" + ;; + gentoo) + OS="$ID" + VERSION="" # rolling release + PACKAGETYPE="emerge" + ;; + freebsd) + OS="$ID" + VERSION="$VERSION_MAJOR" + PACKAGETYPE="pkg" + ;; + osmc) + OS="debian" + PACKAGETYPE="apt" + VERSION="bullseye" + APT_KEY_TYPE="keyring" + ;; + photon) + OS="photon" + VERSION="$VERSION_MAJOR" + PACKAGETYPE="tdnf" + ;; + steamos) + echo "To install Tailscale on SteamOS, please follow the instructions here:" + echo "https://github.com/tailscale-dev/deck-tailscale" + exit 1 + ;; + + # 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 + + # 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 + + 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 + + # Step 2: having detected an OS we support, is it one of the + # versions we support? + OS_UNSUPPORTED= + case "$OS" in + ubuntu|debian|raspbian|centos|oracle|rhel|amazon-linux|opensuse|photon) + # 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 + ;; + fedora) + # All versions supported, no version checking required. + ;; + 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" ] && \ + [ "$VERSION" != "14" ] && \ + [ "$VERSION" != "15" ] + 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/$TRACK/#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 4: run the installation. + OSVERSION="$OS" + [ "$VERSION" != "" ] && OSVERSION="$OSVERSION $VERSION" + + # 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 + case "$PACKAGETYPE" in + apt) + export DEBIAN_FRONTEND=noninteractive + if [ "$APT_KEY_TYPE" = "legacy" ] && ! type gpg >/dev/null; then + $SUDO apt-get update + $SUDO apt-get install -y gnupg + fi + + set -x + $SUDO mkdir -p --mode=0755 /usr/share/keyrings + case "$APT_KEY_TYPE" in + legacy) + $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 + $SUDO chmod 0644 /etc/apt/sources.list.d/tailscale.list + ;; + keyring) + $CURL "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION.noarmor.gpg" | $SUDO tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null + $SUDO chmod 0644 /usr/share/keyrings/tailscale-archive-keyring.gpg + $CURL "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION.tailscale-keyring.list" | $SUDO tee /etc/apt/sources.list.d/tailscale.list + $SUDO chmod 0644 /etc/apt/sources.list.d/tailscale.list + ;; + esac + $SUDO apt-get update + 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 + if [ "$APT_SYSTEMCTL_START" = "true" ]; then + $SUDO systemctl enable --now tailscaled + $SUDO systemctl start tailscaled + fi + set +x + ;; + yum) + set -x + $SUDO yum install yum-utils -y + $SUDO yum-config-manager -y --add-repo "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION/tailscale.repo" + if [ -n "$TAILSCALE_VERSION" ]; then + $SUDO yum install "tailscale-$TAILSCALE_VERSION" -y + else + $SUDO yum install tailscale -y + fi + $SUDO systemctl enable --now tailscaled + set +x + ;; + dnf) + # DNF 5 has a different argument format; determine which one we have. + DNF_VERSION="3" + if LANG=C.UTF-8 dnf --version | grep -q '^dnf5 version'; then + 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 + + set -x + 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 --overwrite --from-repofile="https://pkgs.tailscale.com/$TRACK/$OS/$VERSION/tailscale.repo" + else + echo "unexpected: unknown dnf version $DNF_VERSION" + exit 1 + fi + if [ -n "$TAILSCALE_VERSION" ]; then + $SUDO dnf install -y "tailscale-$TAILSCALE_VERSION" + else + $SUDO dnf install -y tailscale + fi + $SUDO systemctl enable --now tailscaled + set +x + ;; + tdnf) + set -x + curl -fsSL "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION/tailscale.repo" > /etc/yum.repos.d/tailscale.repo + if [ -n "$TAILSCALE_VERSION" ]; then + $SUDO tdnf install -y "tailscale-$TAILSCALE_VERSION" + else + $SUDO tdnf install -y tailscale + fi + $SUDO systemctl enable --now tailscaled + set +x + ;; + zypper) + set -x + $SUDO rpm --import "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION/repo.gpg" + $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 + if [ -n "$TAILSCALE_VERSION" ]; then + $SUDO zypper --non-interactive install "tailscale=$TAILSCALE_VERSION" + else + $SUDO zypper --non-interactive install tailscale + fi + $SUDO systemctl enable --now tailscaled + set +x + ;; + pacman) + set -x + 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 + $SUDO systemctl enable --now tailscaled + set +x + ;; + pkg) + set -x + 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 + $SUDO service tailscaled enable + $SUDO service tailscaled start + set +x + ;; + apk) + set -x + if ! grep -Eq '^http.*/community$' /etc/apk/repositories; then + 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 + 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 + $SUDO rc-update add tailscale + $SUDO rc-service tailscale start + set +x + ;; + xbps) + set -x + 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 + set +x + ;; + emerge) + set -x + 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 + 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