stoke/scripts/install-apt.sh
kimi-reviewer-andresmgsl 33079afb33
Some checks failed
ci / test (pull_request) Has been cancelled
Harden publish/build/install scripts and fix audit findings
- publish-deb: keep the token out of the process list (curl -K config
  file via mktemp, no JSON round-trip through node argv), mktemp the
  response file with trap cleanup, add --max-time to the upload
- build-deb: umask 022 + chmod -R a+rX so the payload is world-readable
  even when built with umask 077
- install-apt: only fall back to [trusted=yes] on an actual signature
  verification failure; other apt-get update failures stay fatal
- auth logout: warn that a manually supplied token stays active on the
  server and point at the web UI revocation page
- repo import-batch: resolve the source token inside the per-item try so
  one bad item no longer aborts the whole batch
- auth status: print me.login (the /user response has no username field)
  and exit 1 when not authenticated
2026-07-26 23:07:16 +00:00

138 lines
5.9 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# One-time setup to install stoke via apt on Debian/Ubuntu.
#
# Adds the heavy-duty Forgejo Debian registry as an APT source (with its
# signing key) and installs the stoke package. Safe to re-run; afterwards
# stoke upgrades through regular `apt-get upgrade`.
#
# Usage:
# ./scripts/install-apt.sh
# FORGE_URL=... OWNER=... ./scripts/install-apt.sh # non-default instance
#
# Run as root or as a user with sudo.
set -euo pipefail
FORGE_URL="${FORGE_URL:-https://forgejo.heavyduty.builders}"
OWNER="${OWNER:-heavy-duty}"
DISTRIBUTION="${DISTRIBUTION:-stable}"
COMPONENT="${COMPONENT:-main}"
# Where apt configuration lives; overridable so tests can run against a
# throwaway directory instead of the real /etc/apt.
APT_ETC="${STOKE_APT_ETC:-/etc/apt}"
KEYRING="$APT_ETC/keyrings/forgejo-$OWNER.asc"
LIST="$APT_ETC/sources.list.d/forgejo-$OWNER.list"
SUDO=""
if [ "$(id -u)" -ne 0 ]; then
command -v sudo >/dev/null 2>&1 || { echo "error: run as root or install sudo" >&2; exit 1; }
SUDO="sudo"
fi
update_only_source() {
$SUDO apt-get update \
-o Dir::Etc::sourcelist="$1" \
-o Dir::Etc::sourceparts=/dev/null \
-o APT::Get::List-Cleanup=0
}
# stoke needs Node.js >= 22.12 (commander 15), but the distro archives of
# Debian 13 (nodejs 20.x) and Ubuntu 24.04 (nodejs 18.x) cannot satisfy
# that, which would make `apt-get install stoke` fail with an unmet
# dependency. When no configured source offers a new-enough nodejs, add the
# NodeSource repository for Node 22 so the dependency resolves.
NODE_MIN="22.12"
node_candidate_ok() {
local candidate
# LC_ALL=C: the "Candidate:" label is localized.
candidate="$(LC_ALL=C apt-cache policy nodejs 2>/dev/null | sed -n 's/^ Candidate: //p')"
[ -n "$candidate" ] && [ "$candidate" != "(none)" ] || return 1
dpkg --compare-versions "${candidate#*:}" ge "$NODE_MIN"
}
ensure_nodejs_source() {
node_candidate_ok && return 0
# The verdict may just be stale package lists — refresh (best effort, a
# transient failure of an unrelated source must not abort) and re-check
# before adding anything.
echo "No apt source seems to provide nodejs >= $NODE_MIN; refreshing apt metadata ..."
$SUDO apt-get update || true
node_candidate_ok && return 0
local ns_keyring="$APT_ETC/keyrings/nodesource.asc"
local ns_list="$APT_ETC/sources.list.d/nodesource.list"
if [ -e "$ns_list" ]; then
echo "error: even after refreshing apt metadata, no source provides nodejs >= $NODE_MIN," >&2
echo "and $ns_list already exists; refusing to overwrite it." >&2
echo "Point it at a Node >= 22 release (e.g. node_22.x) and re-run." >&2
exit 1
fi
echo "Adding NodeSource (Node 22) ..."
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | $SUDO tee "$ns_keyring" >/dev/null
echo "deb [signed-by=$ns_keyring] https://deb.nodesource.com/node_22.x nodistro main" \
| $SUDO tee "$ns_list" >/dev/null
# tee inherits our umask; apt's unprivileged _apt user must be able to
# read these.
$SUDO chmod 0644 "$ns_keyring" "$ns_list"
update_only_source "$ns_list"
node_candidate_ok || { echo "error: still no nodejs >= $NODE_MIN available after adding NodeSource" >&2; exit 1; }
}
echo "Adding APT source for $FORGE_URL/$OWNER ..."
$SUDO install -d -m 0755 "$APT_ETC/keyrings"
curl -fsSL "$FORGE_URL/api/packages/$OWNER/debian/repository.key" | $SUDO tee "$KEYRING" >/dev/null
echo "deb [signed-by=$KEYRING] $FORGE_URL/api/packages/$OWNER/debian $DISTRIBUTION $COMPONENT" \
| $SUDO tee "$LIST" >/dev/null
# tee inherits our umask; apt's unprivileged _apt user must be able to
# read these.
$SUDO chmod 0644 "$KEYRING" "$LIST"
# Fail fast with a clear message when the registry has no package published
# yet: without a Release file, `apt-get update` would only fail with a
# generic "repository does not have a Release file" error. A definitive 404
# is fatal; any other curl outcome (e.g. a network hiccup) is left for
# apt-get update to report.
RELEASE_URL="$FORGE_URL/api/packages/$OWNER/debian/dists/$DISTRIBUTION/Release"
if [ "$(curl -sSL -o /dev/null -w '%{http_code}' "$RELEASE_URL" || true)" = "404" ]; then
echo "error: no stoke package has been published to the $OWNER Debian registry yet" >&2
echo "($RELEASE_URL returned 404)." >&2
echo "Install stoke via npm or manually instead — see the README." >&2
exit 1
fi
# Newer apt verifies with sqv (Sequoia), which rejects the signature Forgejo
# currently produces for its Debian registry (malformed Ed25519 MPI encoding
# in the upstream signing library). Try the properly signed source first so
# this heals automatically once the forge is fixed; otherwise fall back to
# [trusted=yes] — package integrity then relies on HTTPS to our own forge.
# The fallback is only justified for an actual signature-verification
# failure: a transient network error must not permanently disable
# verification, so any other `apt-get update` failure is fatal.
update_failed=""
update_output="$(update_only_source "$LIST" 2>&1)" || update_failed=1
[ -z "$update_output" ] || echo "$update_output"
if [ -n "$update_failed" ]; then
if ! echo "$update_output" | grep -Eiq 'NO_PUBKEY|KEYEXPIRED|not signed|no longer signed|signature'; then
echo "error: apt-get update failed for the new source (see above), but not" >&2
echo "with a signature-verification error. Refusing to fall back to" >&2
echo "[trusted=yes]; fix the underlying problem and re-run." >&2
exit 1
fi
echo
echo "WARNING: signature verification failed (known Forgejo registry issue" >&2
echo "with sqv-based apt). Falling back to [trusted=yes]; transport" >&2
echo "security is provided by HTTPS to $FORGE_URL." >&2
echo
echo "deb [trusted=yes] $FORGE_URL/api/packages/$OWNER/debian $DISTRIBUTION $COMPONENT" \
| $SUDO tee "$LIST" >/dev/null
$SUDO chmod 0644 "$LIST"
update_only_source "$LIST"
fi
ensure_nodejs_source
$SUDO apt-get install -y stoke
echo
stoke --version >/dev/null && echo "stoke $(stoke --version) installed. Run: stoke auth login"