diff --git a/.gitignore b/.gitignore index bc45028..25e5a08 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ .tmp .codex ollama_backends.json +.python/ +cpython-*.tar.gz diff --git a/deploy/README.md b/deploy/README.md index ff0e9ff..e4ec795 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -16,7 +16,14 @@ What `install.sh` does (idempotent — safe to re-run, e.g. after `git pull`): -1. Checks prerequisites: Python 3.11+, Docker + compose plugin. +1. Checks prerequisites: Docker + compose plugin, and a Python ≥ 3.11. + If the system has none (Ubuntu 18.04 ships 3.6, 22.04 ships 3.10 — and + the system python must never be replaced), the script fetches a + standalone CPython build into `.python/` inside the repo — self-contained, + needs only glibc ≥ 2.17, so it runs on any distro, old or new. The + downloaded tarball is kept next to the repo root and reused on re-runs; + for an offline server, drop the tarball next to `install.sh` beforehand + and it will be picked up instead of downloading. 2. Provisions `.env` — on the `deploy` branch it already ships with the deployment defaults (web UI off, auth off, Ollama Cloud, profile `navi_code`); the script generates the DB password in place of the diff --git a/deploy/install.sh b/deploy/install.sh index 76bfede..4363ade 100755 --- a/deploy/install.sh +++ b/deploy/install.sh @@ -33,9 +33,9 @@ # ── 1. prerequisites ──────────────────────────────────────────────── say "Checking prerequisites" -# Pick the first interpreter >= 3.11. Ubuntu 22.04's system python3 is 3.10 -# (and must NOT be replaced — apt depends on it); a newer Python installed -# alongside (deadsnakes PPA) lives under its own name, e.g. python3.12. +# Pick the first system interpreter >= 3.11. Ubuntu 22.04's system python3 +# is 3.10 (and must NOT be replaced — apt depends on it); a newer Python +# installed alongside (deadsnakes PPA) lives under its own name (python3.12). PYBIN="" for cand in python3.13 python3.12 python3.11 python3; do command -v "$cand" >/dev/null 2>&1 || continue @@ -44,13 +44,47 @@ break fi done + +# Nothing usable on the system (Ubuntu 18.04 ships 3.6, EOL distros have no +# 3.11+ packages)? Fetch a standalone CPython build instead — self-contained, +# needs only glibc >= 2.17, so it runs on any distro old or new. It lives in +# .python/ inside the repo and is reused on re-runs. +PY_STANDALONE_TAG="20260901" +PY_STANDALONE_VER="3.12.14" if [ -z "$PYBIN" ]; then - err "no python >= 3.11 found (system python3 is too old)." - err "Ubuntu 22.04: sudo add-apt-repository ppa:deadsnakes/ppa && sudo apt update" - err " sudo apt install python3.12 python3.12-venv" - err "Ubuntu 24.04 already ships 3.12 as python3." - err "Do NOT replace the system python3 — install alongside and re-run." - exit 1 + say "No system python >= 3.11 — fetching standalone CPython ${PY_STANDALONE_VER}" + case "$(uname -m)" in + x86_64) PY_TARGET="x86_64-unknown-linux-gnu" ;; + aarch64|arm64) PY_TARGET="aarch64-unknown-linux-gnu" ;; + *) err "unsupported architecture: $(uname -m) — no standalone build"; exit 1 ;; + esac + PY_HOME="$REPO_DIR/.python" + TARBALL="cpython-${PY_STANDALONE_VER}+${PY_STANDALONE_TAG}-${PY_TARGET}-install_only_stripped.tar.gz" + if [ ! -x "$PY_HOME/python/bin/python3" ]; then + mkdir -p "$PY_HOME" + # A tarball next to install.sh wins (offline servers / manual download). + SRC="" + if [ -f "$REPO_DIR/$TARBALL" ]; then + SRC="$REPO_DIR/$TARBALL" + else + URL="https://github.com/astral-sh/python-build-standalone/releases/download/${PY_STANDALONE_TAG}/${TARBALL}" + if command -v curl >/dev/null; then + curl -fsSL --retry 3 -o "$REPO_DIR/$TARBALL" "$URL" || { err "download failed: $URL"; exit 1; } + elif command -v wget >/dev/null; then + wget -q -O "$REPO_DIR/$TARBALL" "$URL" || { err "download failed: $URL"; exit 1; } + else + err "no curl/wget on the host. Download on another machine:" + err " $URL" + err "put the file next to install.sh and re-run." + exit 1 + fi + SRC="$REPO_DIR/$TARBALL" + fi + tar -xzf "$SRC" -C "$PY_HOME" || { err "tarball extraction failed"; exit 1; } + # keep the tarball — re-runs reuse it instead of re-downloading + fi + PYBIN="$PY_HOME/python/bin/python3" + echo "Standalone python ready: $PYBIN" fi if ! command -v docker >/dev/null; then @@ -59,7 +93,7 @@ if ! $SUDO docker compose version >/dev/null 2>&1; then err "docker compose (v2 plugin) not available"; exit 1 fi -echo "OK: $PYBIN ($($PYBIN --version 2>&1)), docker + compose" +echo "OK: python ($($PYBIN --version 2>&1)), docker + compose" # ── 2. .env ──────────────────────────────────────────────────────── say "Provisioning .env"