From 837a7e5bb1341e1841385dcc705a98c76e84824f Mon Sep 17 00:00:00 2001 From: Marcos Della Date: Sun, 6 Sep 2026 16:18:47 +0000 Subject: [PATCH] fix(install.sh): --version clobbered by /etc/os-release; install Docker Engine when absent; 0.1.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first real kit run (env-qa-02) downloaded monky-deployd_26.04 LTS (Resolute Raccoon)_amd64.deb: sourcing /etc/os-release inline overwrote VERSION. Script vars are now DEPLOYD_VERSION and os-release is read in a subshell. Per the operator's rule (end users run ONE script), install.sh now installs Docker Engine when absent — Docker's apt suite for the host codename, falling back to Ubuntu's docker.io — with --docker-data-root to place the data-root before first start. Existing Docker is left untouched. bash -n + shellcheck -S warning clean. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01KLB7jieMNRkTsJ2epr4Ds1 --- CHANGELOG.md | 8 +++ README.md | 11 +++- ansible/roles/monky_deployd/README.md | 2 +- ansible/roles/monky_deployd/defaults/main.yml | 2 +- config.example.yaml | 2 +- monky_deployd/__init__.py | 2 +- packaging/install.sh | 66 ++++++++++++++----- pyproject.toml | 2 +- 8 files changed, 71 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fcf432..4d8f418 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # Changelog +## 0.1.3 — 2026-09-06 + +- **install.sh: `--version` was clobbered by `/etc/os-release`** (it defines `VERSION`), so the kit tried to download + `monky-deployd_26.04 LTS (Resolute Raccoon)_amd64.deb` (env-qa-02 pilot, first real kit run). Script variables are now + `DEPLOYD_VERSION`; os-release is read in a subshell. +- **install.sh installs Docker Engine when absent** (Docker's apt suite for the codename → fallback `docker.io`), with + `--docker-data-root ` to place the data-root before first start. One script for the end user, per the operator's rule. + ## v0.1.2 — 2026-09-05 - **The GitLab project is private** (its parent groups are private, so it cannot be made public; diff --git a/README.md b/README.md index 5595813..37e78c8 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,9 @@ you the enrolment JWT, a one-time **bootstrap deploy grant** and the read-only * ```sh T= # read-only GitLab deploy token (read_package_registry); the kit carries it -curl -sSf -H "DEPLOY-TOKEN: $T" https://scm.tikali.ai/api/v4/projects/69/packages/generic/monky-deployd/0.1.2/install.sh \ +curl -sSf -H "DEPLOY-TOKEN: $T" https://scm.tikali.ai/api/v4/projects/69/packages/generic/monky-deployd/0.1.3/install.sh \ | sudo bash -s -- --env env-qa-02 --site cbs --token "$T" --bootstrap-file bootstrap.jwt --enrol-jwt ./monky-host.env-qa-02.jwt -# [--transport sdk|proxy|system] [--version 0.1.2] [--laptop] [--bao-ca openbao-ca.pem] [--source gitlab|gitea] +# [--transport sdk|proxy|system] [--version 0.1.3] [--docker-data-root /home/docker-data] [--laptop] [--bao-ca openbao-ca.pem] [--source gitlab|gitea] ``` `install.sh` installs `ziti-edge-tunnel` (OpenZiti `jammy` suite) and `docker-compose-plugin` if @@ -167,3 +167,10 @@ the by-hand recipe). Both locations keep being published. - `docs/PROTOCOL.md`, `docs/OPERATIONS.md`, `CHANGELOG.md` - monky-tenancy `docs/usage.md` (agent protocol), `app/api/agent.py`, `app/schemas_backends.py` - monky-deploy (the renderer whose `render_files` produces the bundle) + +### Docker Engine (since 0.1.3) + +`install.sh` installs Docker Engine when it is absent (Docker's apt suite for the host's Ubuntu codename, falling back to +Ubuntu's `docker.io`), so an end user runs exactly one script. `--docker-data-root ` writes `/etc/docker/daemon.json` +before the daemon first starts (pilot VMs keep the data-root on a dedicated disk, e.g. `/home/docker-data`). A pre-existing +Docker is left untouched. macOS/Windows laptops still need Docker Desktop from the user. diff --git a/ansible/roles/monky_deployd/README.md b/ansible/roles/monky_deployd/README.md index 43f0c5e..0a4da9b 100644 --- a/ansible/roles/monky_deployd/README.md +++ b/ansible/roles/monky_deployd/README.md @@ -16,7 +16,7 @@ template → optional openbao-ca PEM → optional `monky-deployd-proxy.service` | var | note | |---|---| -| `monky_deployd_version` | pinned release, e.g. `0.1.2` | +| `monky_deployd_version` | pinned release, e.g. `0.1.3` | | `monky_deployd_download_token` | **vaulted**: GitLab deploy token, scope `read_package_registry` only (revocable) — the registry is private; seeded in OpenBao at `monky/monky-tenancy/deployd-download` key `token` (path/key are the operator's choice). Empty = no header (only works with the Gitea `base_url`) | | `monky_deployd_env_id` / `_site` / `_transport` | per host (`env-dev-06`, `cbs`, `sdk`) | | `monky_deployd_bootstrap_grant` | tenancy-minted deploy grant (1 h) — `ansible-vault` or a lookup at play time; empty keeps the existing token | diff --git a/ansible/roles/monky_deployd/defaults/main.yml b/ansible/roles/monky_deployd/defaults/main.yml index 9f98342..96a5f2d 100644 --- a/ansible/roles/monky_deployd/defaults/main.yml +++ b/ansible/roles/monky_deployd/defaults/main.yml @@ -1,7 +1,7 @@ --- # monky_deployd — install and configure the Monky backend pull agent (MONKY-ADR-0028 §D). # Copy this role into osg1-07 (roles/monky_deployd) and roll to env-dev-06..09 after the pilot. -monky_deployd_version: "0.1.2" +monky_deployd_version: "0.1.3" monky_deployd_deb: "monky-deployd_{{ monky_deployd_version }}_amd64.deb" # PRIMARY download = 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, no HTTP ingress), so backend diff --git a/config.example.yaml b/config.example.yaml index ca255f1..8f22a7f 100644 --- a/config.example.yaml +++ b/config.example.yaml @@ -1,4 +1,4 @@ -# /etc/monky-deployd/config.yaml — monky-deployd v0.1.2 (MONKY-ADR-0028 §D) +# /etc/monky-deployd/config.yaml — monky-deployd v0.1.3 (MONKY-ADR-0028 §D) # Written by packaging/install.sh (or the ansible role monky_deployd). YAML *subset*: maps, scalars, # simple lists, comments. Keys not listed here are a config error. diff --git a/monky_deployd/__init__.py b/monky_deployd/__init__.py index 1638825..dbe737a 100644 --- a/monky_deployd/__init__.py +++ b/monky_deployd/__init__.py @@ -4,4 +4,4 @@ Dials monky-tenancy over the mesh with the box's host identity, fetches the rend leases a deploy grant, logs in to OpenBao, reads its own secrets, runs `docker compose`, reports. Stdlib only; the optional `openziti` SDK is the `sdk` transport.""" -__version__ = "0.1.2" +__version__ = "0.1.3" diff --git a/packaging/install.sh b/packaging/install.sh index bba6f6a..9990e57 100755 --- a/packaging/install.sh +++ b/packaging/install.sh @@ -3,10 +3,10 @@ # # T= # 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.3/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.3] [--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.3" # 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="" 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?)" @@ -186,7 +218,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" <= 3.12 docker compose version # compose plugin present systemctl is-active ziti-edge-tunnel # run-host mode (drop-in run-host.conf) diff --git a/pyproject.toml b/pyproject.toml index 771c552..7b97620 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "monky-deployd" -version = "0.1.2" +version = "0.1.3" description = "Monky backend pull agent: checkin -> bundle -> lease -> OpenBao -> docker compose -> report, over the ziti mesh (MONKY-ADR-0028)" readme = "README.md" requires-python = ">=3.12"