mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
1bfc1ce2c4
Bumps bundled Terraform from `1.15.2` to `1.15.5` across all pinned locations: - `.github/actions/setup-tf/action.yaml` - `scripts/Dockerfile.base` - `install.sh` - `flake.nix` (+ updated SRI hash for the linux_amd64 zip) - `mise.toml` - `mise.lock` (+ updated per-platform SHA256 checksums) - `provisioner/terraform/testdata/version.txt` - `provisioner/terraform/testdata/resources/ai-tasks-disabled/ai-tasks-disabled.tfplan.json` ## Why Terraform 1.15.5 is built with Go 1.25.10, while the 1.15.2 we currently ship was built with Go 1.25.8. The newer Go runtime addresses recent stdlib CVEs flagged by security scanners. Releases included: 1.15.3 (provider install crash fix, nested-module stack migration fix), 1.15.4 (Linux s390x builds, symlinked provider dir fix), 1.15.5. Release notes: https://github.com/hashicorp/terraform/releases/tag/v1.15.5 ## Cherry-pick #25747 mirrors this PR against `release/2.34`. Created on behalf of @Shelnutt2 Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
874 lines
21 KiB
Bash
Executable File
874 lines
21 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
# Coder's automatic install script.
|
|
# See https://github.com/coder/coder#install
|
|
#
|
|
# To run:
|
|
# curl -L https://coder.com/install.sh | sh
|
|
|
|
usage() {
|
|
arg0="$0"
|
|
if [ "$0" = sh ]; then
|
|
arg0="curl -fsSL https://coder.com/install.sh | sh -s --"
|
|
else
|
|
not_curl_usage="The latest script is available at https://coder.com/install.sh
|
|
"
|
|
fi
|
|
|
|
cath <<EOF
|
|
Installs Coder.
|
|
It tries to use the system package manager if possible.
|
|
After successful installation it explains how to start Coder.
|
|
|
|
Pass in user@host to install Coder on user@host over ssh.
|
|
The remote host must have internet access.
|
|
${not_curl_usage-}
|
|
Usage:
|
|
|
|
${arg0} [--dry-run] [--mainline | --stable | --version X.X.X] [--method detect] \
|
|
[--prefix ~/.local] [--rsh ssh] [user@host]
|
|
|
|
--dry-run
|
|
Echo the commands for the install process without running them.
|
|
|
|
--mainline
|
|
Install the latest mainline version (default).
|
|
|
|
--stable
|
|
Install the latest stable version instead of the latest mainline version.
|
|
|
|
--version X.X.X
|
|
Install a specific version instead of the latest.
|
|
|
|
--method [detect | standalone]
|
|
Choose the installation method. Defaults to detect.
|
|
- detect detects the system package manager and tries to use it.
|
|
Full reference on the process is further below.
|
|
- standalone installs a standalone release archive into /usr/local/bin
|
|
|
|
--prefix <dir>
|
|
Sets the prefix used by standalone release archives. Defaults to /usr/local
|
|
and the binary is copied into /usr/local/bin
|
|
To install in \$HOME, pass --prefix=\$HOME/.local
|
|
|
|
--binary-name <name>
|
|
Sets the name for the CLI in standalone release archives. Defaults to "coder"
|
|
To use the CLI as coder2, pass --binary-name=coder2
|
|
Note: in-product documentation will always refer to the CLI as "coder"
|
|
|
|
--rsh <bin>
|
|
Specifies the remote shell for remote installation. Defaults to ssh.
|
|
|
|
--with-terraform
|
|
Installs Terraform binary from https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/ source
|
|
alongside coder.
|
|
This is great for if you are having issues with Coder installing terraform, or if you
|
|
just want it on your base system aswell.
|
|
This supports most systems, however if you are unsure yours is supported you can check
|
|
the link above.
|
|
--net-admin
|
|
Adds \`CAP_NET_ADMIN\` to the installed binary. This allows Coder to
|
|
increase network speeds, but has security implications.
|
|
See: https://man7.org/linux/man-pages/man7/capabilities.7.html
|
|
This only works on Linux based systems.
|
|
|
|
|
|
The detection method works as follows:
|
|
- Debian, Ubuntu, Raspbian: install the deb package from GitHub.
|
|
- Fedora, CentOS, RHEL, openSUSE: install the rpm package from GitHub.
|
|
- Alpine: install the apk package from GitHub.
|
|
- macOS: if \`brew\` is available, install from the coder/coder Homebrew tap.
|
|
- Otherwise, download from GitHub and install into \`--prefix\`.
|
|
|
|
We build releases on GitHub for amd64, armv7, and arm64 on Windows, Linux, and macOS.
|
|
|
|
When the detection method tries to pull a release from GitHub it will
|
|
fall back to installing standalone when there is no matching release for
|
|
the system's operating system and architecture.
|
|
|
|
The installer will cache all downloaded assets into ~/.cache/coder
|
|
EOF
|
|
}
|
|
|
|
echo_latest_stable_version() {
|
|
url="https://github.com/coder/coder/releases/latest"
|
|
# https://gist.github.com/lukechilds/a83e1d7127b78fef38c2914c4ececc3c#gistcomment-2758860
|
|
response=$(curl -sSLI -o /dev/null -w "\n%{http_code} %{url_effective}" ${url})
|
|
status_code=$(echo "$response" | tail -n1 | cut -d' ' -f1)
|
|
version=$(echo "$response" | tail -n1 | cut -d' ' -f2-)
|
|
body=$(echo "$response" | sed '$d')
|
|
|
|
if [ "$status_code" != "200" ]; then
|
|
echoerr "GitHub API returned status code: ${status_code}"
|
|
echoerr "URL: ${url}"
|
|
exit 1
|
|
fi
|
|
|
|
version="${version#https://github.com/coder/coder/releases/tag/v}"
|
|
echo "${version}"
|
|
}
|
|
|
|
echo_latest_mainline_version() {
|
|
# Fetch the releases from the GitHub API, sort by version number,
|
|
# and take the first result. Note that we're sorting by space-
|
|
# separated numbers and without utilizing the sort -V flag for the
|
|
# best compatibility.
|
|
url="https://api.github.com/repos/coder/coder/releases"
|
|
response=$(curl -sSL -w "\n%{http_code}" ${url})
|
|
status_code=$(echo "$response" | tail -n1)
|
|
body=$(echo "$response" | sed '$d')
|
|
|
|
if [ "$status_code" != "200" ]; then
|
|
echoerr "GitHub API returned status code: ${status_code}"
|
|
echoerr "URL: ${url}"
|
|
echoerr "Response body: ${body}"
|
|
exit 1
|
|
fi
|
|
|
|
# Filter to strict semver (MAJOR.MINOR.PATCH) to exclude
|
|
# pre-release tags like RC builds from version resolution.
|
|
echo "$body" |
|
|
awk -F'"' '/"tag_name"/ {print $4}' |
|
|
tr -d v |
|
|
grep '^[0-9]\+\.[0-9]\+\.[0-9]\+$' |
|
|
tr . ' ' |
|
|
sort -k1,1nr -k2,2nr -k3,3nr |
|
|
head -n1 |
|
|
tr ' ' .
|
|
}
|
|
|
|
echo_standalone_postinstall() {
|
|
if [ "${DRY_RUN-}" ]; then
|
|
echo_dryrun_postinstall
|
|
return
|
|
fi
|
|
|
|
channel=
|
|
advisory="To install our stable release (v${STABLE_VERSION}), use the --stable flag. "
|
|
if [ "${STABLE}" = 1 ]; then
|
|
channel="stable "
|
|
advisory=""
|
|
fi
|
|
if [ "${MAINLINE}" = 1 ]; then
|
|
channel="mainline "
|
|
fi
|
|
|
|
cath <<EOF
|
|
|
|
Coder ${channel}release v${VERSION} installed. ${advisory}See our releases documentation or GitHub for more information on versioning.
|
|
|
|
The Coder binary has been placed in the following location:
|
|
|
|
$STANDALONE_INSTALL_PREFIX/bin/$STANDALONE_BINARY_NAME
|
|
|
|
EOF
|
|
|
|
CODER_COMMAND="$(command -v "$STANDALONE_BINARY_NAME" || true)"
|
|
|
|
if [ -z "${CODER_COMMAND}" ]; then
|
|
cath <<EOF
|
|
Extend your path to use Coder:
|
|
|
|
$ PATH="$STANDALONE_INSTALL_PREFIX/bin:\$PATH"
|
|
|
|
EOF
|
|
elif [ "$CODER_COMMAND" != "$STANDALONE_BINARY_LOCATION" ]; then
|
|
echo_path_conflict "$CODER_COMMAND"
|
|
else
|
|
cath <<EOF
|
|
To run a Coder server:
|
|
|
|
$ $STANDALONE_BINARY_NAME server
|
|
|
|
To connect to a Coder deployment:
|
|
|
|
$ $STANDALONE_BINARY_NAME login <deployment url>
|
|
|
|
EOF
|
|
fi
|
|
}
|
|
|
|
echo_brew_postinstall() {
|
|
if [ "${DRY_RUN-}" ]; then
|
|
echo_dryrun_postinstall
|
|
return
|
|
fi
|
|
|
|
BREW_PREFIX="$(brew --prefix)"
|
|
|
|
cath <<EOF
|
|
|
|
Coder has been installed to
|
|
|
|
$BREW_PREFIX/bin/coder
|
|
|
|
EOF
|
|
|
|
CODER_COMMAND="$(command -v "coder" || true)"
|
|
|
|
if [ "$CODER_COMMAND" != "$BREW_PREFIX/bin/coder" ]; then
|
|
echo_path_conflict "$CODER_COMMAND"
|
|
fi
|
|
|
|
cath <<EOF
|
|
To run a Coder server:
|
|
|
|
$ coder server
|
|
|
|
To connect to a Coder deployment:
|
|
|
|
$ coder login <deployment url>
|
|
|
|
EOF
|
|
}
|
|
|
|
echo_systemd_postinstall() {
|
|
if [ "${DRY_RUN-}" ]; then
|
|
echo_dryrun_postinstall
|
|
return
|
|
fi
|
|
|
|
echoh
|
|
cath <<EOF
|
|
$1 package has been installed.
|
|
|
|
To run a Coder server:
|
|
|
|
# Start Coder now and on reboot
|
|
$ sudo systemctl enable --now coder
|
|
$ journalctl -u coder.service -b
|
|
|
|
# Or just run the server directly
|
|
$ coder server
|
|
|
|
Configuring Coder: https://coder.com/docs/admin/setup
|
|
|
|
To connect to a Coder deployment:
|
|
|
|
$ coder login <deployment url>
|
|
|
|
EOF
|
|
}
|
|
|
|
echo_dryrun_postinstall() {
|
|
cath <<EOF
|
|
Dry-run complete.
|
|
|
|
To install Coder, re-run this script without the --dry-run flag.
|
|
|
|
EOF
|
|
}
|
|
|
|
echo_path_conflict() {
|
|
cath <<EOF
|
|
There is another binary in your PATH that conflicts with the binary we've installed.
|
|
|
|
$1
|
|
|
|
This is likely because of an existing installation of Coder in your \$PATH.
|
|
|
|
Run \`which -a coder\` to view all installations.
|
|
|
|
EOF
|
|
}
|
|
|
|
main() {
|
|
MAINLINE=1
|
|
STABLE=0
|
|
TERRAFORM_VERSION="1.15.5"
|
|
|
|
if [ "${TRACE-}" ]; then
|
|
set -x
|
|
fi
|
|
|
|
unset \
|
|
DRY_RUN \
|
|
METHOD \
|
|
OPTIONAL \
|
|
ALL_FLAGS \
|
|
RSH_ARGS \
|
|
RSH \
|
|
WITH_TERRAFORM \
|
|
CAP_NET_ADMIN
|
|
|
|
ALL_FLAGS=""
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
-*)
|
|
ALL_FLAGS="${ALL_FLAGS} $1"
|
|
;;
|
|
esac
|
|
|
|
case "$1" in
|
|
--dry-run)
|
|
DRY_RUN=1
|
|
;;
|
|
--method)
|
|
METHOD="$(parse_arg "$@")"
|
|
shift
|
|
;;
|
|
--method=*)
|
|
METHOD="$(parse_arg "$@")"
|
|
;;
|
|
--prefix)
|
|
STANDALONE_INSTALL_PREFIX="$(parse_arg "$@")"
|
|
shift
|
|
;;
|
|
--prefix=*)
|
|
STANDALONE_INSTALL_PREFIX="$(parse_arg "$@")"
|
|
;;
|
|
--binary-name)
|
|
STANDALONE_BINARY_NAME="$(parse_arg "$@")"
|
|
shift
|
|
;;
|
|
--binary-name=*)
|
|
STANDALONE_BINARY_NAME="$(parse_arg "$@")"
|
|
;;
|
|
--version)
|
|
VERSION="$(parse_arg "$@")"
|
|
MAINLINE=0
|
|
STABLE=0
|
|
shift
|
|
;;
|
|
--version=*)
|
|
VERSION="$(parse_arg "$@")"
|
|
MAINLINE=0
|
|
STABLE=0
|
|
;;
|
|
# Support edge for backward compatibility.
|
|
--mainline | --edge)
|
|
VERSION=
|
|
MAINLINE=1
|
|
STABLE=0
|
|
;;
|
|
--stable)
|
|
VERSION=
|
|
MAINLINE=0
|
|
STABLE=1
|
|
;;
|
|
--rsh)
|
|
RSH="$(parse_arg "$@")"
|
|
shift
|
|
;;
|
|
--rsh=*)
|
|
RSH="$(parse_arg "$@")"
|
|
;;
|
|
-h | --h | -help | --help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
--with-terraform)
|
|
WITH_TERRAFORM=1
|
|
;;
|
|
--net-admin)
|
|
CAP_NET_ADMIN=1
|
|
;;
|
|
--)
|
|
shift
|
|
# We remove the -- added above.
|
|
ALL_FLAGS="${ALL_FLAGS% --}"
|
|
RSH_ARGS="$*"
|
|
break
|
|
;;
|
|
-*)
|
|
echoerr "Unknown flag $1"
|
|
echoerr "Run with --help to see usage."
|
|
exit 1
|
|
;;
|
|
*)
|
|
RSH_ARGS="$*"
|
|
break
|
|
;;
|
|
esac
|
|
|
|
shift
|
|
done
|
|
|
|
if [ "${RSH_ARGS-}" ]; then
|
|
RSH="${RSH-ssh}"
|
|
echoh "Installing remotely with $RSH $RSH_ARGS"
|
|
curl -fsSL https://coder.com/install.sh | prefix "$RSH_ARGS" "$RSH" "$RSH_ARGS" sh -s -- "$ALL_FLAGS"
|
|
return
|
|
fi
|
|
|
|
# These can be overridden for testing but shouldn't normally be used as it can
|
|
# result in a broken coder.
|
|
OS=${OS:-$(os)}
|
|
ARCH=${ARCH:-$(arch)}
|
|
TERRAFORM_ARCH=${TERRAFORM_ARCH:-$(terraform_arch)}
|
|
|
|
# If we've been provided a flag which is specific to the standalone installation
|
|
# method, we should "detect" standalone to be the appropriate installation method.
|
|
# This check needs to occur before we set these variables with defaults.
|
|
if [ "${STANDALONE_INSTALL_PREFIX-}" ] || [ "${STANDALONE_BINARY_NAME-}" ]; then
|
|
METHOD=standalone
|
|
fi
|
|
|
|
METHOD="${METHOD-detect}"
|
|
if [ "$METHOD" != detect ] && [ "$METHOD" != standalone ]; then
|
|
echoerr "Unknown install method \"$METHOD\""
|
|
echoerr "Run with --help to see usage."
|
|
exit 1
|
|
fi
|
|
|
|
# We can't reasonably support installing specific versions of Coder through
|
|
# Homebrew, so if we're on macOS and the `--version` flag or the `--stable`
|
|
# flag (our tap follows mainline) was set, we should "detect" standalone to
|
|
# be the appropriate installation method. This check needs to occur before we
|
|
# set `VERSION` to a default of the latest release.
|
|
if [ "$OS" = "darwin" ] && { [ "${VERSION-}" ] || [ "${STABLE}" = 1 ]; }; then
|
|
METHOD=standalone
|
|
fi
|
|
|
|
# These are used by the various install_* functions that make use of GitHub
|
|
# releases in order to download and unpack the right release.
|
|
CACHE_DIR=$(echo_cache_dir)
|
|
TERRAFORM_INSTALL_PREFIX=${TERRAFORM_INSTALL_PREFIX:-/usr/local}
|
|
STANDALONE_INSTALL_PREFIX=${STANDALONE_INSTALL_PREFIX:-/usr/local}
|
|
STANDALONE_BINARY_NAME=${STANDALONE_BINARY_NAME:-coder}
|
|
STABLE_VERSION=$(echo_latest_stable_version)
|
|
if [ "${MAINLINE}" = 1 ]; then
|
|
VERSION=$(echo_latest_mainline_version)
|
|
echoh "Resolved mainline version: v${VERSION}"
|
|
elif [ "${STABLE}" = 1 ]; then
|
|
VERSION=${STABLE_VERSION}
|
|
echoh "Resolved stable version: v${VERSION}"
|
|
fi
|
|
|
|
distro_name
|
|
|
|
if [ "${DRY_RUN-}" ]; then
|
|
echoh "Running with --dry-run; the following are the commands that would be run if this were a real installation:"
|
|
echoh
|
|
fi
|
|
|
|
# Start by installing Terraform, if requested
|
|
if [ "${WITH_TERRAFORM-}" ]; then
|
|
with_terraform
|
|
fi
|
|
|
|
# If the version is the same as the stable version, we're installing
|
|
# the stable version.
|
|
if [ "${MAINLINE}" = 1 ] && [ "${VERSION}" = "${STABLE_VERSION}" ]; then
|
|
echoh "The latest mainline version has been promoted to stable, selecting stable."
|
|
MAINLINE=0
|
|
STABLE=1
|
|
fi
|
|
# If the manually specified version is stable, mark it as such.
|
|
if [ "${MAINLINE}" = 0 ] && [ "${STABLE}" = 0 ] && [ "${VERSION}" = "${STABLE_VERSION}" ]; then
|
|
STABLE=1
|
|
fi
|
|
|
|
# Standalone installs by pulling pre-built releases from GitHub.
|
|
if [ "$METHOD" = standalone ]; then
|
|
if has_standalone; then
|
|
install_standalone
|
|
exit 0
|
|
else
|
|
echoerr "There are no standalone releases for $ARCH"
|
|
echoerr "Please try again without '--method standalone'"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# DISTRO can be overridden for testing but shouldn't normally be used as it
|
|
# can result in a broken coder.
|
|
DISTRO=${DISTRO:-$(distro)}
|
|
|
|
case $DISTRO in
|
|
darwin) install_macos ;;
|
|
# The .deb and .rpm files are pulled from GitHub.
|
|
debian) install_deb ;;
|
|
fedora | opensuse) install_rpm ;;
|
|
# We don't have GitHub releases that work on Alpine or FreeBSD so we have no
|
|
# choice but to use npm here.
|
|
alpine) install_apk ;;
|
|
# For anything else we'll try to install standalone but fall back to npm if
|
|
# we don't have releases for the architecture.
|
|
*)
|
|
echoh "Unsupported package manager."
|
|
echoh "Falling back to standalone installation."
|
|
install_standalone
|
|
;;
|
|
esac
|
|
|
|
if [ "${CAP_NET_ADMIN:-}" ]; then
|
|
cap_net_admin
|
|
fi
|
|
}
|
|
|
|
cap_net_admin() {
|
|
if ! command_exists setcap && command_exists capsh; then
|
|
echo "Package 'libcap' not found. See install instructions for your distro: https://command-not-found.com/setcap"
|
|
return
|
|
fi
|
|
|
|
# Make sure we'e allowed to add CAP_NET_ADMIN.
|
|
if sudo_sh_c capsh --has-p=CAP_NET_ADMIN; then
|
|
sudo_sh_c setcap CAP_NET_ADMIN=+ep "$(command -v coder)" || true
|
|
|
|
# Unable to escalate perms, notify the user.
|
|
else
|
|
echo "Unable to setcap agent binary. Ensure the root user has CAP_NET_ADMIN permissions."
|
|
fi
|
|
}
|
|
|
|
parse_arg() {
|
|
case "$1" in
|
|
*=*)
|
|
# Remove everything after first equal sign.
|
|
opt="${1%%=*}"
|
|
# Remove everything before first equal sign.
|
|
optarg="${1#*=}"
|
|
if [ ! "$optarg" ] && [ ! "${OPTIONAL-}" ]; then
|
|
echoerr "$opt requires an argument"
|
|
echoerr "Run with --help to see usage."
|
|
exit 1
|
|
fi
|
|
echo "$optarg"
|
|
return
|
|
;;
|
|
esac
|
|
|
|
case "${2-}" in
|
|
"" | -*)
|
|
if [ ! "${OPTIONAL-}" ]; then
|
|
echoerr "$1 requires an argument"
|
|
echoerr "Run with --help to see usage."
|
|
exit 1
|
|
fi
|
|
;;
|
|
*)
|
|
echo "$2"
|
|
return
|
|
;;
|
|
esac
|
|
}
|
|
|
|
fetch() {
|
|
URL="$1"
|
|
FILE="$2"
|
|
|
|
if [ -e "$FILE" ]; then
|
|
echoh "+ Reusing $FILE"
|
|
return
|
|
fi
|
|
|
|
sh_c mkdir -p "$CACHE_DIR"
|
|
sh_c curl \
|
|
-#fL \
|
|
-o "$FILE.incomplete" \
|
|
-C - \
|
|
"$URL"
|
|
sh_c mv "$FILE.incomplete" "$FILE"
|
|
}
|
|
|
|
with_terraform() {
|
|
# Check if the unzip package is installed. If not error peacefully.
|
|
if ! (command_exists unzip); then
|
|
echoh
|
|
echoerr "This script needs the unzip package to run."
|
|
echoerr "Please install unzip to use this function"
|
|
exit 1
|
|
fi
|
|
echoh "Installing Terraform version $TERRAFORM_VERSION $TERRAFORM_ARCH from the HashiCorp release repository."
|
|
echoh
|
|
|
|
# Download from official source and save it to cache
|
|
fetch "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_${OS}_${TERRAFORM_ARCH}.zip" \
|
|
"$CACHE_DIR/terraform_${TERRAFORM_VERSION}_${OS}_${TERRAFORM_ARCH}.zip"
|
|
|
|
sh_c mkdir -p "$TERRAFORM_INSTALL_PREFIX" 2>/dev/null || true
|
|
|
|
sh_c="sh_c"
|
|
if [ ! -w "$TERRAFORM_INSTALL_PREFIX" ]; then
|
|
sh_c="sudo_sh_c"
|
|
fi
|
|
# Prepare /usr/local/bin/ and the binary for copying
|
|
"$sh_c" mkdir -p "$TERRAFORM_INSTALL_PREFIX/bin"
|
|
"$sh_c" unzip -d "$CACHE_DIR" -o "$CACHE_DIR/terraform_${TERRAFORM_VERSION}_${OS}_${ARCH}.zip"
|
|
COPY_LOCATION="$TERRAFORM_INSTALL_PREFIX/bin/terraform"
|
|
|
|
# Remove the file if it already exists to
|
|
# avoid https://github.com/coder/coder/issues/2086
|
|
if [ -f "$COPY_LOCATION" ]; then
|
|
"$sh_c" rm "$COPY_LOCATION"
|
|
fi
|
|
|
|
# Copy the binary to the correct location.
|
|
"$sh_c" cp "$CACHE_DIR/terraform" "$COPY_LOCATION"
|
|
}
|
|
|
|
install_macos() {
|
|
# If there is no `brew` binary available, just default to installing standalone
|
|
if command_exists brew; then
|
|
echoh "Installing coder with Homebrew from the coder/coder tap."
|
|
echoh
|
|
|
|
sh_c brew install coder/coder/coder
|
|
|
|
echo_brew_postinstall
|
|
return
|
|
fi
|
|
|
|
echoh "Homebrew is not available."
|
|
echoh "Falling back to standalone installation."
|
|
install_standalone
|
|
}
|
|
|
|
install_deb() {
|
|
echoh "Installing v$VERSION of the $ARCH deb package from GitHub."
|
|
echoh
|
|
|
|
fetch "https://github.com/coder/coder/releases/download/v$VERSION/coder_${VERSION}_${OS}_${ARCH}.deb" \
|
|
"$CACHE_DIR/coder_${VERSION}_$ARCH.deb"
|
|
sudo_sh_c dpkg --force-confdef --force-confold -i "$CACHE_DIR/coder_${VERSION}_$ARCH.deb"
|
|
|
|
echo_systemd_postinstall deb
|
|
}
|
|
|
|
install_rpm() {
|
|
echoh "Installing v$VERSION of the $ARCH rpm package from GitHub."
|
|
echoh
|
|
|
|
fetch "https://github.com/coder/coder/releases/download/v$VERSION/coder_${VERSION}_${OS}_${ARCH}.rpm" \
|
|
"$CACHE_DIR/coder_${VERSION}_${OS}_${ARCH}.rpm"
|
|
sudo_sh_c rpm -U "$CACHE_DIR/coder_${VERSION}_${OS}_${ARCH}.rpm"
|
|
|
|
echo_systemd_postinstall rpm
|
|
}
|
|
|
|
install_apk() {
|
|
echoh "Installing v$VERSION of the $ARCH apk package from GitHub."
|
|
echoh
|
|
|
|
fetch "https://github.com/coder/coder/releases/download/v$VERSION/coder_${VERSION}_${OS}_${ARCH}.apk" \
|
|
"$CACHE_DIR/coder_${VERSION}_${OS}_${ARCH}.apk"
|
|
sudo_sh_c apk add --allow-untrusted "$CACHE_DIR/coder_${VERSION}_${OS}_${ARCH}.apk"
|
|
|
|
echo_systemd_postinstall apk
|
|
}
|
|
|
|
install_standalone() {
|
|
echoh "Installing v$VERSION of the $ARCH release from GitHub."
|
|
echoh
|
|
|
|
# macOS releases are packaged as .zip
|
|
case $OS in
|
|
darwin) STANDALONE_ARCHIVE_FORMAT=zip ;;
|
|
*) STANDALONE_ARCHIVE_FORMAT=tar.gz ;;
|
|
esac
|
|
fetch "https://github.com/coder/coder/releases/download/v$VERSION/coder_${VERSION}_${OS}_${ARCH}.$STANDALONE_ARCHIVE_FORMAT" \
|
|
"$CACHE_DIR/coder_${VERSION}_${OS}_${ARCH}.$STANDALONE_ARCHIVE_FORMAT"
|
|
|
|
# -w only works if the directory exists so try creating it first. If this
|
|
# fails we can ignore the error as the -w check will then swap us to sudo.
|
|
sh_c mkdir -p "$STANDALONE_INSTALL_PREFIX" 2>/dev/null || true
|
|
|
|
sh_c mkdir -p "$CACHE_DIR/tmp"
|
|
if [ "$STANDALONE_ARCHIVE_FORMAT" = tar.gz ]; then
|
|
sh_c tar -C "$CACHE_DIR/tmp" -xzf "$CACHE_DIR/coder_${VERSION}_${OS}_${ARCH}.tar.gz"
|
|
else
|
|
sh_c unzip -d "$CACHE_DIR/tmp" -o "$CACHE_DIR/coder_${VERSION}_${OS}_${ARCH}.zip"
|
|
fi
|
|
|
|
STANDALONE_BINARY_LOCATION="$STANDALONE_INSTALL_PREFIX/bin/$STANDALONE_BINARY_NAME"
|
|
|
|
sh_c="sh_c"
|
|
if [ ! -w "$STANDALONE_INSTALL_PREFIX" ]; then
|
|
sh_c="sudo_sh_c"
|
|
fi
|
|
|
|
"$sh_c" mkdir -p "$STANDALONE_INSTALL_PREFIX/bin"
|
|
|
|
# Remove the file if it already exists to
|
|
# avoid https://github.com/coder/coder/issues/2086
|
|
if [ -f "$STANDALONE_BINARY_LOCATION" ]; then
|
|
"$sh_c" rm "$STANDALONE_BINARY_LOCATION"
|
|
fi
|
|
|
|
# Copy the binary to the correct location.
|
|
"$sh_c" cp "$CACHE_DIR/tmp/coder" "$STANDALONE_BINARY_LOCATION"
|
|
|
|
# Clean up the extracted files (note, not using sudo: $sh_c -> sh_c).
|
|
sh_c rm -rv "$CACHE_DIR/tmp"
|
|
|
|
echo_standalone_postinstall
|
|
}
|
|
|
|
# Determine if we have standalone releases on GitHub for the system's arch.
|
|
has_standalone() {
|
|
case $ARCH in
|
|
amd64) return 0 ;;
|
|
arm64) return 0 ;;
|
|
armv7)
|
|
[ "$(distro)" != darwin ]
|
|
return
|
|
;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
os() {
|
|
uname="$(uname)"
|
|
case $uname in
|
|
Linux) echo linux ;;
|
|
Darwin) echo darwin ;;
|
|
FreeBSD) echo freebsd ;;
|
|
*) echo "$uname" ;;
|
|
esac
|
|
}
|
|
|
|
# Print the detected Linux distro, otherwise print the OS name.
|
|
#
|
|
# Example outputs:
|
|
# - darwin -> darwin
|
|
# - freebsd -> freebsd
|
|
# - ubuntu, raspbian, debian ... -> debian
|
|
# - amzn, centos, rhel, fedora, ... -> fedora
|
|
# - opensuse-{leap,tumbleweed} -> opensuse
|
|
# - alpine -> alpine
|
|
# - arch -> arch
|
|
#
|
|
# Inspired by https://github.com/docker/docker-install/blob/26ff363bcf3b3f5a00498ac43694bf1c7d9ce16c/install.sh#L111-L120.
|
|
distro() {
|
|
if [ "$OS" = "darwin" ] || [ "$OS" = "freebsd" ]; then
|
|
echo "$OS"
|
|
return
|
|
fi
|
|
|
|
if [ -f /etc/os-release ]; then
|
|
(
|
|
# shellcheck disable=SC1091
|
|
. /etc/os-release
|
|
if [ "${ID_LIKE-}" ]; then
|
|
for id_like in $ID_LIKE; do
|
|
case "$id_like" in debian | fedora | opensuse)
|
|
echo "$id_like"
|
|
return
|
|
;;
|
|
esac
|
|
done
|
|
fi
|
|
|
|
echo "$ID"
|
|
)
|
|
return
|
|
fi
|
|
}
|
|
|
|
# Print a human-readable name for the OS/distro.
|
|
distro_name() {
|
|
if [ "$(uname)" = "Darwin" ]; then
|
|
echo "macOS v$(sw_vers -productVersion)"
|
|
return
|
|
fi
|
|
|
|
if [ -f /etc/os-release ]; then
|
|
(
|
|
# shellcheck disable=SC1091
|
|
. /etc/os-release
|
|
echo "$PRETTY_NAME"
|
|
)
|
|
return
|
|
fi
|
|
|
|
# Prints something like: Linux 4.19.0-9-amd64
|
|
uname -sr
|
|
}
|
|
|
|
arch() {
|
|
uname_m=$(uname -m)
|
|
case $uname_m in
|
|
aarch64) echo arm64 ;;
|
|
x86_64) echo amd64 ;;
|
|
armv7l) echo armv7 ;;
|
|
*) echo "$uname_m" ;;
|
|
esac
|
|
}
|
|
|
|
# The following is to change the naming, that way people with armv7 won't receive a error
|
|
# List of binaries can be found here: https://releases.hashicorp.com/terraform/
|
|
terraform_arch() {
|
|
uname_m=$(uname -m)
|
|
case $uname_m in
|
|
aarch64) echo arm64 ;;
|
|
x86_64) echo amd64 ;;
|
|
armv7l) echo arm ;;
|
|
*) echo "$uname_m" ;;
|
|
esac
|
|
}
|
|
|
|
command_exists() {
|
|
if [ ! "$1" ]; then return 1; fi
|
|
command -v "$@" >/dev/null
|
|
}
|
|
|
|
sh_c() {
|
|
echoh "+ $*"
|
|
if [ ! "${DRY_RUN-}" ]; then
|
|
sh -c "$*"
|
|
fi
|
|
}
|
|
|
|
sudo_sh_c() {
|
|
if [ "$(id -u)" = 0 ]; then
|
|
sh_c "$@"
|
|
elif command_exists sudo; then
|
|
sh_c "sudo $*"
|
|
elif command_exists doas; then
|
|
sh_c "doas $*"
|
|
elif command_exists su; then
|
|
sh_c "su - -c '$*'"
|
|
else
|
|
echoh
|
|
echoerr "This script needs to run the following command as root."
|
|
echoerr " $*"
|
|
echoerr "Please install sudo, su, or doas."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
echo_cache_dir() {
|
|
if [ "${XDG_CACHE_HOME-}" ]; then
|
|
echo "$XDG_CACHE_HOME/coder"
|
|
elif [ "${HOME-}" ]; then
|
|
echo "$HOME/.cache/coder"
|
|
else
|
|
echo "/tmp/coder-cache"
|
|
fi
|
|
}
|
|
|
|
echoh() {
|
|
echo "$@" | humanpath
|
|
}
|
|
|
|
cath() {
|
|
humanpath
|
|
}
|
|
|
|
echoerr() {
|
|
echoh "$@" >&2
|
|
}
|
|
|
|
# humanpath replaces all occurrences of " $HOME" with " ~"
|
|
# and all occurrences of '"$HOME' with the literal '"$HOME'.
|
|
humanpath() {
|
|
sed "s# $HOME# ~#g; s#\"$HOME#\"\$HOME#g"
|
|
}
|
|
|
|
# We need to make sure we exit with a non zero exit if the command fails.
|
|
# /bin/sh does not support -o pipefail unfortunately.
|
|
prefix() {
|
|
PREFIX="$1"
|
|
shift
|
|
fifo="$(mktemp -d)/fifo"
|
|
mkfifo "$fifo"
|
|
sed -e "s#^#$PREFIX: #" "$fifo" &
|
|
"$@" >"$fifo" 2>&1
|
|
}
|
|
|
|
main "$@"
|