#!/usr/bin/env bash # Установка runinfra на Linux x86_64. # # curl -fsSL https://get.runinfra.ru | bash # curl -fsSL https://get.runinfra.ru | RUNINFRA_VERSION=0.1.0 bash # curl -fsSL https://get.runinfra.ru/install.sh | bash -s -- --version 0.1.0 # # Переменные: # RUNINFRA_DL — база артефактов (default: https://dl.runinfra.ru/releases) # RUNINFRA_VERSION — latest | semver (default: latest) # RUNINFRA_INSTALL_DIR — каталог бинаря (default: ~/runinfra/bin) # RUNINFRA_PUBKEY_FILE — локальный PEM (default: рядом со скриптом или с dl) set -euo pipefail DL_BASE="${RUNINFRA_DL:-https://dl.runinfra.ru/releases}" VERSION="${RUNINFRA_VERSION:-latest}" INSTALL_DIR="${RUNINFRA_INSTALL_DIR:-$HOME/runinfra/bin}" BIN_NAME="runinfra" usage() { cat <&2 usage >&2 exit 2 ;; esac done need_cmd() { if ! command -v "$1" >/dev/null 2>&1; then echo "требуется команда: $1" >&2 exit 1 fi } need_cmd curl need_cmd tar need_cmd openssl need_cmd jq OS="$(uname -s)" ARCH="$(uname -m)" if [[ "$OS" != "Linux" ]]; then echo "поддерживается только Linux (сейчас: $OS)" >&2 exit 1 fi if [[ "$ARCH" != "x86_64" ]]; then echo "поддерживается только x86_64 (сейчас: $ARCH)" >&2 exit 1 fi load_pubkey() { if [[ -n "${RUNINFRA_PUBKEY_FILE:-}" && -f "$RUNINFRA_PUBKEY_FILE" ]]; then cat "$RUNINFRA_PUBKEY_FILE" return fi local script_dir="" if [[ -n "${BASH_SOURCE[0]:-}" ]]; then script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" fi if [[ -n "$script_dir" && -f "$script_dir/release_pubkey.pem" ]]; then cat "$script_dir/release_pubkey.pem" return fi local pubkey_url="${RUNINFRA_PUBKEY_URL:-${DL_BASE}/release_pubkey.pem}" curl -fsSL "$pubkey_url" } WORK="$(mktemp -d)" cleanup() { rm -rf "$WORK"; } trap cleanup EXIT fetch_manifest() { if [[ "$VERSION" == "latest" ]]; then curl -fsSL "${DL_BASE}/latest.json" -o "$WORK/manifest.json" else curl -fsSL "${DL_BASE}/${VERSION}/manifest.json" -o "$WORK/manifest.json" fi } echo "==> runinfra install (version=${VERSION})" fetch_manifest RESOLVED_VERSION="$(jq -r '.version' "$WORK/manifest.json")" ARTIFACT="$(jq -r '.artifact' "$WORK/manifest.json")" SHA256_EXPECTED="$(jq -r '.sha256' "$WORK/manifest.json")" SIG_B64="$(jq -r '.sig' "$WORK/manifest.json")" ARTIFACT_URL="$(jq -r '.url // empty' "$WORK/manifest.json")" MIN_SUPPORTED="$(jq -r '.min_supported // empty' "$WORK/manifest.json")" if [[ -z "$ARTIFACT_URL" || "$ARTIFACT_URL" == "null" ]]; then ARTIFACT_URL="${DL_BASE}/${RESOLVED_VERSION}/${ARTIFACT}" fi if [[ "$VERSION" == "latest" && -n "$MIN_SUPPORTED" && "$MIN_SUPPORTED" != "null" ]]; then echo " latest: $RESOLVED_VERSION (min_supported: $MIN_SUPPORTED)" else echo " version: $RESOLVED_VERSION" fi echo "==> скачивание $ARTIFACT_URL" curl -fsSL "$ARTIFACT_URL" -o "$WORK/$ARTIFACT" SHA256_ACTUAL="" if command -v sha256sum >/dev/null 2>&1; then SHA256_ACTUAL="$(sha256sum "$WORK/$ARTIFACT" | awk '{print $1}')" else SHA256_ACTUAL="$(openssl dgst -sha256 "$WORK/$ARTIFACT" | awk '{print $NF}')" fi if [[ "$SHA256_ACTUAL" != "$SHA256_EXPECTED" ]]; then echo "sha256 mismatch" >&2 echo " expected: $SHA256_EXPECTED" >&2 echo " actual: $SHA256_ACTUAL" >&2 exit 1 fi echo "==> проверка ed25519-подписи" load_pubkey > "$WORK/pubkey.pem" printf '%s' "$SHA256_EXPECTED" > "$WORK/message" printf '%s' "$SIG_B64" | openssl base64 -d -A > "$WORK/sig.bin" if ! openssl pkeyutl -verify -pubin -inkey "$WORK/pubkey.pem" -rawin -in "$WORK/message" -sigfile "$WORK/sig.bin" >/dev/null 2>&1; then echo "подпись релиза не прошла проверку" >&2 exit 1 fi mkdir -p "$INSTALL_DIR" TMP_BIN="$INSTALL_DIR/.${BIN_NAME}.install.$$" tar -xzf "$WORK/$ARTIFACT" -C "$WORK" cp "$WORK/$BIN_NAME" "$TMP_BIN" chmod +x "$TMP_BIN" mv -f "$TMP_BIN" "$INSTALL_DIR/$BIN_NAME" echo "==> установлено: $INSTALL_DIR/$BIN_NAME" if command -v "$INSTALL_DIR/$BIN_NAME" >/dev/null 2>&1 || [[ -x "$INSTALL_DIR/$BIN_NAME" ]]; then echo "==> runinfra init" "$INSTALL_DIR/$BIN_NAME" init || true fi cat <