installer.sh 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. #!/bin/sh
  2. # Copyright (c) Tailscale Inc & AUTHORS
  3. # SPDX-License-Identifier: BSD-3-Clause
  4. #
  5. # This script detects the current operating system, and installs
  6. # Tailscale according to that OS's conventions.
  7. set -eu
  8. # All the code is wrapped in a main function that gets called at the
  9. # bottom of the file, so that a truncated partial download doesn't end
  10. # up executing half a script.
  11. main() {
  12. # Step 1: detect the current linux distro, version, and packaging system.
  13. #
  14. # We rely on a combination of 'uname' and /etc/os-release to find
  15. # an OS name and version, and from there work out what
  16. # installation method we should be using.
  17. #
  18. # The end result of this step is that the following three
  19. # variables are populated, if detection was successful.
  20. OS=""
  21. VERSION=""
  22. PACKAGETYPE=""
  23. APT_KEY_TYPE="" # Only for apt-based distros
  24. APT_SYSTEMCTL_START=false # Only needs to be true for Kali
  25. TRACK="${TRACK:-stable}"
  26. case "$TRACK" in
  27. stable|unstable)
  28. ;;
  29. *)
  30. echo "unsupported track $TRACK"
  31. exit 1
  32. ;;
  33. esac
  34. if [ -f /etc/os-release ]; then
  35. # /etc/os-release populates a number of shell variables. We care about the following:
  36. # - ID: the short name of the OS (e.g. "debian", "freebsd")
  37. # - VERSION_ID: the numeric release version for the OS, if any (e.g. "18.04")
  38. # - VERSION_CODENAME: the codename of the OS release, if any (e.g. "buster")
  39. # - UBUNTU_CODENAME: if it exists, use instead of VERSION_CODENAME
  40. . /etc/os-release
  41. case "$ID" in
  42. ubuntu|pop|neon|zorin|tuxedo)
  43. OS="ubuntu"
  44. if [ "${UBUNTU_CODENAME:-}" != "" ]; then
  45. VERSION="$UBUNTU_CODENAME"
  46. else
  47. VERSION="$VERSION_CODENAME"
  48. fi
  49. PACKAGETYPE="apt"
  50. # Third-party keyrings became the preferred method of
  51. # installation in Ubuntu 20.04.
  52. if expr "$VERSION_ID" : "2.*" >/dev/null; then
  53. APT_KEY_TYPE="keyring"
  54. else
  55. APT_KEY_TYPE="legacy"
  56. fi
  57. ;;
  58. debian)
  59. OS="$ID"
  60. VERSION="$VERSION_CODENAME"
  61. PACKAGETYPE="apt"
  62. # Third-party keyrings became the preferred method of
  63. # installation in Debian 11 (Bullseye).
  64. if [ -z "${VERSION_ID:-}" ]; then
  65. # rolling release. If you haven't kept current, that's on you.
  66. APT_KEY_TYPE="keyring"
  67. elif [ "$VERSION_ID" -lt 11 ]; then
  68. APT_KEY_TYPE="legacy"
  69. else
  70. APT_KEY_TYPE="keyring"
  71. fi
  72. ;;
  73. linuxmint)
  74. if [ "${UBUNTU_CODENAME:-}" != "" ]; then
  75. OS="ubuntu"
  76. VERSION="$UBUNTU_CODENAME"
  77. elif [ "${DEBIAN_CODENAME:-}" != "" ]; then
  78. OS="debian"
  79. VERSION="$DEBIAN_CODENAME"
  80. else
  81. OS="ubuntu"
  82. VERSION="$VERSION_CODENAME"
  83. fi
  84. PACKAGETYPE="apt"
  85. if [ "$VERSION_ID" -lt 5 ]; then
  86. APT_KEY_TYPE="legacy"
  87. else
  88. APT_KEY_TYPE="keyring"
  89. fi
  90. ;;
  91. elementary)
  92. OS="ubuntu"
  93. VERSION="$UBUNTU_CODENAME"
  94. PACKAGETYPE="apt"
  95. if [ "$VERSION_ID" -lt 6 ]; then
  96. APT_KEY_TYPE="legacy"
  97. else
  98. APT_KEY_TYPE="keyring"
  99. fi
  100. ;;
  101. parrot|mendel)
  102. OS="debian"
  103. PACKAGETYPE="apt"
  104. if [ "$VERSION_ID" -lt 5 ]; then
  105. VERSION="buster"
  106. APT_KEY_TYPE="legacy"
  107. else
  108. VERSION="bullseye"
  109. APT_KEY_TYPE="keyring"
  110. fi
  111. ;;
  112. galliumos)
  113. OS="ubuntu"
  114. PACKAGETYPE="apt"
  115. VERSION="bionic"
  116. APT_KEY_TYPE="legacy"
  117. ;;
  118. pureos|kaisen)
  119. OS="debian"
  120. PACKAGETYPE="apt"
  121. VERSION="bullseye"
  122. APT_KEY_TYPE="keyring"
  123. ;;
  124. raspbian)
  125. OS="$ID"
  126. VERSION="$VERSION_CODENAME"
  127. PACKAGETYPE="apt"
  128. # Third-party keyrings became the preferred method of
  129. # installation in Raspbian 11 (Bullseye).
  130. if [ "$VERSION_ID" -lt 11 ]; then
  131. APT_KEY_TYPE="legacy"
  132. else
  133. APT_KEY_TYPE="keyring"
  134. fi
  135. ;;
  136. kali)
  137. OS="debian"
  138. PACKAGETYPE="apt"
  139. YEAR="$(echo "$VERSION_ID" | cut -f1 -d.)"
  140. APT_SYSTEMCTL_START=true
  141. # Third-party keyrings became the preferred method of
  142. # installation in Debian 11 (Bullseye), which Kali switched
  143. # to in roughly 2021.x releases
  144. if [ "$YEAR" -lt 2021 ]; then
  145. # Kali VERSION_ID is "kali-rolling", which isn't distinguishing
  146. VERSION="buster"
  147. APT_KEY_TYPE="legacy"
  148. else
  149. VERSION="bullseye"
  150. APT_KEY_TYPE="keyring"
  151. fi
  152. ;;
  153. Deepin|deepin) # https://github.com/tailscale/tailscale/issues/7862
  154. OS="debian"
  155. PACKAGETYPE="apt"
  156. if [ "$VERSION_ID" -lt 20 ]; then
  157. APT_KEY_TYPE="legacy"
  158. VERSION="buster"
  159. else
  160. APT_KEY_TYPE="keyring"
  161. VERSION="bullseye"
  162. fi
  163. ;;
  164. pika)
  165. PACKAGETYPE="apt"
  166. # All versions of PikaOS are new enough to prefer keyring
  167. APT_KEY_TYPE="keyring"
  168. # Older versions of PikaOS are based on Ubuntu rather than Debian
  169. if [ "$VERSION_ID" -lt 4 ]; then
  170. OS="ubuntu"
  171. VERSION="$UBUNTU_CODENAME"
  172. else
  173. OS="debian"
  174. VERSION="$DEBIAN_CODENAME"
  175. fi
  176. ;;
  177. centos)
  178. OS="$ID"
  179. VERSION="$VERSION_ID"
  180. PACKAGETYPE="dnf"
  181. if [ "$VERSION" = "7" ]; then
  182. PACKAGETYPE="yum"
  183. fi
  184. ;;
  185. ol)
  186. OS="oracle"
  187. VERSION="$(echo "$VERSION_ID" | cut -f1 -d.)"
  188. PACKAGETYPE="dnf"
  189. if [ "$VERSION" = "7" ]; then
  190. PACKAGETYPE="yum"
  191. fi
  192. ;;
  193. rhel)
  194. OS="$ID"
  195. VERSION="$(echo "$VERSION_ID" | cut -f1 -d.)"
  196. PACKAGETYPE="dnf"
  197. if [ "$VERSION" = "7" ]; then
  198. PACKAGETYPE="yum"
  199. fi
  200. ;;
  201. fedora)
  202. OS="$ID"
  203. VERSION=""
  204. PACKAGETYPE="dnf"
  205. ;;
  206. rocky|almalinux|nobara|openmandriva|sangoma|risios|cloudlinux|alinux|fedora-asahi-remix)
  207. OS="fedora"
  208. VERSION=""
  209. PACKAGETYPE="dnf"
  210. ;;
  211. amzn)
  212. OS="amazon-linux"
  213. VERSION="$VERSION_ID"
  214. PACKAGETYPE="yum"
  215. ;;
  216. xenenterprise)
  217. OS="centos"
  218. VERSION="$(echo "$VERSION_ID" | cut -f1 -d.)"
  219. PACKAGETYPE="yum"
  220. ;;
  221. opensuse-leap|sles)
  222. OS="opensuse"
  223. VERSION="leap/$VERSION_ID"
  224. PACKAGETYPE="zypper"
  225. ;;
  226. opensuse-tumbleweed)
  227. OS="opensuse"
  228. VERSION="tumbleweed"
  229. PACKAGETYPE="zypper"
  230. ;;
  231. sle-micro-rancher)
  232. OS="opensuse"
  233. VERSION="leap/15.4"
  234. PACKAGETYPE="zypper"
  235. ;;
  236. arch|archarm|endeavouros|blendos|garuda|archcraft|cachyos)
  237. OS="arch"
  238. VERSION="" # rolling release
  239. PACKAGETYPE="pacman"
  240. ;;
  241. manjaro|manjaro-arm)
  242. OS="manjaro"
  243. VERSION="" # rolling release
  244. PACKAGETYPE="pacman"
  245. ;;
  246. alpine)
  247. OS="$ID"
  248. VERSION="$VERSION_ID"
  249. PACKAGETYPE="apk"
  250. ;;
  251. postmarketos)
  252. OS="alpine"
  253. VERSION="$VERSION_ID"
  254. PACKAGETYPE="apk"
  255. ;;
  256. nixos)
  257. echo "Please add Tailscale to your NixOS configuration directly:"
  258. echo
  259. echo "services.tailscale.enable = true;"
  260. exit 1
  261. ;;
  262. void)
  263. OS="$ID"
  264. VERSION="" # rolling release
  265. PACKAGETYPE="xbps"
  266. ;;
  267. gentoo)
  268. OS="$ID"
  269. VERSION="" # rolling release
  270. PACKAGETYPE="emerge"
  271. ;;
  272. freebsd)
  273. OS="$ID"
  274. VERSION="$(echo "$VERSION_ID" | cut -f1 -d.)"
  275. PACKAGETYPE="pkg"
  276. ;;
  277. osmc)
  278. OS="debian"
  279. PACKAGETYPE="apt"
  280. VERSION="bullseye"
  281. APT_KEY_TYPE="keyring"
  282. ;;
  283. photon)
  284. OS="photon"
  285. VERSION="$(echo "$VERSION_ID" | cut -f1 -d.)"
  286. PACKAGETYPE="tdnf"
  287. ;;
  288. # TODO: wsl?
  289. # TODO: synology? qnap?
  290. esac
  291. fi
  292. # If we failed to detect something through os-release, consult
  293. # uname and try to infer things from that.
  294. if [ -z "$OS" ]; then
  295. if type uname >/dev/null 2>&1; then
  296. case "$(uname)" in
  297. FreeBSD)
  298. # FreeBSD before 12.2 doesn't have
  299. # /etc/os-release, so we wouldn't have found it in
  300. # the os-release probing above.
  301. OS="freebsd"
  302. VERSION="$(freebsd-version | cut -f1 -d.)"
  303. PACKAGETYPE="pkg"
  304. ;;
  305. OpenBSD)
  306. OS="openbsd"
  307. VERSION="$(uname -r)"
  308. PACKAGETYPE=""
  309. ;;
  310. Darwin)
  311. OS="macos"
  312. VERSION="$(sw_vers -productVersion | cut -f1-2 -d.)"
  313. PACKAGETYPE="appstore"
  314. ;;
  315. Linux)
  316. OS="other-linux"
  317. VERSION=""
  318. PACKAGETYPE=""
  319. ;;
  320. esac
  321. fi
  322. fi
  323. # Ideally we want to use curl, but on some installs we
  324. # only have wget. Detect and use what's available.
  325. CURL=
  326. if type curl >/dev/null; then
  327. CURL="curl -fsSL"
  328. elif type wget >/dev/null; then
  329. CURL="wget -q -O-"
  330. fi
  331. if [ -z "$CURL" ]; then
  332. echo "The installer needs either curl or wget to download files."
  333. echo "Please install either curl or wget to proceed."
  334. exit 1
  335. fi
  336. TEST_URL="https://pkgs.tailscale.com/"
  337. RC=0
  338. TEST_OUT=$($CURL "$TEST_URL" 2>&1) || RC=$?
  339. if [ $RC != 0 ]; then
  340. echo "The installer cannot reach $TEST_URL"
  341. echo "Please make sure that your machine has internet access."
  342. echo "Test output:"
  343. echo $TEST_OUT
  344. exit 1
  345. fi
  346. # Step 2: having detected an OS we support, is it one of the
  347. # versions we support?
  348. OS_UNSUPPORTED=
  349. case "$OS" in
  350. ubuntu|debian|raspbian|centos|oracle|rhel|amazon-linux|opensuse|photon)
  351. # Check with the package server whether a given version is supported.
  352. URL="https://pkgs.tailscale.com/$TRACK/$OS/$VERSION/installer-supported"
  353. $CURL "$URL" 2> /dev/null | grep -q OK || OS_UNSUPPORTED=1
  354. ;;
  355. fedora)
  356. # All versions supported, no version checking required.
  357. ;;
  358. arch)
  359. # Rolling release, no version checking needed.
  360. ;;
  361. manjaro)
  362. # Rolling release, no version checking needed.
  363. ;;
  364. alpine)
  365. # All versions supported, no version checking needed.
  366. # TODO: is that true? When was tailscale packaged?
  367. ;;
  368. void)
  369. # Rolling release, no version checking needed.
  370. ;;
  371. gentoo)
  372. # Rolling release, no version checking needed.
  373. ;;
  374. freebsd)
  375. if [ "$VERSION" != "12" ] && \
  376. [ "$VERSION" != "13" ]
  377. then
  378. OS_UNSUPPORTED=1
  379. fi
  380. ;;
  381. openbsd)
  382. OS_UNSUPPORTED=1
  383. ;;
  384. macos)
  385. # We delegate macOS installation to the app store, it will
  386. # perform version checks for us.
  387. ;;
  388. other-linux)
  389. OS_UNSUPPORTED=1
  390. ;;
  391. *)
  392. OS_UNSUPPORTED=1
  393. ;;
  394. esac
  395. if [ "$OS_UNSUPPORTED" = "1" ]; then
  396. case "$OS" in
  397. other-linux)
  398. echo "Couldn't determine what kind of Linux is running."
  399. echo "You could try the static binaries at:"
  400. echo "https://pkgs.tailscale.com/$TRACK/#static"
  401. ;;
  402. "")
  403. echo "Couldn't determine what operating system you're running."
  404. ;;
  405. *)
  406. echo "$OS $VERSION isn't supported by this script yet."
  407. ;;
  408. esac
  409. echo
  410. echo "If you'd like us to support your system better, please email [email protected]"
  411. echo "and tell us what OS you're running."
  412. echo
  413. echo "Please include the following information we gathered from your system:"
  414. echo
  415. echo "OS=$OS"
  416. echo "VERSION=$VERSION"
  417. echo "PACKAGETYPE=$PACKAGETYPE"
  418. if type uname >/dev/null 2>&1; then
  419. echo "UNAME=$(uname -a)"
  420. else
  421. echo "UNAME="
  422. fi
  423. echo
  424. if [ -f /etc/os-release ]; then
  425. cat /etc/os-release
  426. else
  427. echo "No /etc/os-release"
  428. fi
  429. exit 1
  430. fi
  431. # Step 3: work out if we can run privileged commands, and if so,
  432. # how.
  433. CAN_ROOT=
  434. SUDO=
  435. if [ "$(id -u)" = 0 ]; then
  436. CAN_ROOT=1
  437. SUDO=""
  438. elif type sudo >/dev/null; then
  439. CAN_ROOT=1
  440. SUDO="sudo"
  441. elif type doas >/dev/null; then
  442. CAN_ROOT=1
  443. SUDO="doas"
  444. fi
  445. if [ "$CAN_ROOT" != "1" ]; then
  446. echo "This installer needs to run commands as root."
  447. echo "We tried looking for 'sudo' and 'doas', but couldn't find them."
  448. echo "Either re-run this script as root, or set up sudo/doas."
  449. exit 1
  450. fi
  451. # Step 4: run the installation.
  452. OSVERSION="$OS"
  453. [ "$VERSION" != "" ] && OSVERSION="$OSVERSION $VERSION"
  454. echo "Installing Tailscale for $OSVERSION, using method $PACKAGETYPE"
  455. case "$PACKAGETYPE" in
  456. apt)
  457. export DEBIAN_FRONTEND=noninteractive
  458. if [ "$APT_KEY_TYPE" = "legacy" ] && ! type gpg >/dev/null; then
  459. $SUDO apt-get update
  460. $SUDO apt-get install -y gnupg
  461. fi
  462. set -x
  463. $SUDO mkdir -p --mode=0755 /usr/share/keyrings
  464. case "$APT_KEY_TYPE" in
  465. legacy)
  466. $CURL "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION.asc" | $SUDO apt-key add -
  467. $CURL "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION.list" | $SUDO tee /etc/apt/sources.list.d/tailscale.list
  468. ;;
  469. keyring)
  470. $CURL "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION.noarmor.gpg" | $SUDO tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
  471. $CURL "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION.tailscale-keyring.list" | $SUDO tee /etc/apt/sources.list.d/tailscale.list
  472. ;;
  473. esac
  474. $SUDO apt-get update
  475. $SUDO apt-get install -y tailscale tailscale-archive-keyring
  476. if [ "$APT_SYSTEMCTL_START" = "true" ]; then
  477. $SUDO systemctl enable --now tailscaled
  478. $SUDO systemctl start tailscaled
  479. fi
  480. set +x
  481. ;;
  482. yum)
  483. set -x
  484. $SUDO yum install yum-utils -y
  485. $SUDO yum-config-manager -y --add-repo "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION/tailscale.repo"
  486. $SUDO yum install tailscale -y
  487. $SUDO systemctl enable --now tailscaled
  488. set +x
  489. ;;
  490. dnf)
  491. # DNF 5 has a different argument format; determine which one we have.
  492. DNF_VERSION="3"
  493. if dnf --version | grep -q '^dnf5 version'; then
  494. DNF_VERSION="5"
  495. fi
  496. # The 'config-manager' plugin wasn't implemented when
  497. # DNF5 was released; detect that and use the old
  498. # version if necessary.
  499. if [ "$DNF_VERSION" = "5" ]; then
  500. set -x
  501. $SUDO dnf install -y 'dnf-command(config-manager)' && DNF_HAVE_CONFIG_MANAGER=1 || DNF_HAVE_CONFIG_MANAGER=0
  502. set +x
  503. if [ "$DNF_HAVE_CONFIG_MANAGER" != "1" ]; then
  504. if type dnf-3 >/dev/null; then
  505. DNF_VERSION="3"
  506. else
  507. echo "dnf 5 detected, but 'dnf-command(config-manager)' not available and dnf-3 not found"
  508. exit 1
  509. fi
  510. fi
  511. fi
  512. set -x
  513. if [ "$DNF_VERSION" = "3" ]; then
  514. $SUDO dnf install -y 'dnf-command(config-manager)'
  515. $SUDO dnf config-manager --add-repo "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION/tailscale.repo"
  516. elif [ "$DNF_VERSION" = "5" ]; then
  517. # Already installed config-manager, above.
  518. $SUDO dnf config-manager addrepo --from-repofile="https://pkgs.tailscale.com/$TRACK/$OS/$VERSION/tailscale.repo"
  519. else
  520. echo "unexpected: unknown dnf version $DNF_VERSION"
  521. exit 1
  522. fi
  523. $SUDO dnf install -y tailscale
  524. $SUDO systemctl enable --now tailscaled
  525. set +x
  526. ;;
  527. tdnf)
  528. set -x
  529. curl -fsSL "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION/tailscale.repo" > /etc/yum.repos.d/tailscale.repo
  530. $SUDO tdnf install -y tailscale
  531. $SUDO systemctl enable --now tailscaled
  532. set +x
  533. ;;
  534. zypper)
  535. set -x
  536. $SUDO rpm --import "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION/repo.gpg"
  537. $SUDO zypper --non-interactive ar -g -r "https://pkgs.tailscale.com/$TRACK/$OS/$VERSION/tailscale.repo"
  538. $SUDO zypper --non-interactive --gpg-auto-import-keys refresh
  539. $SUDO zypper --non-interactive install tailscale
  540. $SUDO systemctl enable --now tailscaled
  541. set +x
  542. ;;
  543. pacman)
  544. set -x
  545. $SUDO pacman -S tailscale --noconfirm
  546. $SUDO systemctl enable --now tailscaled
  547. set +x
  548. ;;
  549. pkg)
  550. set -x
  551. $SUDO pkg install tailscale
  552. $SUDO service tailscaled enable
  553. $SUDO service tailscaled start
  554. set +x
  555. ;;
  556. apk)
  557. set -x
  558. if ! grep -Eq '^http.*/community$' /etc/apk/repositories; then
  559. if type setup-apkrepos >/dev/null; then
  560. $SUDO setup-apkrepos -c -1
  561. else
  562. echo "installing tailscale requires the community repo to be enabled in /etc/apk/repositories"
  563. exit 1
  564. fi
  565. fi
  566. $SUDO apk add tailscale
  567. $SUDO rc-update add tailscale
  568. $SUDO rc-service tailscale start
  569. set +x
  570. ;;
  571. xbps)
  572. set -x
  573. $SUDO xbps-install tailscale -y
  574. set +x
  575. ;;
  576. emerge)
  577. set -x
  578. $SUDO emerge --ask=n net-vpn/tailscale
  579. set +x
  580. ;;
  581. appstore)
  582. set -x
  583. open "https://apps.apple.com/us/app/tailscale/id1475387142"
  584. set +x
  585. ;;
  586. *)
  587. echo "unexpected: unknown package type $PACKAGETYPE"
  588. exit 1
  589. ;;
  590. esac
  591. echo "Installation complete! Log in to start using Tailscale by running:"
  592. echo
  593. if [ -z "$SUDO" ]; then
  594. echo "tailscale up"
  595. else
  596. echo "$SUDO tailscale up"
  597. fi
  598. }
  599. main