113 lines
3.9 KiB
Cheetah
113 lines
3.9 KiB
Cheetah
#!/bin/sh
|
|
set -e
|
|
# Nadir bootstrap installer.
|
|
#
|
|
# Detects the host architecture, fetches the latest release asset from the
|
|
# Gitea releases API, and installs it as a systemd service:
|
|
#
|
|
# curl -fsSL https://<existing-nadir-host>:<port>/install.sh | sudo sh
|
|
#
|
|
# The binary always comes from the Gitea release (not the source instance),
|
|
# so the installed copy is guaranteed to be the latest tagged build,
|
|
# independent of whatever version the serving host happens to be running.
|
|
#
|
|
# Everything is wrapped in do_install and invoked on the last line, the same
|
|
# pattern get.docker.com uses: when piped via `curl | sh`, sh executes while
|
|
# still receiving bytes from the network. Defining the whole body as a
|
|
# function before running anything means sh has fully parsed the script
|
|
# before do_install ever runs.
|
|
|
|
# Where to look for releases. Substituted at request time by the server
|
|
# (cmd/server/server.go) so the script knows which Gitea instance owns
|
|
# this deployment. Example: https://gitea.example.com/urania/nadir
|
|
RELEASE_REPO="__NADIR_RELEASE_REPO__"
|
|
|
|
do_install() {
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|
echo "this script must be run as root (try piping through 'sudo sh')" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v curl >/dev/null 2>&1; then
|
|
echo "curl is required" >&2
|
|
exit 1
|
|
fi
|
|
|
|
case "$(uname -m)" in
|
|
x86_64|amd64) arch=amd64 ;;
|
|
aarch64|arm64) arch=arm64 ;;
|
|
*) echo "unsupported architecture: $(uname -m) (only amd64 and arm64 are built)" >&2; exit 1 ;;
|
|
esac
|
|
|
|
api="$RELEASE_REPO/releases/latest"
|
|
api="${api%/}"
|
|
# Convert https://host/owner/repo/releases/latest into Gitea API form.
|
|
# Splits the URL once on '/' between host and path, inserts /api/v1/repos.
|
|
host=$(echo "$RELEASE_REPO" | awk -F/ '{print $1"//"$3}')
|
|
path=$(echo "$RELEASE_REPO" | awk -F/ '{print $4"/"$5}')
|
|
api="$host/api/v1/repos/$path/releases/latest"
|
|
|
|
echo "querying $api ..."
|
|
asset_url=$(curl -fsSL "$api" \
|
|
| grep -o '"browser_download_url":"[^"]*linux-'"$arch"'"' \
|
|
| head -n1 \
|
|
| cut -d'"' -f4)
|
|
|
|
if [ -z "$asset_url" ]; then
|
|
echo "no linux-$arch asset found in the latest release at $api" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "downloading $asset_url ..."
|
|
curl -f --progress-bar -L "$asset_url" -o /usr/local/bin/nadir.tmp
|
|
|
|
asset_name=$(basename "$asset_url")
|
|
|
|
# Verify SHA-256: download the checksums file published alongside the binary
|
|
# and confirm the hash matches. This catches CDN corruption and (together with
|
|
# the HTTPS transport) makes tampered binaries detectable.
|
|
sums_url="$host/api/v1/repos/$path/releases/latest"
|
|
sums_asset_url=$(curl -fsSL "$sums_url" \
|
|
| grep -o '"browser_download_url":"[^"]*sha256sums\.txt"' \
|
|
| head -n1 \
|
|
| cut -d'"' -f4)
|
|
|
|
if [ -n "$sums_asset_url" ]; then
|
|
echo "verifying checksum ..."
|
|
curl -fsSL "$sums_asset_url" -o /tmp/nadir-sha256sums.txt
|
|
# Extract the expected hash for our asset and compare.
|
|
expected=$(grep "$asset_name" /tmp/nadir-sha256sums.txt | awk '{print $1}')
|
|
actual=$(sha256sum /usr/local/bin/nadir.tmp | awk '{print $1}')
|
|
rm -f /tmp/nadir-sha256sums.txt
|
|
if [ -z "$expected" ]; then
|
|
echo "warning: sha256sums.txt does not contain a hash for $asset_name" >&2
|
|
echo "proceeding without verification" >&2
|
|
elif [ "$expected" != "$actual" ]; then
|
|
echo "SHA-256 MISMATCH: expected $expected, got $actual" >&2
|
|
echo "the downloaded binary may be corrupted or tampered with — aborting" >&2
|
|
rm -f /usr/local/bin/nadir.tmp
|
|
exit 1
|
|
else
|
|
echo "checksum OK ($actual)"
|
|
fi
|
|
else
|
|
echo "warning: no sha256sums.txt in release — skipping verification" >&2
|
|
fi
|
|
|
|
mv /usr/local/bin/nadir.tmp /usr/local/bin/nadir
|
|
chmod +x /usr/local/bin/nadir
|
|
|
|
echo "binary installed at /usr/local/bin/nadir"
|
|
echo "installing as a systemd service ..."
|
|
if [ -c /dev/tty ]; then
|
|
/usr/local/bin/nadir install < /dev/tty
|
|
else
|
|
/usr/local/bin/nadir install
|
|
fi
|
|
|
|
echo
|
|
echo "done. check status with: nadir status"
|
|
}
|
|
|
|
do_install
|