|
|
|
@@ -3,10 +3,10 @@
|
|
|
|
|
#
|
|
|
|
|
# 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 \
|
|
|
|
|
# https://scm.tikali.ai/api/v4/projects/69/packages/generic/monky-deployd/0.1.4/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]
|
|
|
|
|
# [--transport sdk|proxy|system] [--version 0.1.4] [--enrol-jwt /path/monky-host.env-qa-02.jwt] \
|
|
|
|
|
# [--laptop] [--source gitlab|gitea] [--docker-data-root /home/docker-data]
|
|
|
|
|
#
|
|
|
|
|
# --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 —
|
|
|
|
@@ -29,7 +29,7 @@
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
umask 077
|
|
|
|
|
|
|
|
|
|
DEFAULT_VERSION="0.1.2"
|
|
|
|
|
DEFAULT_VERSION="0.1.4"
|
|
|
|
|
# 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
|
|
|
|
@@ -45,7 +45,7 @@ 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"
|
|
|
|
|
ENV_ID="" SITE="" TRANSPORT="sdk" DOCKER_DATA_ROOT="" TUNNEL_FAILED="" DEPLOYD_VERSION="$DEFAULT_VERSION" ENROL_JWT="" BOOTSTRAP_FILE="" NO_RUN="" FORCE_CONFIG="" BAO_CA="" LAPTOP="false"
|
|
|
|
|
|
|
|
|
|
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; }
|
|
|
|
@@ -56,7 +56,8 @@ while [ $# -gt 0 ]; do
|
|
|
|
|
--env) ENV_ID="$2"; shift 2 ;;
|
|
|
|
|
--site) SITE="$2"; shift 2 ;;
|
|
|
|
|
--transport) TRANSPORT="$2"; shift 2 ;;
|
|
|
|
|
--version) VERSION="$2"; shift 2 ;;
|
|
|
|
|
--version) DEPLOYD_VERSION="$2"; shift 2 ;;
|
|
|
|
|
--docker-data-root) DOCKER_DATA_ROOT="$2"; shift 2 ;;
|
|
|
|
|
--enrol-jwt) ENROL_JWT="$2"; shift 2 ;;
|
|
|
|
|
--bootstrap-file) BOOTSTRAP_FILE="$2"; shift 2 ;;
|
|
|
|
|
--bao-ca) BAO_CA="$2"; shift 2 ;;
|
|
|
|
@@ -86,9 +87,13 @@ IDENTITY="$IDENTITY_DIR/monky-host.$ENV_ID.json"
|
|
|
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
|
|
|
|
|
|
|
|
if [ -r /etc/os-release ]; then
|
|
|
|
|
. /etc/os-release
|
|
|
|
|
if [ "${ID:-}" != "ubuntu" ] || [ "${VERSION_ID:-}" != "26.04" ]; then
|
|
|
|
|
echo "WARNING: verified on Ubuntu 26.04; this is ${PRETTY_NAME:-unknown}. Continuing." >&2
|
|
|
|
|
# read os-release in a SUBSHELL: it defines VERSION/NAME/ID/... and sourcing it inline clobbered
|
|
|
|
|
# this script's own variables (0.1.2 → "26.04 LTS (Resolute Raccoon)" on the env-qa-02 pilot)
|
|
|
|
|
OS_ID=$(. /etc/os-release; printf '%s' "${ID:-}")
|
|
|
|
|
OS_VERSION_ID=$(. /etc/os-release; printf '%s' "${VERSION_ID:-}")
|
|
|
|
|
OS_CODENAME=$(. /etc/os-release; printf '%s' "${VERSION_CODENAME:-${UBUNTU_CODENAME:-}}")
|
|
|
|
|
if [ "$OS_ID" != "ubuntu" ] || [ "$OS_VERSION_ID" != "26.04" ]; then
|
|
|
|
|
echo "WARNING: verified on Ubuntu 26.04 only (this is ${OS_ID:-?} ${OS_VERSION_ID:-?}); continuing" >&2
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
@@ -108,7 +113,34 @@ fi
|
|
|
|
|
if [ "$TRANSPORT" = "proxy" ] && ! command -v ziti >/dev/null 2>&1; then
|
|
|
|
|
need_pkgs+=(openziti) # the `ziti` CLI (ziti tunnel proxy) from the same repo
|
|
|
|
|
fi
|
|
|
|
|
command -v docker >/dev/null 2>&1 || die "docker is not installed; install Docker Engine first (https://docs.docker.com/engine/install/ubuntu/)"
|
|
|
|
|
if ! command -v docker >/dev/null 2>&1; then
|
|
|
|
|
# Docker Engine from Docker's apt repo (the suite for this Ubuntu codename); falls back to Ubuntu's
|
|
|
|
|
# docker.io if Docker has no suite for the codename yet. --docker-data-root puts the data-root on
|
|
|
|
|
# a dedicated disk BEFORE the daemon first starts (pilot VMs mount one at /home/docker-data).
|
|
|
|
|
log "docker is not installed — installing Docker Engine"
|
|
|
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
|
|
|
install -d -m 0755 /etc/apt/keyrings
|
|
|
|
|
if curl -fsSL --max-time 20 "https://download.docker.com/linux/ubuntu/dists/${OS_CODENAME:-noble}/Release" -o /dev/null 2>/dev/null; then
|
|
|
|
|
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
|
|
|
|
|
chmod a+r /etc/apt/keyrings/docker.gpg
|
|
|
|
|
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu ${OS_CODENAME:-noble} stable" > /etc/apt/sources.list.d/docker.list
|
|
|
|
|
apt-get update -qq
|
|
|
|
|
docker_pkgs="docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin"
|
|
|
|
|
else
|
|
|
|
|
log "Docker has no apt suite for '${OS_CODENAME:-?}' yet — using Ubuntu's docker.io"
|
|
|
|
|
apt-get update -qq
|
|
|
|
|
docker_pkgs="docker.io docker-compose-v2"
|
|
|
|
|
fi
|
|
|
|
|
if [ -n "$DOCKER_DATA_ROOT" ]; then
|
|
|
|
|
install -d -m 0710 "$DOCKER_DATA_ROOT"
|
|
|
|
|
install -d -m 0755 /etc/docker
|
|
|
|
|
[ -f /etc/docker/daemon.json ] || printf '{ "data-root": "%s" }\n' "$DOCKER_DATA_ROOT" > /etc/docker/daemon.json
|
|
|
|
|
fi
|
|
|
|
|
# shellcheck disable=SC2086
|
|
|
|
|
apt-get install -y -qq --no-install-recommends $docker_pkgs
|
|
|
|
|
systemctl enable --now docker
|
|
|
|
|
log "installed $(docker --version) (data-root $(docker info -f '{{.DockerRootDir}}' 2>/dev/null || echo default))"
|
|
|
|
|
fi
|
|
|
|
|
docker compose version >/dev/null 2>&1 || need_pkgs+=(docker-compose-plugin)
|
|
|
|
|
python3 -c 'import sys; sys.exit(0 if sys.version_info >= (3, 12) else 1)' 2>/dev/null || die "python3 >= 3.12 is required"
|
|
|
|
|
if [ "${#need_pkgs[@]}" -gt 0 ]; then
|
|
|
|
@@ -119,23 +151,23 @@ fi
|
|
|
|
|
|
|
|
|
|
# --- 2. the pinned .deb -----------------------------------------------------------------------------
|
|
|
|
|
installed="$(dpkg-query -W -f='${Version}' monky-deployd 2>/dev/null || true)"
|
|
|
|
|
if [ "$installed" = "$VERSION" ]; then
|
|
|
|
|
log "monky-deployd $VERSION already installed"
|
|
|
|
|
if [ "$installed" = "$DEPLOYD_VERSION" ]; then
|
|
|
|
|
log "monky-deployd $DEPLOYD_VERSION already installed"
|
|
|
|
|
else
|
|
|
|
|
tmp="$(mktemp -d)"; trap 'rm -rf "$tmp"' EXIT
|
|
|
|
|
deb="monky-deployd_${VERSION}_amd64.deb"
|
|
|
|
|
deb="monky-deployd_${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}"
|
|
|
|
|
url="${BASE_URL:-$GITLAB_BASE_URL}/${DEPLOYD_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}"
|
|
|
|
|
url="${BASE_URL:-$GITEA_BASE_URL}/releases/download/v${DEPLOYD_VERSION}"
|
|
|
|
|
fi
|
|
|
|
|
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?)"
|
|
|
|
@@ -162,14 +194,21 @@ chmod 0600 "$IDENTITY"
|
|
|
|
|
# ziti-edge-tunnel as a HOST (bind side, no tun/DNS) — the agent dials with the SDK or the proxy
|
|
|
|
|
install -d /etc/systemd/system/ziti-edge-tunnel.service.d
|
|
|
|
|
cat > /etc/systemd/system/ziti-edge-tunnel.service.d/run-host.conf <<'DROPIN'
|
|
|
|
|
# monky-deployd: run-host mode (no tun, no DNS); identities from the standard directory
|
|
|
|
|
# monky-deployd: run-host mode (no tun, no DNS); identities from the standard directory.
|
|
|
|
|
# ExecStartPre is cleared: the package's ziti-edge-tunnel.sh (auto-enrol *.jwt in the identity dir)
|
|
|
|
|
# is not executable by user ziti on 1.18.x (203/EXEC, env-qa-02 pilot) and run-host does not need it.
|
|
|
|
|
[Service]
|
|
|
|
|
ExecStartPre=
|
|
|
|
|
ExecStart=
|
|
|
|
|
ExecStart=/opt/openziti/bin/ziti-edge-tunnel run-host --identity-dir=/opt/openziti/etc/identities
|
|
|
|
|
DROPIN
|
|
|
|
|
systemctl daemon-reload
|
|
|
|
|
systemctl enable --now ziti-edge-tunnel.service
|
|
|
|
|
systemctl restart ziti-edge-tunnel.service || true
|
|
|
|
|
systemctl enable ziti-edge-tunnel.service >/dev/null 2>&1 || true
|
|
|
|
|
if ! systemctl restart ziti-edge-tunnel.service; then
|
|
|
|
|
# do NOT abort here: config, ACLs, grant and timer below must land so a re-run needs no new kit
|
|
|
|
|
echo "WARNING: ziti-edge-tunnel.service failed to start — see: journalctl -u ziti-edge-tunnel; continuing" >&2
|
|
|
|
|
TUNNEL_FAILED=1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# --- 4. config, ACLs, bootstrap grant -----------------------------------------------------------------
|
|
|
|
|
install -d -m 0750 -o root -g monky-deployd "$ETC"
|
|
|
|
@@ -186,7 +225,7 @@ if [ -s "$ETC/config.yaml" ] && [ -z "$FORCE_CONFIG" ]; then
|
|
|
|
|
log "keeping existing $ETC/config.yaml (use --force-config to rewrite)"
|
|
|
|
|
else
|
|
|
|
|
cat > "$ETC/config.yaml" <<CFG
|
|
|
|
|
# written by install.sh $(date -u +%FT%TZ) — monky-deployd $VERSION
|
|
|
|
|
# written by install.sh $(date -u +%FT%TZ) — monky-deployd $DEPLOYD_VERSION
|
|
|
|
|
env_id: $ENV_ID
|
|
|
|
|
site: $SITE
|
|
|
|
|
transport: $TRANSPORT
|
|
|
|
@@ -246,7 +285,7 @@ rm -f "$ETC/enrol.jwt"
|
|
|
|
|
|
|
|
|
|
cat <<CHECK
|
|
|
|
|
|
|
|
|
|
monky-deployd $VERSION installed for $ENV_ID ($SITE, transport $TRANSPORT). Verification checklist (Ubuntu 26.04):
|
|
|
|
|
monky-deployd $DEPLOYD_VERSION installed for $ENV_ID ($SITE, transport $TRANSPORT). Verification checklist (Ubuntu 26.04):
|
|
|
|
|
python3 --version # >= 3.12
|
|
|
|
|
docker compose version # compose plugin present
|
|
|
|
|
systemctl is-active ziti-edge-tunnel # run-host mode (drop-in run-host.conf)
|
|
|
|
@@ -260,3 +299,7 @@ monky-deployd $VERSION installed for $ENV_ID ($SITE, transport $TRANSPORT). Veri
|
|
|
|
|
CHECK
|
|
|
|
|
CHECK_STATUS="$(monky-deployd status 2>&1 || true)"
|
|
|
|
|
echo "$CHECK_STATUS" | sed 's/^/ | /'
|
|
|
|
|
if [ -n "$TUNNEL_FAILED" ] && ! systemctl is-active --quiet ziti-edge-tunnel.service; then
|
|
|
|
|
echo "ERROR: ziti-edge-tunnel.service is not running; the agent cannot reach the mesh until it is. Everything else is installed — fix the unit and 'systemctl restart ziti-edge-tunnel monky-deployd'." >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|