README: install and update from object storage
This commit is contained in:
+59
-18
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
# Runix installer — the one command that sets a host up.
|
||||
#
|
||||
# curl -fsSL https://vcs.astra-dev.online/svesnav/runix/raw/branch/main/install.sh | sudo sh
|
||||
# curl -fsSL https://runix-releases.s3-alpha-web.astra-dev.online/install.sh | sudo sh
|
||||
#
|
||||
# Asks what this host should be (control plane, agent, or both), checks
|
||||
# the prerequisites, installs under /opt/runix and wires up systemd.
|
||||
@@ -19,9 +19,15 @@
|
||||
set -eu
|
||||
|
||||
PREFIX=${RUNIX_PREFIX:-/opt/runix}
|
||||
# Releases are served from a Gitea instance by default. Point GITEA at a
|
||||
# GitHub-style host by clearing it (RUNIX_GITEA=) and setting a download
|
||||
# base, if you mirror the release elsewhere.
|
||||
# Releases are served from object storage by default: it needs no account,
|
||||
# so a plain `curl … | sh` works on a fresh box. The layout is
|
||||
#
|
||||
# <base>/latest.json names the newest version
|
||||
# <base>/<version>/<asset> the binaries, install.sh and SHA256SUMS
|
||||
#
|
||||
# Clear it (RUNIX_S3=) to fall back to the git forge below.
|
||||
S3_BASE=${RUNIX_S3:-https://runix-releases.s3-alpha-web.astra-dev.online}
|
||||
# The forge is the fallback source, used when S3_BASE is empty.
|
||||
GITEA=${RUNIX_GITEA:-https://vcs.astra-dev.online}
|
||||
REPO=${RUNIX_REPO:-svesnav/runix}
|
||||
VERSION=${RUNIX_VERSION:-latest}
|
||||
@@ -86,8 +92,9 @@ Options:
|
||||
--server-binary PATH Install a local control-plane build
|
||||
--agent-binary PATH Install a local agent build
|
||||
--version VERSION Release to install (default: latest)
|
||||
--repo OWNER/NAME Release repository (default: $REPO)
|
||||
--gitea URL Gitea instance serving releases (default: $GITEA)
|
||||
--s3 URL Object store serving releases (default: $S3_BASE)
|
||||
--repo OWNER/NAME Release repository, when not using --s3
|
||||
--gitea URL Gitea instance serving releases (fallback source)
|
||||
--repo-token TOK Read token, if the instance requires sign-in
|
||||
--prefix PATH Install root (default: $PREFIX)
|
||||
--no-start Install and configure, but do not start services
|
||||
@@ -95,7 +102,7 @@ Options:
|
||||
-h, --help Show this help
|
||||
|
||||
Environment equivalents: RUNIX_PREFIX, RUNIX_VERSION, RUNIX_REPO,
|
||||
RUNIX_GITEA, RUNIX_TOKEN, RUNIX_DATABASE_DSN, RUNIX_ADMIN_PASSWORD,
|
||||
RUNIX_S3, RUNIX_GITEA, RUNIX_TOKEN, RUNIX_DATABASE_DSN, RUNIX_ADMIN_PASSWORD,
|
||||
RUNIX_HTTP_HOST, RUNIX_AGENT_SERVER_URL, RUNIX_AGENT_TOKEN,
|
||||
RUNIX_POSTGRES_PORT.
|
||||
|
||||
@@ -125,7 +132,8 @@ while [ $# -gt 0 ]; do
|
||||
--agent-binary) AGENT_BIN="$2"; shift 2 ;;
|
||||
--version) VERSION="$2"; shift 2 ;;
|
||||
--repo) REPO="$2"; shift 2 ;;
|
||||
--gitea) GITEA="$2"; shift 2 ;;
|
||||
--s3) S3_BASE="$2"; shift 2 ;;
|
||||
--gitea) GITEA="$2"; S3_BASE=""; shift 2 ;;
|
||||
--repo-token|--github-token) DL_TOKEN="$2"; shift 2 ;;
|
||||
--prefix) PREFIX="$2"; shift 2 ;;
|
||||
--no-start) NO_START=1; shift ;;
|
||||
@@ -136,7 +144,9 @@ while [ $# -gt 0 ]; do
|
||||
done
|
||||
|
||||
if [ -z "$DOWNLOAD_BASE" ]; then
|
||||
if [ -n "$GITEA" ]; then
|
||||
if [ -n "$S3_BASE" ]; then
|
||||
DOWNLOAD_BASE="$S3_BASE"
|
||||
elif [ -n "$GITEA" ]; then
|
||||
DOWNLOAD_BASE="$GITEA/$REPO/releases"
|
||||
else
|
||||
DOWNLOAD_BASE="https://github.com/$REPO/releases"
|
||||
@@ -802,6 +812,16 @@ RESOLVED_TAG=""
|
||||
resolve_tag() {
|
||||
if [ "$VERSION" != latest ]; then RESOLVED_TAG="$VERSION"; return 0; fi
|
||||
[ -n "$RESOLVED_TAG" ] && return 0
|
||||
# Object storage serves no API, so the newest version is named in a
|
||||
# small manifest published beside the binaries.
|
||||
if [ -n "$S3_BASE" ]; then
|
||||
_man=$(mktemp)
|
||||
if fetch "$S3_BASE/latest.json" "$_man" "application/json"; then
|
||||
RESOLVED_TAG=$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$_man" | head -n1)
|
||||
fi
|
||||
rm -f "$_man"
|
||||
[ -n "$RESOLVED_TAG" ] && return 0
|
||||
fi
|
||||
if [ -n "$GITEA" ]; then
|
||||
_loc=$(redirect_of "$DOWNLOAD_BASE/latest" 2>/dev/null || true)
|
||||
RESOLVED_TAG=$(printf '%s' "$_loc" | sed -n 's#.*/releases/tag/##p')
|
||||
@@ -843,19 +863,26 @@ asset_id() {
|
||||
|
||||
# try_download NAME DEST — quiet, returns non-zero if the asset is absent.
|
||||
try_download() {
|
||||
_name=$1; _dest=$2
|
||||
if [ -n "$GITEA" ]; then
|
||||
# Distinct variable names: POSIX sh has no locals, and resolve_tag
|
||||
# below calls fetch, which would otherwise overwrite the _dest we were
|
||||
# handed — sending the binary to the manifest's temp file instead of
|
||||
# where the caller expects it.
|
||||
_tdname=$1; _tddest=$2
|
||||
if [ -n "$S3_BASE" ]; then
|
||||
resolve_tag || return 1
|
||||
fetch "$S3_BASE/$RESOLVED_TAG/$_tdname" "$_tddest" || return 1
|
||||
elif [ -n "$GITEA" ]; then
|
||||
# Gitea assets download by tag; the token (if any) rides in fetch.
|
||||
resolve_tag || return 1
|
||||
fetch "$DOWNLOAD_BASE/download/$RESOLVED_TAG/$_name" "$_dest" || return 1
|
||||
fetch "$DOWNLOAD_BASE/download/$RESOLVED_TAG/$_tdname" "$_tddest" || return 1
|
||||
elif [ -n "$DL_TOKEN" ]; then
|
||||
_id=$(asset_id "$_name") || return 1
|
||||
_id=$(asset_id "$_tdname") || return 1
|
||||
fetch "https://api.github.com/repos/$REPO/releases/assets/$_id" \
|
||||
"$_dest" "application/octet-stream" || return 1
|
||||
"$_tddest" "application/octet-stream" || return 1
|
||||
elif [ "$VERSION" = latest ]; then
|
||||
fetch "$DOWNLOAD_BASE/latest/download/$_name" "$_dest" || return 1
|
||||
fetch "$DOWNLOAD_BASE/latest/download/$_tdname" "$_tddest" || return 1
|
||||
else
|
||||
fetch "$DOWNLOAD_BASE/download/$VERSION/$_name" "$_dest" || return 1
|
||||
fetch "$DOWNLOAD_BASE/download/$VERSION/$_tdname" "$_tddest" || return 1
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -1016,6 +1043,14 @@ install_server() {
|
||||
mkdir -p "$PREFIX"
|
||||
install_binary runix-server "$SERVER_BIN"
|
||||
|
||||
# Applying an update from the UI replaces the binary in place, which
|
||||
# means writing a new file into this directory and renaming it over the
|
||||
# old one — so the service user has to own the directory, not just the
|
||||
# file. Without this the update fails with a bare permission error long
|
||||
# after the download has succeeded.
|
||||
chown "$SERVER_USER" "$BIN_DIR" 2>/dev/null || true
|
||||
chown "$SERVER_USER" "$BIN_DIR/runix-server" 2>/dev/null || true
|
||||
|
||||
[ "$DB_MODE" = docker ] && provision_postgres
|
||||
[ -n "$DSN" ] || fail "no database configured"
|
||||
|
||||
@@ -1094,7 +1129,11 @@ NoNewPrivileges=yes
|
||||
PrivateTmp=yes
|
||||
ProtectSystem=strict
|
||||
ProtectHome=yes
|
||||
ReadWritePaths=$CONFIG_DIR
|
||||
# The binary directory is writable so the control plane can replace its own
|
||||
# binary when an administrator applies an update from the UI. That is the
|
||||
# price of in-app updates: the service can rewrite the file it runs from.
|
||||
# Drop \$BIN_DIR here to forbid it, and upgrade by re-running this script.
|
||||
ReadWritePaths=$CONFIG_DIR $BIN_DIR
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1376,7 +1415,9 @@ fi
|
||||
if [ "$ROLE" = server ]; then
|
||||
echo
|
||||
echo " Add hosts from the UI (Servers → Add server), then run on each:"
|
||||
if [ -n "$GITEA" ]; then
|
||||
if [ -n "$S3_BASE" ]; then
|
||||
say " curl -fsSL $S3_BASE/install.sh | sudo sh -s -- \\"
|
||||
elif [ -n "$GITEA" ]; then
|
||||
say " curl -fsSL $GITEA/$REPO/raw/branch/main/install.sh | sudo sh -s -- \\"
|
||||
else
|
||||
say " curl -fsSL $DOWNLOAD_BASE/latest/download/install.sh | sudo sh -s -- \\"
|
||||
|
||||
Reference in New Issue
Block a user