feat: add one-command alpha14 server installation #42

Merged
ochenstarik-ui merged 2 commits from codex/release-alpha14 into main 2026-08-15 15:52:21 +00:00
4 changed files with 218 additions and 9 deletions
Showing only changes of commit d206c2219e - Show all commits

View file

@ -16,8 +16,13 @@ usage() {
Usage:
smm-setup.sh [--tag TAG] [--repository OWNER/REPO] COMMAND [ARG...]
Commands are passed to the verified ochenstarik-server-monitor-manager.sh
asset from the selected immutable GitHub release. Common commands:
Convenience installation commands:
install-hub PUBLIC_HOST [HTTPS_PORT] [WG_PORT]
install-node
Other commands are passed to the verified ochenstarik-server-monitor-manager.sh
asset from the selected immutable GitHub release. Use -- before a command to
force pass-through. Common bootstrap commands:
install-agent | install-control | uninstall-agent | uninstall-control
backup-create | backup-restore | version
@ -37,6 +42,7 @@ require_command() {
command -v "$1" >/dev/null 2>&1 || die "required command is unavailable: $1"
}
pass_through=0
while [[ $# -gt 0 ]]; do
case "$1" in
--tag)
@ -54,6 +60,7 @@ while [[ $# -gt 0 ]]; do
exit 0
;;
--)
pass_through=1
shift
break
;;
@ -75,6 +82,20 @@ done
[[ "$REPOSITORY" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]] \
|| die "invalid repository: $REPOSITORY"
action="$1"
shift
if (( pass_through == 0 )); then
case "$action" in
install-hub)
[[ $# -ge 1 && $# -le 3 ]] \
|| die "install-hub requires PUBLIC_HOST [HTTPS_PORT] [WG_PORT]"
;;
install-node)
[[ $# -eq 0 ]] || die "install-node takes no arguments"
;;
esac
fi
require_command curl
require_command sha256sum
require_command mktemp
@ -99,4 +120,72 @@ curl -fsSL "$release_base/$INNER_ASSET.sha256" -o "$temporary_directory/$INNER_A
install -m 0755 "$temporary_directory/$INNER_ASSET" "$cached_script"
install -m 0644 "$temporary_directory/$INNER_ASSET.sha256" "$cached_checksum"
exec "$cached_script" "$@"
download_required_asset() {
local asset="$1"
if ! curl -fsSL "$release_base/$asset" -o "$temporary_directory/$asset"; then
case "$asset" in
server-monitor-manager-manifest.json|server-monitor-manager-manifest.sig|server-monitor-manager-manifest.pem)
die "required signed-release asset is unavailable: $asset"
;;
*)
die "required release asset is unavailable: $asset"
;;
esac
fi
}
download_platform_release() {
local platform archive_asset asset
case "$(uname -m)" in
x86_64) platform="linux-x64" ;;
aarch64|arm64) platform="linux-arm64" ;;
*) die "unsupported architecture: $(uname -m)" ;;
esac
archive_asset="server-monitor-manager-$platform.tar.gz"
for asset in \
"$archive_asset" \
"$archive_asset.sha256" \
server-monitor-manager-manifest.json \
server-monitor-manager-manifest.sig \
server-monitor-manager-manifest.pem; do
download_required_asset "$asset"
done
(
cd "$temporary_directory"
sha256sum -c "$archive_asset.sha256" >/dev/null
) || die "checksum verification failed for $RELEASE_TAG/$archive_asset"
downloaded_archive="$temporary_directory/$archive_asset"
}
if (( pass_through == 1 )); then
exec "$cached_script" "$action" "$@"
fi
case "$action" in
install-hub)
download_platform_release
archive="$downloaded_archive"
public_host="$1"
https_port="${2:-}"
wg_port="${3:-}"
if [[ -n "$https_port" ]]; then
"$cached_script" install-control "$archive" "$public_host" "$https_port"
else
"$cached_script" install-control "$archive" "$public_host"
fi
if [[ -n "$wg_port" ]]; then
exec "$cached_script" mesh-init "$public_host" "$wg_port"
fi
exec "$cached_script" mesh-init "$public_host"
;;
install-node)
download_platform_release
archive="$downloaded_archive"
exec "$cached_script" install-node "$archive"
;;
*)
exec "$cached_script" "$action" "$@"
;;
esac

