mirror of
https://scm.tikali.ai/tikali/applications/monky/monky-deployd.git
synced 2026-09-18 05:36:15 +00:00
feat(install): read-only deploy token for the private package registry (v0.1.2)
The GitLab project is private (its parent groups are private, so it cannot be made public): the v0.1.1 one-liner answered 401 anonymously. install.sh gains --token / MONKY_DEPLOYD_TOKEN and sends `DEPLOY-TOKEN: <token>` (a GitLab deploy token, scope read_package_registry only, revocable) on every registry download, the script itself included; the token goes through a 0600 curl -K file (never the command line, the log or an xtrace). The grant is taken via --bootstrap-file when the script is piped (stdin IS the script). Ansible: monky_deployd_download_token (vaulted) -> DEPLOY-TOKEN header, no_log. Docs explain why, the token's scope and the --source gitea alternative (split-horizon Gitea, cbs/iac#102). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KLB7jieMNRkTsJ2epr4Ds1
This commit is contained in:
+45
-20
@@ -1,18 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
# monky-deployd installer — Ubuntu 26.04 (verified target).
|
||||
#
|
||||
# curl -fsSL https://scm.tikali.ai/tikali/applications/monky/monky-deployd/-/raw/main/packaging/install.sh \
|
||||
# | sudo bash -s -- --env env-qa-02 --site cbs [--transport sdk|proxy|system] [--version 0.1.1] \
|
||||
# [--enrol-jwt /path/monky-host.env-qa-02.jwt] [--laptop] [--source gitlab|gitea] < bootstrap.jwt
|
||||
# T=<read-only GitLab deploy token, scope read_package_registry> # from the install kit / OpenBao
|
||||
# curl -sSf -H "DEPLOY-TOKEN: $T" \
|
||||
# https://scm.tikali.ai/api/v4/projects/69/packages/generic/monky-deployd/0.1.2/install.sh \
|
||||
# | sudo bash -s -- --env env-qa-02 --site cbs --token "$T" --bootstrap-file bootstrap.jwt \
|
||||
# [--transport sdk|proxy|system] [--version 0.1.2] [--enrol-jwt /path/monky-host.env-qa-02.jwt] \
|
||||
# [--laptop] [--source gitlab|gitea]
|
||||
#
|
||||
# stdin (or --bootstrap-file): the ONE-TIME bootstrap deploy grant from the install kit
|
||||
# (GET /v1/backends/{id}/agent/install). The enrolment JWT is read from --enrol-jwt or
|
||||
# /etc/monky-deployd/enrol.jwt and is only needed when the host identity is not enrolled yet.
|
||||
# --token / MONKY_DEPLOYD_TOKEN: the GitLab project is PRIVATE (its parent groups are private, so it
|
||||
# cannot be made public); every download from the generic package registry — this script included —
|
||||
# sends `DEPLOY-TOKEN: <token>`. The token is read-only (read_package_registry), revocable, and is
|
||||
# never printed by this script. Not needed with --source gitea.
|
||||
# --bootstrap-file (or stdin when the script runs from a FILE): the ONE-TIME bootstrap deploy grant
|
||||
# from the install kit (GET /v1/backends/{id}/agent/install). The enrolment JWT is read from
|
||||
# --enrol-jwt or /etc/monky-deployd/enrol.jwt and is only needed when the host identity is not
|
||||
# enrolled yet.
|
||||
#
|
||||
# What it does (idempotent):
|
||||
# 1. apt: ziti-edge-tunnel (OpenZiti `jammy` suite) if absent, docker-compose-plugin, acl
|
||||
# 2. downloads the pinned monky-deployd_<ver>_amd64.deb + .sha256 from the scm.tikali.ai package registry
|
||||
# (--source gitea: the Gitea release, off-estate), verifies, installs
|
||||
# (DEPLOY-TOKEN header; --source gitea: the Gitea release, off-estate), verifies, installs
|
||||
# 3. enrols /opt/openziti/etc/identities/monky-host.<env>.json if absent (ziti-edge-tunnel enroll),
|
||||
# chown ziti:ziti 0600, switches ziti-edge-tunnel.service to `run-host` via a drop-in
|
||||
# 4. writes /etc/monky-deployd/config.yaml, ACLs so user monky-deployd can read the identity,
|
||||
@@ -21,22 +29,25 @@
|
||||
set -euo pipefail
|
||||
umask 077
|
||||
|
||||
DEFAULT_VERSION="0.1.1"
|
||||
# Download source. PRIMARY is the public GitLab project's generic package registry on scm.tikali.ai:
|
||||
# inside the estate gitea.cbs.tikali.net is split-horizon to jump1's RED EIP (10.10.0.175), which has
|
||||
# no HTTP ingress, so backend boxes cannot reach the Gitea mirror (cbs/iac#102); scm.tikali.ai they can.
|
||||
# `--source gitea` keeps the Gitea release as the off-estate alternative. --base-url / MONKY_DEPLOYD_BASE_URL
|
||||
# override the base for whichever layout is selected.
|
||||
DEFAULT_VERSION="0.1.2"
|
||||
# Download source. PRIMARY is the GitLab project's generic package registry on scm.tikali.ai: inside
|
||||
# the estate gitea.cbs.tikali.net is split-horizon to jump1's RED EIP (10.10.0.175), which has no HTTP
|
||||
# ingress, so backend boxes cannot reach the Gitea mirror (cbs/iac#102); scm.tikali.ai they can. The
|
||||
# project is PRIVATE (parent groups are private), so the registry needs the read-only deploy token
|
||||
# (--token / MONKY_DEPLOYD_TOKEN, sent as the DEPLOY-TOKEN header). `--source gitea` keeps the Gitea
|
||||
# release as the off-estate alternative (no token). --base-url / MONKY_DEPLOYD_BASE_URL override the
|
||||
# base for whichever layout is selected.
|
||||
GITLAB_BASE_URL="https://scm.tikali.ai/api/v4/projects/69/packages/generic/monky-deployd"
|
||||
GITEA_BASE_URL="https://gitea.cbs.tikali.net/mdella/monky-deployd"
|
||||
SOURCE="${MONKY_DEPLOYD_SOURCE:-gitlab}"
|
||||
BASE_URL="${MONKY_DEPLOYD_BASE_URL:-}"
|
||||
TOKEN="${MONKY_DEPLOYD_TOKEN:-}"
|
||||
OPENZITI_SUITE="${OPENZITI_SUITE:-jammy}"
|
||||
IDENTITY_DIR="/opt/openziti/etc/identities"
|
||||
ETC="/etc/monky-deployd"
|
||||
ENV_ID="" SITE="" TRANSPORT="sdk" VERSION="$DEFAULT_VERSION" ENROL_JWT="" BOOTSTRAP_FILE="" NO_RUN="" FORCE_CONFIG="" BAO_CA="" LAPTOP="false"
|
||||
|
||||
usage() { sed -n '2,20p' "$0"; exit "${1:-0}"; }
|
||||
usage() { if [ -f "$0" ]; then sed -n '2,28p' "$0"; else echo "monky-deployd install.sh — see README.md (Install)"; fi; exit "${1:-0}"; }
|
||||
die() { echo "install.sh: $*" >&2; exit 1; }
|
||||
log() { echo "==> $*"; }
|
||||
|
||||
@@ -51,6 +62,7 @@ while [ $# -gt 0 ]; do
|
||||
--bao-ca) BAO_CA="$2"; shift 2 ;;
|
||||
--base-url) BASE_URL="$2"; shift 2 ;;
|
||||
--source) SOURCE="$2"; shift 2 ;;
|
||||
--token) TOKEN="$2"; shift 2 ;;
|
||||
--laptop) LAPTOP="true"; shift ;;
|
||||
--no-run) NO_RUN=1; shift ;;
|
||||
--force-config) FORCE_CONFIG=1; shift ;;
|
||||
@@ -67,6 +79,9 @@ SITE="${SITE,,}"
|
||||
[[ "$SITE" =~ ^(cbs|pdx)$ ]] || die "site must be cbs|pdx"
|
||||
[[ "$TRANSPORT" =~ ^(sdk|proxy|system)$ ]] || die "transport must be sdk|proxy|system"
|
||||
[[ "$SOURCE" =~ ^(gitlab|gitea)$ ]] || die "source must be gitlab|gitea"
|
||||
# never let the token leak through xtrace / the environment of children
|
||||
{ set +x; } 2>/dev/null
|
||||
export -n MONKY_DEPLOYD_TOKEN 2>/dev/null || true
|
||||
IDENTITY="$IDENTITY_DIR/monky-host.$ENV_ID.json"
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
@@ -109,14 +124,23 @@ if [ "$installed" = "$VERSION" ]; then
|
||||
else
|
||||
tmp="$(mktemp -d)"; trap 'rm -rf "$tmp"' EXIT
|
||||
deb="monky-deployd_${VERSION}_amd64.deb"
|
||||
# the deploy token travels in a 0600 curl config file (-K), never on the command line, so neither
|
||||
# `ps` nor an xtrace shows it; the file dies with $tmp
|
||||
curlrc="$tmp/curlrc"; : > "$curlrc"; chmod 0600 "$curlrc"
|
||||
if [ "$SOURCE" = gitlab ]; then
|
||||
url="${BASE_URL:-$GITLAB_BASE_URL}/${VERSION}"
|
||||
if [ -n "$TOKEN" ]; then
|
||||
printf 'header = "DEPLOY-TOKEN: %s"\n' "$TOKEN" > "$curlrc"
|
||||
else
|
||||
echo "WARNING: no --token/MONKY_DEPLOYD_TOKEN: the scm.tikali.ai project is private, the download will 401 (use --source gitea off-estate)" >&2
|
||||
fi
|
||||
else
|
||||
url="${BASE_URL:-$GITEA_BASE_URL}/releases/download/v${VERSION}"
|
||||
fi
|
||||
log "downloading $deb from $url"
|
||||
curl -fsSL -o "$tmp/$deb" "$url/$deb"
|
||||
curl -fsSL -o "$tmp/$deb.sha256" "$url/$deb.sha256"
|
||||
log "downloading $deb from $url${TOKEN:+ (DEPLOY-TOKEN)}"
|
||||
curl -fsSL -K "$curlrc" -o "$tmp/$deb" "$url/$deb" || die "download of $deb failed (private registry: is the deploy token set and valid?)"
|
||||
curl -fsSL -K "$curlrc" -o "$tmp/$deb.sha256" "$url/$deb.sha256" || die "download of $deb.sha256 failed"
|
||||
rm -f "$curlrc"
|
||||
(cd "$tmp" && sha256sum -c "$deb.sha256") || die "sha256 mismatch on $deb"
|
||||
apt_update_once || true
|
||||
apt-get install -y -qq "$tmp/$deb"
|
||||
@@ -194,10 +218,11 @@ if [ "$TRANSPORT" = "proxy" ]; then
|
||||
printf 'ZITI_IDENTITY=%s\n' "$IDENTITY" > "$ETC/proxy.env"; chmod 0644 "$ETC/proxy.env"
|
||||
systemctl enable --now monky-deployd-proxy.service
|
||||
fi
|
||||
# bootstrap grant: stdin (the kit pipes it) or --bootstrap-file; 0600, owned by the agent so it can consume it
|
||||
# bootstrap grant: --bootstrap-file, or stdin — but ONLY when this script runs from a file: with
|
||||
# `curl … | bash -s --` stdin IS the script, so reading it here would swallow the rest of it
|
||||
grant=""
|
||||
if [ -n "$BOOTSTRAP_FILE" ]; then grant="$(tr -d '[:space:]' < "$BOOTSTRAP_FILE")"
|
||||
elif [ ! -t 0 ]; then grant="$(tr -d '[:space:]' </dev/stdin || true)"; fi
|
||||
elif [ ! -t 0 ] && [ -f "$0" ]; then grant="$(tr -d '[:space:]' </dev/stdin || true)"; fi
|
||||
if [ -n "$grant" ]; then
|
||||
printf '%s\n' "$grant" > "$ETC/bootstrap.jwt"
|
||||
chown monky-deployd:monky-deployd "$ETC/bootstrap.jwt"; chmod 0600 "$ETC/bootstrap.jwt"
|
||||
@@ -207,7 +232,7 @@ elif [ -s /var/lib/monky-deployd/bao.token ]; then
|
||||
else
|
||||
echo "WARNING: no bootstrap grant on stdin and no bao.token: the agent cannot check in until you provide one" >&2
|
||||
fi
|
||||
unset grant
|
||||
unset grant TOKEN
|
||||
|
||||
# --- 5. timer + first tick ----------------------------------------------------------------------------------
|
||||
systemctl daemon-reload
|
||||
|
||||
Reference in New Issue
Block a user