installer.sh 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. #!/bin/sh
  2. # Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
  3. # Use of this source code is governed by a BSD-style
  4. # license that can be found in the LICENSE file.
  5. #
  6. # This script detects the current operating system, and installs
  7. # Tailscale according to that OS's conventions.
  8. set -eu
  9. # All the code is wrapped in a main function that gets called at the
  10. # bottom of the file, so that a truncated partial download doesn't end
  11. # up executing half a script.
  12. main() {
  13. # Step 1: detect the current linux distro, version, and packaging system.
  14. #
  15. # We rely on a combination of 'uname' and /etc/os-release to find
  16. # an OS name and version, and from there work out what
  17. # installation method we should be using.
  18. #
  19. # The end result of this step is that the following three
  20. # variables are populated, if detection was successful.
  21. OS=""
  22. VERSION=""
  23. PACKAGETYPE=""
  24. APT_KEY_TYPE="" # Only for apt-based distros
  25. if [ -f /etc/os-release ]; then
  26. # /etc/os-release populates a number of shell variables. We care about the following:
  27. # - ID: the short name of the OS (e.g. "debian", "freebsd")
  28. # - VERSION_ID: the numeric release version for the OS, if any (e.g. "18.04")
  29. # - VERSION_CODENAME: the codename of the OS release, if any (e.g. "buster")
  30. . /etc/os-release
  31. case "$ID" in
  32. ubuntu|pop|neon)
  33. OS="ubuntu"
  34. VERSION="$VERSION_CODENAME"
  35. PACKAGETYPE="apt"
  36. # Third-party keyrings became the preferred method of
  37. # installation in Ubuntu 20.04.
  38. if expr "$VERSION_ID" : "2.*" >/dev/null; then
  39. APT_KEY_TYPE="keyring"
  40. else
  41. APT_KEY_TYPE="legacy"
  42. fi
  43. ;;
  44. debian)
  45. OS="$ID"
  46. VERSION="$VERSION_CODENAME"
  47. PACKAGETYPE="apt"
  48. # Third-party keyrings became the preferred method of
  49. # installation in Debian 11 (Bullseye).
  50. if [ "$VERSION_ID" -lt 11 ]; then
  51. APT_KEY_TYPE="legacy"
  52. else
  53. APT_KEY_TYPE="keyring"
  54. fi
  55. ;;
  56. raspbian)
  57. OS="$ID"
  58. VERSION="$VERSION_CODENAME"
  59. PACKAGETYPE="apt"
  60. # Third-party keyrings became the preferred method of
  61. # installation in Raspbian 11 (Bullseye).
  62. if [ "$VERSION_ID" -lt 11 ]; then
  63. APT_KEY_TYPE="legacy"
  64. else
  65. APT_KEY_TYPE="keyring"
  66. fi
  67. ;;
  68. centos)
  69. OS="$ID"
  70. VERSION="$VERSION_ID"
  71. PACKAGETYPE="dnf"
  72. if [ "$VERSION" = "7" ]; then
  73. PACKAGETYPE="yum"
  74. fi
  75. ;;
  76. ol)
  77. OS="oracle"
  78. VERSION="$(echo "$VERSION_ID" | cut -f1 -d.)"
  79. PACKAGETYPE="dnf"
  80. if [ "$VERSION" = "7" ]; then
  81. PACKAGETYPE="yum"
  82. fi
  83. ;;
  84. rhel)
  85. OS="$ID"
  86. VERSION="$(echo "$VERSION_ID" | cut -f1 -d.)"
  87. PACKAGETYPE="dnf"
  88. ;;
  89. fedora)
  90. OS="$ID"
  91. VERSION=""
  92. PACKAGETYPE="dnf"
  93. ;;
  94. amzn)
  95. OS="amazon-linux"
  96. VERSION="$VERSION_ID"
  97. PACKAGETYPE="yum"
  98. ;;
  99. opensuse-leap)
  100. OS="opensuse"
  101. VERSION="leap/$VERSION_ID"
  102. PACKAGETYPE="zypper"
  103. ;;
  104. opensuse-tumbleweed)
  105. OS="opensuse"
  106. VERSION="tumbleweed"
  107. PACKAGETYPE="zypper"
  108. ;;
  109. arch)
  110. OS="$ID"
  111. VERSION="" # rolling release
  112. PACKAGETYPE="pacman"
  113. ;;
  114. manjaro)
  115. OS="$ID"
  116. VERSION="" # rolling release
  117. PACKAGETYPE="pacman"
  118. ;;
  119. alpine)
  120. OS="$ID"
  121. VERSION="$VERSION_ID"
  122. PACKAGETYPE="apk"
  123. ;;
  124. nixos)
  125. echo "Please add Tailscale to your NixOS configuration directly:"
  126. echo
  127. echo "services.tailscale.enable = true;"
  128. exit 1
  129. ;;
  130. void)
  131. OS="$ID"
  132. VERSION="" # rolling release
  133. PACKAGETYPE="xbps"
  134. ;;
  135. gentoo)
  136. OS="$ID"
  137. VERSION="" # rolling release
  138. PACKAGETYPE="emerge"
  139. ;;
  140. freebsd)
  141. OS="$ID"
  142. VERSION="$(echo "$VERSION_ID" | cut -f1 -d.)"
  143. PACKAGETYPE="pkg"
  144. ;;
  145. # TODO: wsl?
  146. # TODO: synology? qnap?
  147. esac
  148. fi
  149. # If we failed to detect something through os-release, consult
  150. # uname and try to infer things from that.
  151. if [ -z "$OS" ]; then
  152. if type uname >/dev/null 2>&1; then
  153. case "$(uname)" in
  154. FreeBSD)
  155. # FreeBSD before 12.2 doesn't have
  156. # /etc/os-release, so we wouldn't have found it in
  157. # the os-release probing above.
  158. OS="freebsd"
  159. VERSION="$(freebsd-version | cut -f1 -d.)"
  160. PACKAGETYPE="pkg"
  161. ;;
  162. OpenBSD)
  163. OS="openbsd"
  164. VERSION="$(uname -r)"
  165. PACKAGETYPE=""
  166. ;;
  167. Darwin)
  168. OS="macos"
  169. VERSION="$(sw_vers -productVersion | cut -f1-2 -d.)"
  170. PACKAGETYPE="appstore"
  171. ;;
  172. Linux)
  173. OS="other-linux"
  174. VERSION=""
  175. PACKAGETYPE=""
  176. ;;
  177. esac
  178. fi
  179. fi
  180. # Step 2: having detected an OS we support, is it one of the
  181. # versions we support?
  182. OS_UNSUPPORTED=
  183. case "$OS" in
  184. ubuntu)
  185. if [ "$VERSION" != "xenial" ] && \
  186. [ "$VERSION" != "bionic" ] && \
  187. [ "$VERSION" != "eoan" ] && \
  188. [ "$VERSION" != "focal" ] && \
  189. [ "$VERSION" != "groovy" ] && \
  190. [ "$VERSION" != "hirsute" ] && \
  191. [ "$VERSION" != "impish" ]
  192. then
  193. OS_UNSUPPORTED=1
  194. fi
  195. ;;
  196. debian)
  197. if [ "$VERSION" != "stretch" ] && \
  198. [ "$VERSION" != "buster" ] && \
  199. [ "$VERSION" != "bullseye" ] && \
  200. [ "$VERSION" != "bookworm" ] && \
  201. [ "$VERSION" != "sid" ]
  202. then
  203. OS_UNSUPPORTED=1
  204. fi
  205. ;;
  206. raspbian)
  207. if [ "$VERSION" != "buster" ] && \
  208. [ "$VERSION" != "bullseye" ]
  209. then
  210. OS_UNSUPPORTED=1
  211. fi
  212. ;;
  213. centos)
  214. if [ "$VERSION" != "7" ] && \
  215. [ "$VERSION" != "8" ]
  216. then
  217. OS_UNSUPPORTED=1
  218. fi
  219. ;;
  220. oracle)
  221. if [ "$VERSION" != "7" ] && \
  222. [ "$VERSION" != "8" ]
  223. then
  224. OS_UNSUPPORTED=1
  225. fi
  226. ;;
  227. rhel)
  228. if [ "$VERSION" != "8" ]
  229. then
  230. OS_UNSUPPORTED=1
  231. fi
  232. ;;
  233. amazon-linux)
  234. if [ "$VERSION" != "2" ]
  235. then
  236. OS_UNSUPPORTED=1
  237. fi
  238. ;;
  239. opensuse)
  240. if [ "$VERSION" != "leap/15.1" ] && \
  241. [ "$VERSION" != "leap/15.2" ] && \
  242. [ "$VERSION" != "leap/15.3" ] && \
  243. [ "$VERSION" != "tumbleweed" ]
  244. then
  245. OS_UNSUPPORTED=1
  246. fi
  247. ;;
  248. fedora)
  249. # All versions supported, no version checking required.
  250. ;;
  251. arch)
  252. # Rolling release, no version checking needed.
  253. ;;
  254. manjaro)
  255. # Rolling release, no version checking needed.
  256. ;;
  257. alpine)
  258. # All versions supported, no version checking needed.
  259. # TODO: is that true? When was tailscale packaged?
  260. ;;
  261. void)
  262. # Rolling release, no version checking needed.
  263. ;;
  264. gentoo)
  265. # Rolling release, no version checking needed.
  266. ;;
  267. freebsd)
  268. if [ "$VERSION" != "12" ] && \
  269. [ "$VERSION" != "13" ]
  270. then
  271. OS_UNSUPPORTED=1
  272. fi
  273. ;;
  274. openbsd)
  275. OS_UNSUPPORTED=1
  276. ;;
  277. macos)
  278. # We delegate macOS installation to the app store, it will
  279. # perform version checks for us.
  280. ;;
  281. other-linux)
  282. OS_UNSUPPORTED=1
  283. ;;
  284. *)
  285. OS_UNSUPPORTED=1
  286. ;;
  287. esac
  288. if [ "$OS_UNSUPPORTED" = "1" ]; then
  289. case "$OS" in
  290. other-linux)
  291. echo "Couldn't determine what kind of Linux is running."
  292. echo "You could try the static binaries at:"
  293. echo "https://pkgs.tailscale.com/stable/#static"
  294. ;;
  295. "")
  296. echo "Couldn't determine what operating system you're running."
  297. ;;
  298. *)
  299. echo "$OS $VERSION isn't supported by this script yet."
  300. ;;
  301. esac
  302. echo
  303. echo "If you'd like us to support your system better, please email [email protected]"
  304. echo "and tell us what OS you're running."
  305. echo
  306. echo "Please include the following information we gathered from your system:"
  307. echo
  308. echo "OS=$OS"
  309. echo "VERSION=$VERSION"
  310. echo "PACKAGETYPE=$PACKAGETYPE"
  311. if type uname >/dev/null 2>&1; then
  312. echo "UNAME=$(uname -a)"
  313. else
  314. echo "UNAME="
  315. fi
  316. echo
  317. if [ -f /etc/os-release ]; then
  318. cat /etc/os-release
  319. else
  320. echo "No /etc/os-release"
  321. fi
  322. exit 1
  323. fi
  324. # Step 3: work out if we can run privileged commands, and if so,
  325. # how.
  326. CAN_ROOT=
  327. SUDO=
  328. if [ "$(id -u)" = 0 ]; then
  329. CAN_ROOT=1
  330. SUDO=""
  331. elif type sudo >/dev/null; then
  332. CAN_ROOT=1
  333. SUDO="sudo"
  334. elif type doas >/dev/null; then
  335. CAN_ROOT=1
  336. SUDO="doas"
  337. fi
  338. if [ "$CAN_ROOT" != "1" ]; then
  339. echo "This installer needs to run commands as root."
  340. echo "We tried looking for 'sudo' and 'doas', but couldn't find them."
  341. echo "Either re-run this script as root, or set up sudo/doas."
  342. exit 1
  343. fi
  344. # Step 4: run the installation.
  345. echo "Installing Tailscale for $OS $VERSION, using method $PACKAGETYPE"
  346. case "$PACKAGETYPE" in
  347. apt)
  348. # Ideally we want to use curl, but on some installs we
  349. # only have wget. Detect and use what's available.
  350. CURL=
  351. if type curl >/dev/null; then
  352. CURL="curl -fsSL"
  353. elif type wget >/dev/null; then
  354. CURL="wget -q -O-"
  355. fi
  356. if [ -z "$CURL" ]; then
  357. echo "The installer needs either curl or wget to download files."
  358. echo "Please install either curl or wget to proceed."
  359. exit 1
  360. fi
  361. if ! type gpg >/dev/null; then
  362. echo "The installer needs gnupg to do keyring management."
  363. echo "Please install gnupg to proceed".
  364. exit 1
  365. fi
  366. set -x
  367. $SUDO mkdir -p --mode=0755 /usr/share/keyrings
  368. case "$APT_KEY_TYPE" in
  369. legacy)
  370. $CURL "https://pkgs.tailscale.com/stable/$OS/$VERSION.asc" | $SUDO apt-key add -
  371. $CURL "https://pkgs.tailscale.com/stable/$OS/$VERSION.list" | $SUDO tee /etc/apt/sources.list.d/tailscale.list
  372. ;;
  373. keyring)
  374. $CURL "https://pkgs.tailscale.com/stable/$OS/$VERSION.noarmor.gpg" | $SUDO tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
  375. $CURL "https://pkgs.tailscale.com/stable/$OS/$VERSION.tailscale-keyring.list" | $SUDO tee /etc/apt/sources.list.d/tailscale.list
  376. ;;
  377. esac
  378. $SUDO apt-get update
  379. $SUDO apt-get install tailscale
  380. set +x
  381. ;;
  382. yum)
  383. set -x
  384. $SUDO yum install yum-utils
  385. $SUDO yum-config-manager --add-repo "https://pkgs.tailscale.com/stable/$OS/$VERSION/tailscale.repo"
  386. $SUDO yum install tailscale
  387. $SUDO systemctl enable --now tailscaled
  388. set +x
  389. ;;
  390. dnf)
  391. set -x
  392. $SUDO dnf config-manager --add-repo "https://pkgs.tailscale.com/stable/$OS/$VERSION/tailscale.repo"
  393. $SUDO dnf install tailscale
  394. $SUDO systemctl enable --now tailscaled
  395. set +x
  396. ;;
  397. zypper)
  398. set -x
  399. $SUDO zypper ar -g -r "https://pkgs.tailscale.com/stable/$OS/$VERSION/tailscale.repo"
  400. $SUDO zypper ref
  401. $SUDO zypper in tailscale
  402. $SUDO systemctl enable --now tailscaled
  403. set +x
  404. ;;
  405. pacman)
  406. set -x
  407. $SUDO pacman -S tailscale
  408. $SUDO systemctl enable --now tailscaled
  409. set +x
  410. ;;
  411. apk)
  412. set -x
  413. $SUDO apk add tailscale
  414. $SUDO rc-update add tailscale
  415. set +x
  416. ;;
  417. xbps)
  418. set -x
  419. $SUDO xbps-install tailscale
  420. set +x
  421. ;;
  422. emerge)
  423. set -x
  424. $SUDO emerge net-vpn/tailscale
  425. set +x
  426. ;;
  427. appstore)
  428. set -x
  429. open "https://apps.apple.com/us/app/tailscale/id1475387142"
  430. set +x
  431. ;;
  432. *)
  433. echo "unexpected: unknown package type $PACKAGETYPE"
  434. exit 1
  435. ;;
  436. esac
  437. echo "Installation complete! Log in to start using Tailscale by running:"
  438. echo
  439. if [ -z "$SUDO" ]; then
  440. echo "tailscale up"
  441. else
  442. echo "$SUDO tailscale up"
  443. fi
  444. }
  445. main