installer.sh 8.9 KB

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