View file

@ -4,7 +4,32 @@ Server Monitor Manager устанавливает Control (Hub) и Agent (Node)
Текущая версия предназначена для alpha-тестирования на Ubuntu Server 22.04/24.04 и Debian 12/13 (`amd64`, `arm64`, systemd). Hub должен иметь публичный IPv4-адрес или DNS-имя и доступный UDP-порт. Node может находиться за NAT без белого IP.
## Файлы релиза
## Быстрая установка
Скачайте и проверьте convenience installer из `v0.1.0-alpha.14`:
```bash
curl -fsSLO https://github.com/ochenstarik-ui/server-monitor-manager/releases/download/v0.1.0-alpha.14/smm-setup.sh
curl -fsSLO https://github.com/ochenstarik-ui/server-monitor-manager/releases/download/v0.1.0-alpha.14/smm-setup.sh.sha256
sha256sum -c smm-setup.sh.sha256
chmod 700 smm-setup.sh
```
На Hub установка Control и инициализация Mesh выполняются одной командой. Порты можно не указывать: по умолчанию используются HTTPS `7443` и WireGuard `51820`.
```bash
sudo ./smm-setup.sh install-hub hub.example.com 7443 51820
```
На Node команда сама выбирает `linux-x64` или `linux-arm64`, скачивает и проверяет релиз, затем запрашивает код `SMMNODE2`:
```bash
sudo ./smm-setup.sh install-node
```
Обе команды публично скачивают архив, его checksum, manifest, подпись и Fulcio-сертификат из одного неизменяемого тега. Отсутствие любого файла подписи прерывает установку; автоматического перехода на unsigned-режим нет. Опции `--tag` и `--repository` предназначены для явного выбора другого источника. Остальные команды bootstrap по-прежнему можно передавать напрямую; `-- COMMAND` принудительно включает сквозной режим.
## Ручная установка и файлы релиза
Скачайте из одного GitHub Release:
@ -19,7 +44,7 @@ Server Monitor Manager устанавливает Control (Hub) и Agent (Node)
Bootstrap проверяет подпись manifest, затем SHA-256 архива по manifest, и принимает в архиве только каталоги `agent`, `control`, `deploy` и `bootstrap`.
## 1. Установка главного сервера (Hub)
## 1. Ручная установка главного сервера (Hub)
```bash
sha256sum -c ochenstarik-server-monitor-manager.sh.sha256

View file

@ -12,7 +12,8 @@ Known release history:
- `v0.1.0-alpha.8` contains the v1 `server-monitor-manager-bootstrap-manifest.json` layout and an orphaned `server-monitor-manager-manifest.sig` without the corresponding manifest v2. Published assets remain immutable; the anomaly is documented rather than repaired in place.
- Tags `v0.1.0-alpha.10` and `v0.1.0-alpha.11` exist, but their Release pipelines failed before a GitHub Release was published. Those version numbers are burned and must not be moved, deleted, recreated, or reused.
- `v0.1.0-alpha.12` was published, but its Windows `SHA256SUMS` asset used CRLF and was not consumable by GNU `sha256sum -c`. The immutable release remains published as historical evidence; the correction is released under a higher version.
- `v0.1.0-alpha.13` corrected the checksum portability defect, but its keyless manifest signature lacked the published signing certificate required by production consumers. The immutable release remains published as historical evidence; the producer/consumer certificate contract is corrected under a higher version.
- `v0.1.0-alpha.12` was published with a keyless manifest signature but without the Fulcio signing certificate, so consumers cannot verify that signature. Its Windows `SHA256SUMS` asset also used CRLF and was not consumable by GNU `sha256sum -c`. The immutable release remains published as historical evidence; neither defect is repaired in place.
- `v0.1.0-alpha.13` corrected the checksum portability defect, but it was also published with a keyless manifest signature and without the Fulcio signing certificate required by production consumers. The immutable release remains published as historical evidence; the producer/consumer certificate contract is corrected under a higher version.
- `v0.1.0-alpha.14` is the first release whose contract requires the manifest, keyless signature, and Fulcio certificate to be published and verified together. Its tag may be created only from `main` after the release pull request, required CI, and a branch `workflow_dispatch` dry run of the Release pipeline are green.
Every release candidate must pass a branch `workflow_dispatch` run of the Release pipeline before its immutable version tag is created. The release owner has sole write ownership of version sources, `deploy/**`, `tests/bootstrap/**`, release workflows, the root README release status, and translated README release statuses. Other contributors request changes to those paths in their report; they do not edit or bump them directly. One pull request covers one release topic and may merge only after required CI is green.

View file

@ -17,6 +17,8 @@ v1_fixture="$root/tests/fixtures/alpha8-v1-release"
}
bash -n "$setup"
grep -Fq 'readonly DEFAULT_RELEASE_TAG="v0.1.0-alpha.14"' "$setup"
grep -Fq 'install-hub PUBLIC_HOST [HTTPS_PORT] [WG_PORT]' "$setup"
grep -Fxq ' install-node' "$setup"
if grep -Fq 'validate_control_url' "$setup" || grep -Fq '${CONTROL_URL%/}/control' "$setup"; then
printf '%s\n' 'temporary control URL workaround must not be present in smm-setup.sh' >&2
exit 1
@ -54,6 +56,8 @@ grep -Fq 'sha256sum -c SHA256SUMS' "$workflow"
grep -Fq -- '--output-certificate server-monitor-manager-manifest.pem' "$workflow"
grep -Fq 'server-monitor-manager-manifest.pem' "$workflow"
grep -Fq 'v0.1.0-alpha.13' "$policy"
grep -Fq 'v0.1.0-alpha.14' "$policy"
grep -Fq 'first release whose contract requires the manifest, keyless signature, and Fulcio certificate' "$policy"
grep -Fq 'Published release tags and their assets are immutable.' "$installer_contract"
grep -Fq 'publish a new, higher version tag' "$installer_contract"
@ -86,10 +90,34 @@ trap 'rm -rf -- "$work"' EXIT
mkdir -p "$work/bin" "$work/home"
cat >"$work/inner.sh" <<'INNER'
#!/usr/bin/env bash
printf 'INNER_COMMAND=%s\n' "$1"
set -Eeuo pipefail
printf 'INNER_ARGS='
printf '%s ' "$@"
printf '\n'
case "${1:-}" in
install-control|install-node)
archive="$2"
[[ "$archive" == */server-monitor-manager-linux-*.tar.gz ]] || exit 0
directory="$(dirname "$archive")"
for required in \
server-monitor-manager-manifest.json \
server-monitor-manager-manifest.sig \
server-monitor-manager-manifest.pem; do
[[ -s "$directory/$required" ]] || {
printf 'missing signed-release asset: %s\n' "$required" >&2
exit 1
}
done
;;
esac
INNER
chmod +x "$work/inner.sh"
inner_hash="$(sha256sum "$work/inner.sh" | cut -d' ' -f1)"
printf '%s\n' 'release archive fixture' >"$work/archive.tar.gz"
archive_hash="$(sha256sum "$work/archive.tar.gz" | cut -d' ' -f1)"
printf '%s\n' '{"schema":"smm-manifest/v2"}' >"$work/server-monitor-manager-manifest.json"
printf '%s\n' 'fixture-signature' >"$work/server-monitor-manager-manifest.sig"
printf '%s\n' 'fixture-certificate' >"$work/server-monitor-manager-manifest.pem"
cat >"$work/bin/curl" <<EOF_CURL
#!/usr/bin/env bash
set -Eeuo pipefail
@ -103,6 +131,11 @@ while [[ \$# -gt 0 ]]; do
esac
done
printf '%s\n' "\$url" >>'$work/urls'
asset="\${url##*/}"
if [[ "\${SMM_TEST_MISSING_ASSET:-}" == "\$asset" ]]; then
printf 'fixture asset unavailable: %s\n' "\$asset" >&2
exit 22
fi
case "\$url" in
*/ochenstarik-server-monitor-manager.sh)
cp '$work/inner.sh' "\$out"
@ -110,6 +143,15 @@ case "\$url" in
*/ochenstarik-server-monitor-manager.sh.sha256)
printf '%s %s\n' '$inner_hash' 'ochenstarik-server-monitor-manager.sh' >"\$out"
;;
*/server-monitor-manager-linux-x64.tar.gz|*/server-monitor-manager-linux-arm64.tar.gz)
cp '$work/archive.tar.gz' "\$out"
;;
*/server-monitor-manager-linux-x64.tar.gz.sha256|*/server-monitor-manager-linux-arm64.tar.gz.sha256)
printf '%s %s\n' '$archive_hash' "\${asset%.sha256}" >"\$out"
;;
*/server-monitor-manager-manifest.json|*/server-monitor-manager-manifest.sig|*/server-monitor-manager-manifest.pem)
cp '$work/'"\$asset" "\$out"
;;
*)
printf 'unexpected URL: %s\n' "\$url" >&2
exit 1
@ -117,10 +159,62 @@ case "\$url" in
esac
EOF_CURL
chmod +x "$work/bin/curl"
cat >"$work/bin/uname" <<'EOF_UNAME'
#!/usr/bin/env bash
printf '%s\n' "${SMM_TEST_ARCH:-x86_64}"
EOF_UNAME
chmod +x "$work/bin/uname"
HOME="$work/home" PATH="$work/bin:$PATH" bash "$setup" version >"$work/output"
grep -Fq 'INNER_COMMAND=version' "$work/output"
grep -Fq 'INNER_ARGS=version ' "$work/output"
grep -Fq '/releases/download/v0.1.0-alpha.14/ochenstarik-server-monitor-manager.sh' "$work/urls"
grep -Fq '/releases/download/v0.1.0-alpha.14/ochenstarik-server-monitor-manager.sh.sha256' "$work/urls"
if HOME="$work/home" PATH="$work/bin:$PATH" bash "$setup" install-hub >"$work/invalid.out" 2>&1; then
printf '%s\n' 'install-hub accepted a missing PUBLIC_HOST' >&2
exit 1
fi
grep -Fq 'install-hub requires PUBLIC_HOST [HTTPS_PORT] [WG_PORT]' "$work/invalid.out"
if HOME="$work/home" PATH="$work/bin:$PATH" bash "$setup" install-hub host 7443 51820 extra >"$work/invalid.out" 2>&1; then
printf '%s\n' 'install-hub accepted an extra argument' >&2
exit 1
fi
if HOME="$work/home" PATH="$work/bin:$PATH" bash "$setup" install-node extra >"$work/invalid.out" 2>&1; then
printf '%s\n' 'install-node accepted an argument' >&2
exit 1
fi
grep -Fq 'install-node takes no arguments' "$work/invalid.out"
HOME="$work/home" PATH="$work/bin:$PATH" bash "$setup" install-hub hub.example.com 7443 51820 >"$work/hub.out"
grep -Eq 'INNER_ARGS=install-control .*/server-monitor-manager-linux-x64.tar.gz hub.example.com 7443 ' "$work/hub.out"
grep -Fq 'INNER_ARGS=mesh-init hub.example.com 51820 ' "$work/hub.out"
HOME="$work/home" PATH="$work/bin:$PATH" bash "$setup" install-node >"$work/node.out"
grep -Eq 'INNER_ARGS=install-node .*/server-monitor-manager-linux-x64.tar.gz ' "$work/node.out"
SMM_TEST_ARCH=aarch64 HOME="$work/home" PATH="$work/bin:$PATH" bash "$setup" install-node >"$work/arm-node.out"
grep -Fq '/server-monitor-manager-linux-arm64.tar.gz' "$work/urls"
HOME="$work/home" PATH="$work/bin:$PATH" bash "$setup" -- install-node legacy.tar.gz >"$work/pass-through.out"
grep -Fq 'INNER_ARGS=install-node legacy.tar.gz ' "$work/pass-through.out"
for required in \
server-monitor-manager-manifest.json \
server-monitor-manager-manifest.sig \
server-monitor-manager-manifest.pem; do
for mode in node hub; do
if [[ "$mode" == node ]]; then
install_arguments=(install-node)
else
install_arguments=(install-hub hub.example.com)
fi
if SMM_TEST_MISSING_ASSET="$required" HOME="$work/home" PATH="$work/bin:$PATH" \
bash "$setup" "${install_arguments[@]}" >"$work/missing.out" 2>&1; then
printf '%s continued without %s\n' "$mode" "$required" >&2
exit 1
fi
grep -Fq "required signed-release asset is unavailable: $required" "$work/missing.out"
done
done
printf '%s\n' 'RELEASE_CONTRACT=PASS'