#!/bin/bash set -euo pipefail PROJECT="lobe-sandbox" PROFILE="sandbox-default" BUILDER="sb-builder" IMAGE_ALIAS="lobe-sandbox-base" BASE="images:debian/13" log() { echo "==> [$(date +%H:%M:%S)] $*"; } if incus info "$BUILDER" --project "$PROJECT" >/dev/null 2>&1; then log "Removing existing builder" incus delete "$BUILDER" --project "$PROJECT" --force fi log "Launching builder from $BASE (4GB/4CPU for fast build)" incus launch "$BASE" "$BUILDER" --project "$PROJECT" -p "$PROFILE" \ -c limits.memory=4GiB -c limits.cpu=4 log "Waiting for network" for i in {1..60}; do if incus exec "$BUILDER" --project "$PROJECT" -- bash -c "getent hosts deb.debian.org >/dev/null 2>&1"; then log "Network ready after ${i}s"; break fi sleep 1 done log "Installing apt packages" incus exec "$BUILDER" --project "$PROJECT" -- bash -c ' set -e export DEBIAN_FRONTEND=noninteractive apt-get update apt-get install -y --no-install-recommends \ python3 python3-dev python3-venv python3-pip \ ca-certificates curl wget git gnupg build-essential pkg-config \ jq ripgrep fd-find bat fonts-noto-cjk \ less tree unzip zip xz-utils sudo locales tzdata ln -sf /usr/bin/fdfind /usr/local/bin/fd ln -sf /usr/bin/batcat /usr/local/bin/bat sed -i "/zh_CN.UTF-8/s/^# //;/en_US.UTF-8/s/^# //" /etc/locale.gen locale-gen ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ' log "Installing Node.js 20 via NodeSource" incus exec "$BUILDER" --project "$PROJECT" -- bash -c ' set -e export DEBIAN_FRONTEND=noninteractive curl -fsSL https://deb.nodesource.com/setup_20.x | bash - apt-get install -y --no-install-recommends nodejs corepack enable ' log "Installing uv" incus exec "$BUILDER" --project "$PROJECT" -- bash -c ' curl -LsSf https://astral.sh/uv/install.sh | sh -s -- --no-modify-path --install-dir /usr/local/bin ls -la /usr/local/bin/uv /usr/local/bin/uvx ' log "Installing bun" incus exec "$BUILDER" --project "$PROJECT" -- bash -c ' curl -fsSL https://bun.sh/install | env BUN_INSTALL=/usr/local bash ls -la /usr/local/bin/bun ' log "Creating sandbox user and /workspace" incus exec "$BUILDER" --project "$PROJECT" -- bash -c ' set -e useradd --create-home --shell /bin/bash --uid 1000 sandbox mkdir -p /workspace/data /workspace/output /workspace/tmp chown -R sandbox:sandbox /workspace /home/sandbox printf "cd /workspace\nexport LANG=zh_CN.UTF-8\n" >> /home/sandbox/.bashrc ' log "Cleaning apt cache" incus exec "$BUILDER" --project "$PROJECT" -- bash -c ' apt-get clean rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ' log "Verifying versions" incus exec "$BUILDER" --project "$PROJECT" -- bash -c ' echo "python : $(python3 --version)" echo "node : $(node --version)" echo "bun : $(bun --version)" echo "uv : $(uv --version)" echo "git : $(git --version)" echo "rg : $(rg --version | head -1)" echo "fd : $(fd --version)" echo "user : $(id sandbox)" echo "space : $(du -sh /workspace)" echo "rootfs : $(du -sh --one-file-system / 2>/dev/null | tail -1)" ' log "Stopping builder" incus stop "$BUILDER" --project "$PROJECT" if incus image alias list --project "$PROJECT" | grep -q "$IMAGE_ALIAS"; then log "Deleting old $IMAGE_ALIAS image" incus image delete "$IMAGE_ALIAS" --project "$PROJECT" fi log "Publishing as $IMAGE_ALIAS" incus publish "$BUILDER" --project "$PROJECT" --alias "$IMAGE_ALIAS" log "Deleting builder" incus delete "$BUILDER" --project "$PROJECT" log "Image info" incus image list --project "$PROJECT" log "DONE"