File size: 6,888 Bytes
95f8c4b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | #!/data/data/com.termux/files/usr/bin/bash
# Idempotent Termux prereq installer for aistudio-api.
#
# What it does:
# 1. Ensures pkg: proot-distro, ca-certificates, curl.
# 2. Installs proot-distro container ${AISTUDIO_PROOT_NAME} (default
# aistudio-api) — Ubuntu 24.04 from termux/proot-distro. Skips if
# already present so it never collides with the user's own
# `ubuntu` (or any other) container.
# 3. Inside the container, apt-installs the glibc runtime deps
# CloakBrowser actually needs (libnss3, libnspr4, libgbm1,
# libasound2, libxkbcommon0, libxcomposite1, libxdamage1,
# libxrandr2, libxkbcommon0, libatk-bridge2.0-0, libatk1.0-0,
# libatspi2.0-0, libgtk-3-0, libnotify4, fonts-liberation).
# 4. Downloads CloakBrowser into
# <project_root>/.cloakbrowser/chromium-<ver>/. Skips if already
# cached. Extracts in place; copies the chrome tree into the
# container at /opt/cloakbrowser/ so the wrapper can --bind it.
#
# Flags:
# --project-root PATH where to place .cloakbrowser (default: cwd)
# --proot-name NAME container name (default: aistudio-api)
# --proot-distro IMAGE OCI image to install (default: ubuntu:24.04)
# --chromium-version VER CloakBrowser chromium version
# (default: 146.0.7680.177.3)
# --skip-proot-install don't create/update proot container
# --skip-browser-download don't re-fetch CloakBrowser tarball
#
# Re-running is safe and fast: each step short-circuits when its
# precondition is already satisfied.
set -euo pipefail
PROJECT_ROOT="$(pwd)"
PROOT_NAME="aistudio-api"
PROOT_IMAGE="ubuntu:24.04"
CHROMIUM_VERSION="146.0.7680.177.3"
SKIP_PROOT=0
SKIP_BROWSER=0
while [[ $# -gt 0 ]]; do
case "$1" in
--project-root) PROJECT_ROOT="$2"; shift 2 ;;
--proot-name) PROOT_NAME="$2"; shift 2 ;;
--proot-distro) PROOT_IMAGE="$2"; shift 2 ;;
--chromium-version) CHROMIUM_VERSION="$2"; shift 2 ;;
--skip-proot-install) SKIP_PROOT=1; shift ;;
--skip-browser-download) SKIP_BROWSER=1; shift ;;
-h|--help) sed -n '2,40p' "$0"; exit 0 ;;
*) echo "unknown flag: $1" >&2; exit 2 ;;
esac
done
PROJECT_ROOT="$(cd "${PROJECT_ROOT}" && pwd)"
CLOAK_ROOT="${PROJECT_ROOT}/.cloakbrowser"
CHROME_DIR_HOST="${CLOAK_ROOT}/chromium-${CHROMIUM_VERSION}"
log() { printf '[install] %s\n' "$*" >&2; }
# ---------- 1. Termux host packages ----------
if command -v pkg >/dev/null 2>&1; then
NEEDED_PKGS=()
for p in proot-distro ca-certificates curl; do
if ! command -v "${p%proot-distro*}" >/dev/null 2>&1 \
&& ! dpkg -s "${p}" >/dev/null 2>&1; then
NEEDED_PKGS+=("${p}")
fi
done
command -v proot-distro >/dev/null 2>&1 || NEEDED_PKGS+=("proot-distro")
command -v curl >/dev/null 2>&1 || NEEDED_PKGS+=("curl")
if [[ ${#NEEDED_PKGS[@]} -gt 0 ]]; then
log "Installing Termux packages: ${NEEDED_PKGS[*]}"
pkg update -y
pkg install -y "${NEEDED_PKGS[@]}"
else
log "Termux packages already present"
fi
else
log "pkg not found; assuming non-Termux host (skip host deps)"
fi
command -v proot-distro >/dev/null 2>&1 || {
echo "proot-distro is required. Install it via 'pkg install proot-distro'." >&2
exit 1
}
# ---------- 2. proot container ----------
if { proot-distro list 2>&1 1>/dev/null || true; } | grep -qE "[[:space:]]\\*?[[:space:]]*${PROOT_NAME}([[:space:]]|$)"; then
log "proot container '${PROOT_NAME}' already exists; skipping install"
elif [[ ${SKIP_PROOT} -eq 1 ]]; then
log "--skip-proot-install set but container missing; aborting"
exit 1
else
log "Installing proot container '${PROOT_NAME}' from ${PROOT_IMAGE}"
proot-distro install "${PROOT_IMAGE}" --name "${PROOT_NAME}"
fi
# ---------- 3. apt deps inside container ----------
install_apt_deps() {
proot-distro login "${PROOT_NAME}" -- bash -c '
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
export TZ=UTC
dpkg --configure -a >/dev/null 2>&1 || true
apt-get install -y --no-install-recommends \
ca-certificates curl \
libnss3 libnspr4 libgbm1 libasound2t64 \
libxkbcommon0 libxcomposite1 libxdamage1 libxrandr2 \
libxfixes3 libxext6 libxrender1 libx11-6 libxcb1 \
libatk-bridge2.0-0 libatk1.0-0 libatspi2.0-0 \
libgtk-3-0 libnotify4 fonts-liberation libpangocairo-1.0-0
apt-get clean
rm -rf /var/lib/apt/lists/*
'
}
log "Ensuring runtime libs inside container '${PROOT_NAME}'"
install_apt_deps
# ---------- 4. CloakBrowser binary ----------
ARCHIVE_NAME="cloakbrowser-linux-arm64.tar.gz"
DOWNLOAD_URL="https://github.com/CloakHQ/cloakbrowser/releases/download/chromium-v${CHROMIUM_VERSION}/${ARCHIVE_NAME}"
mkdir -p "${CLOAK_ROOT}"
if [[ -x "${CHROME_DIR_HOST}/chrome" ]]; then
log "CloakBrowser ${CHROMIUM_VERSION} already cached at ${CHROME_DIR_HOST}"
elif [[ ${SKIP_BROWSER} -eq 1 ]]; then
log "--skip-browser-download set but no chrome binary; aborting"
exit 1
else
log "Downloading CloakBrowser ${CHROMIUM_VERSION} (~200MB)..."
TMP="$(mktemp -d)"
trap 'rm -rf "${TMP}"' EXIT
if command -v curl >/dev/null 2>&1; then
curl -fSL --retry 3 -o "${TMP}/${ARCHIVE_NAME}" "${DOWNLOAD_URL}"
else
proot-distro login "${PROOT_NAME}" -- curl -fSL --retry 3 \
proot-distro copy "${PROOT_NAME}:/tmp/${ARCHIVE_NAME}" \
"${TMP}/${ARCHIVE_NAME}"
fi
tar -xzf "${TMP}/${ARCHIVE_NAME}" -C "${CLOAK_ROOT}"
# Tarball may nest: chromium-<ver>/... — flatten one level if so.
INNER="$(find "${CLOAK_ROOT}" -mindepth 2 -maxdepth 2 -type d -name 'chromium-*' | head -1 || true)"
if [[ -n "${INNER}" && "${INNER}" != "${CHROME_DIR_HOST}" ]]; then
mv "${INNER}" "${CHROME_DIR_HOST}"
fi
if [[ ! -x "${CHROME_DIR_HOST}/chrome" ]]; then
echo "extracted chrome binary not found at ${CHROME_DIR_HOST}/chrome" >&2
exit 1
fi
log "CloakBrowser extracted to ${CHROME_DIR_HOST}"
fi
# ---------- 5. Stage chrome tree into the container ----------
PROOT_CHROME_DIR="/opt/cloakbrowser"
log "Staging chrome tree into container at ${PROOT_CHROME_DIR}"
# proot-distro copy -r copies the dir itself. We'll rename it inside.
proot-distro login "${PROOT_NAME}" -- bash -c "rm -rf '/opt/$(basename "${CHROME_DIR_HOST}")'"
proot-distro copy -r "${CHROME_DIR_HOST}" "${PROOT_NAME}:/opt/$(basename "${CHROME_DIR_HOST}")"
proot-distro login "${PROOT_NAME}" -- bash -c "
rm -rf '${PROOT_CHROME_DIR}'
mv '/opt/$(basename "${CHROME_DIR_HOST}")' '${PROOT_CHROME_DIR}'
"
cat <<EOF
[install] Done.
Quick smoke test:
bash scripts/cloakbrowser_termux/run-chrome.sh --version
Then start the API:
uv run python3 main.py server --port 8080
EOF |