#!/usr/bin/env bash # KLYRN bootstrap. Served at https://get.klyrn.com # # curl -fsSL https://get.klyrn.com | bash # # This script deliberately does almost nothing: it checks the platform, # downloads the signed klyrn binary, verifies it, and hands over to # `klyrn install`, where every real step is a resumable, verifiable stage. # # Everything lives in one function that is called on the last line, so bash # has read the whole script before running any of it: a truncated download # does nothing, and no child process can swallow the rest of the script # from the pipe. set -euo pipefail KLYRN_TMP="" trap '[ -n "$KLYRN_TMP" ] && rm -rf "$KLYRN_TMP"' EXIT klyrn_bootstrap() { local DL CHANNEL VERSION PUBKEY OS_ID OS_VER OS_NAME ARCH TMP BIN_URL SHA DL="${KLYRN_DOWNLOAD_BASE:-https://dl.klyrn.com}" # The public install command installs stable, now that a stable release # exists (1.0.0). It stayed on beta until then because defaulting to a # channel with nothing in it would fail, and defaulting to "dev", which this # once did, silently hands a stranger whatever was last pushed there. # KLYRN_CHANNEL=beta still installs the newest pre-release on purpose. CHANNEL="${KLYRN_CHANNEL:-stable}" VERSION="${KLYRN_VERSION:-latest}" # ed25519 public key (hex) used to sign release manifests. The served copy # at get.klyrn.com has the current key injected; the repository copy is # empty so a build never trusts a key by accident. # # With no key there is nothing to verify against, and the sha256 check below # does not stand in for one: that checksum is read out of the same manifest # a signature would have authenticated, so anyone able to serve the manifest # serves their own binary and their own matching checksum. This used to # print a warning and install anyway. It refuses now. The realistic way the # key goes missing is not an attack but the injection step quietly failing, # which is exactly the case where a warning scrolls past and a root install # proceeds unverified. PUBKEY="${KLYRN_PUBKEY:-fffd32e16d789fba3328293d188af15fa57d7d4acc4fc5636f6cecf1d15e4a61}" say() { printf '\033[1m%s\033[0m\n' "$*"; } fail() { printf '\n\033[31m%s\033[0m\n' "$*" >&2; exit 1; } [ "$(id -u)" = "0" ] || fail "Run as root: curl -fsSL https://get.klyrn.com | sudo bash" command -v curl >/dev/null || fail "curl is required (apt-get install -y curl)" # Read os-release in a subshell: sourcing it here would overwrite VERSION. OS_ID="$(. /etc/os-release 2>/dev/null && echo "${ID:-}")" OS_VER="$(. /etc/os-release 2>/dev/null && echo "${VERSION_ID:-}")" OS_NAME="$(. /etc/os-release 2>/dev/null && echo "${PRETTY_NAME:-unknown}")" [ -n "$OS_ID" ] || fail "Cannot read /etc/os-release" [ "$OS_ID" = "ubuntu" ] && [ "$OS_VER" = "24.04" ] || \ fail "KLYRN V1 supports Ubuntu 24.04 LTS. This is ${OS_NAME}." case "$(uname -m)" in x86_64|amd64) ARCH=amd64 ;; aarch64|arm64) fail "KLYRN has never been run on arm64, so it does not install there yet. A binary can be built for it and the manifest has fields for it, but no arm64 machine has ever run KLYRN and nothing about it is tested: the package names, the PHP and MariaDB repositories and the systemd unit behaviour are all verified on x86_64 only. Shipping it untested would be worse than saying no. Use an x86_64 server. https://klyrn.com/docs/requirements/" ;; *) fail "KLYRN runs on x86_64. This machine reports $(uname -m)." ;; esac TMP="$(mktemp -d /tmp/klyrn-get.XXXXXX)" KLYRN_TMP="$TMP" if [ "$CHANNEL" = "beta" ]; then printf '\n\033[1mYou chose the beta channel.\033[0m\n' printf 'This installs a pre-release build. It is tested, and it is not finished:\n' printf 'use a fresh or non-critical server, and expect updates often.\n' printf 'What beta means: https://klyrn.com/docs/updates/\n\n' fi say "Downloading KLYRN (${CHANNEL}/${VERSION}, linux/${ARCH})" curl -fsSL "${DL}/${CHANNEL}/${VERSION}/manifest.json" -o "$TMP/manifest.json"