From 7efeaf02e866f4abad664e3309cf37a82e5fdea3 Mon Sep 17 00:00:00 2001 From: "Aaron D. Lee" Date: Tue, 6 Jan 2026 15:37:44 -0500 Subject: [PATCH] Bundle pyenv Python with pre-built tarball for zero-compile installs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Combined tarball includes pyenv Python 3.12 + venv with all deps - Downloads from GitHub releases by default (~50MB) - Reduces install time from 20+ min to ~2 min - Add --no-prebuilt / --from-source flags to force compile - Update BUILD_IMAGE.md with tarball creation instructions - Rename tarball: stegasoo-pi-arm64.tar.zst (was venv-only) Fresh Pi installs no longer need to compile Python or jpegio. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .gitignore | 3 +- rpi/BUILD_IMAGE.md | 54 +++++++++++++++----- rpi/setup.sh | 121 +++++++++++++++++++++++++++------------------ 3 files changed, 117 insertions(+), 61 deletions(-) diff --git a/.gitignore b/.gitignore index 662e079..eb88bd7 100644 --- a/.gitignore +++ b/.gitignore @@ -86,5 +86,6 @@ pishrink.sh frontends/web/temp_files/ rpi/config.json -# Pre-built venv tarball (39MB - too large for git) +# Pre-built Pi tarballs (too large for git) +rpi/stegasoo-pi-arm64.tar.zst rpi/stegasoo-venv-pi-arm64.tar.zst diff --git a/rpi/BUILD_IMAGE.md b/rpi/BUILD_IMAGE.md index 7c7b89b..534d204 100644 --- a/rpi/BUILD_IMAGE.md +++ b/rpi/BUILD_IMAGE.md @@ -39,22 +39,20 @@ cd stegasoo ./rpi/setup.sh ``` -### Fast Build Option (with pre-built venv) +### Default: Fast Build (downloads pre-built environment) -If you have `stegasoo-venv-pi-arm64.tar.zst` from a previous build: +By default, `setup.sh` downloads a pre-built tarball from GitHub releases containing: +- pyenv with Python 3.12 (pre-compiled for ARM64) +- venv with all dependencies (jpegio, scipy, etc.) +This reduces install time from **20+ minutes to ~2 minutes**. + +To force a from-source build: ```bash -cd /opt -git clone -b 4.1 https://github.com/adlee-was-taken/stegasoo.git stegasoo - -# Copy pre-built venv (from your host machine) -# On host: scp rpi/stegasoo-venv-pi-arm64.tar.zst admin@stegasoo.local:/opt/stegasoo/rpi/ - -cd stegasoo -./rpi/setup.sh # Detects tarball, extracts instead of compiling (~2 min vs 20+) +./rpi/setup.sh --no-prebuilt ``` -**Standard build** takes ~15-20 minutes and installs: +**From-source build** takes ~15-20 minutes and installs: - Python 3.12 via pyenv - jpegio (patched for ARM) - Stegasoo with web UI @@ -130,6 +128,40 @@ zstdcat stegasoo-rpi-*.img.zst | sudo dd of=/dev/sdX bs=4M status=progress --- +## Creating the Pre-built Tarball + +After a successful from-source build, create the pre-built tarball for future installs: + +```bash +# On the Pi after successful setup: +cd ~ + +# Strip caches and tests from venv (295MB → 208MB) +find /opt/stegasoo/venv/ -type d -name '__pycache__' -exec rm -rf {} + 2>/dev/null +find /opt/stegasoo/venv/ -type d -name 'tests' -exec rm -rf {} + 2>/dev/null +find /opt/stegasoo/venv/ -type d -name 'test' -exec rm -rf {} + 2>/dev/null + +# Create venv tarball +cd /opt/stegasoo +tar -cf - venv/ | zstd -19 -T0 > ~/stegasoo-venv.tar.zst + +# Create combined tarball (pyenv + venv pointer) +cd ~ +tar -cf - .pyenv stegasoo-venv.tar.zst | zstd -19 -T0 > /tmp/stegasoo-pi-arm64.tar.zst + +# Check size (should be ~50-60MB) +ls -lh /tmp/stegasoo-pi-arm64.tar.zst +``` + +Pull to host and upload to GitHub releases: +```bash +# On host: +scp admin@stegasoo.local:/tmp/stegasoo-pi-arm64.tar.zst ./ +# Upload to GitHub releases as stegasoo-pi-arm64.tar.zst +``` + +--- + ## Quick Command Summary ```bash diff --git a/rpi/setup.sh b/rpi/setup.sh index ef26f61..35064ef 100755 --- a/rpi/setup.sh +++ b/rpi/setup.sh @@ -181,16 +181,17 @@ else cd "$INSTALL_DIR" fi -# Pre-built venv tarball (skips 20+ min compile time) -PREBUILT_VENV="$INSTALL_DIR/rpi/stegasoo-venv-pi-arm64.tar.zst" -PREBUILT_VENV_URL="${PREBUILT_VENV_URL:-https://github.com/adlee-was-taken/stegasoo/releases/download/v4.1.3/stegasoo-venv-pi-arm64.tar.zst}" +# Pre-built environment tarball (skips 20+ min compile time) +# Includes both pyenv Python 3.12 AND venv with all dependencies +PREBUILT_TARBALL="$INSTALL_DIR/rpi/stegasoo-pi-arm64.tar.zst" +PREBUILT_URL="${PREBUILT_URL:-https://github.com/adlee-was-taken/stegasoo/releases/download/v4.1.3/stegasoo-pi-arm64.tar.zst}" USE_PREBUILT=true # Use local tarball if present, otherwise will download -if [ -f "$PREBUILT_VENV" ]; then - echo -e "${GREEN}Found local pre-built venv - fast install mode${NC}" +if [ -f "$PREBUILT_TARBALL" ]; then + echo -e "${GREEN}Found local pre-built environment - fast install mode${NC}" else - echo -e "${GREEN}Will download pre-built venv - fast install mode${NC}" + echo -e "${GREEN}Will download pre-built environment - fast install mode${NC}" fi # Allow --no-prebuilt flag to force from-source build @@ -199,16 +200,25 @@ if [[ " $* " =~ " --no-prebuilt " ]] || [[ " $* " =~ " --from-source " ]]; then echo -e "${YELLOW}Building from source (--no-prebuilt specified)${NC}" fi -echo -e "${GREEN}[5/12]${NC} Installing pyenv and Python $PYTHON_VERSION..." +# Fast path: use pre-built environment if available +if [ "$USE_PREBUILT" = true ]; then + echo -e "${GREEN}[5/8]${NC} Installing pre-built Python environment..." -# Install pyenv if not present -if [ ! -d "$HOME/.pyenv" ]; then - curl https://pyenv.run | bash + # Download if local file doesn't exist + if [ ! -f "$PREBUILT_TARBALL" ]; then + echo " Downloading pre-built environment (~50MB)..." + curl -L -o "$PREBUILT_TARBALL" "$PREBUILT_URL" + fi - # Add pyenv to current shell + # Extract pre-built environment (includes pyenv Python + venv) + echo " Extracting pre-built environment..." + zstd -d "$PREBUILT_TARBALL" --stdout | tar -xf - -C "$HOME" + + # Setup pyenv in current shell export PYENV_ROOT="$HOME/.pyenv" export PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init -)" + pyenv global $PYTHON_VERSION # Add to .bashrc if not already there if ! grep -q 'PYENV_ROOT' ~/.bashrc; then @@ -218,48 +228,20 @@ if [ ! -d "$HOME/.pyenv" ]; then echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc echo 'eval "$(pyenv init - bash)"' >> ~/.bashrc fi -else - echo " pyenv already installed" - export PYENV_ROOT="$HOME/.pyenv" - export PATH="$PYENV_ROOT/bin:$PATH" - eval "$(pyenv init -)" -fi -# Install Python 3.12 if not present (required even for pre-built venv) -if ! pyenv versions | grep -q "$PYTHON_VERSION"; then - if [ "$USE_PREBUILT" = true ]; then - echo -e " ${YELLOW}Note: Python $PYTHON_VERSION needed for pre-built venv${NC}" + # Verify Python + INSTALLED_PY=$(python --version 2>&1 | cut -d' ' -f2 | cut -d'.' -f1,2) + echo -e " ${GREEN}✓${NC} Python: $INSTALLED_PY" + + # Extract venv to install dir + echo -e "${GREEN}[6/8]${NC} Setting up virtual environment..." + if [ -f "$HOME/stegasoo-venv.tar.zst" ]; then + zstd -d "$HOME/stegasoo-venv.tar.zst" --stdout | tar -xf - -C "$INSTALL_DIR" + rm "$HOME/stegasoo-venv.tar.zst" fi - echo " Building Python $PYTHON_VERSION (this takes ~10 minutes)..." - pyenv install $PYTHON_VERSION -else - echo " Python $PYTHON_VERSION already installed" -fi -pyenv global $PYTHON_VERSION - -# Verify Python version -INSTALLED_PY=$(python --version 2>&1 | cut -d' ' -f2 | cut -d'.' -f1,2) -if [ "$INSTALLED_PY" != "$PYTHON_VERSION" ]; then - echo -e "${RED}Error: Python $PYTHON_VERSION not active. Got: $INSTALLED_PY${NC}" - exit 1 -fi - -# Fast path: use pre-built venv if available -if [ "$USE_PREBUILT" = true ]; then - echo -e "${GREEN}[6/8]${NC} Installing pre-built Python environment..." - - # Download if URL provided and local file doesn't exist - if [ ! -f "$PREBUILT_VENV" ] && [ -n "$PREBUILT_VENV_URL" ]; then - echo " Downloading pre-built venv..." - curl -L -o "$PREBUILT_VENV" "$PREBUILT_VENV_URL" - fi - - # Extract pre-built venv (zstd compressed) - echo " Extracting pre-built venv (this is much faster!)..." - zstd -d "$PREBUILT_VENV" --stdout | tar -xf - -C "$INSTALL_DIR" # Activate and verify - source venv/bin/activate + source "$INSTALL_DIR/venv/bin/activate" VENV_PY=$(python --version 2>&1 | cut -d' ' -f2 | cut -d'.' -f1,2) echo -e " ${GREEN}✓${NC} venv Python: $VENV_PY" @@ -270,6 +252,47 @@ if [ "$USE_PREBUILT" = true ]; then # Adjust step numbers for rest of script STEP_OFFSET=-4 else + echo -e "${GREEN}[5/12]${NC} Installing pyenv and Python $PYTHON_VERSION..." + + # Install pyenv if not present + if [ ! -d "$HOME/.pyenv" ]; then + curl https://pyenv.run | bash + + # Add pyenv to current shell + export PYENV_ROOT="$HOME/.pyenv" + export PATH="$PYENV_ROOT/bin:$PATH" + eval "$(pyenv init -)" + + # Add to .bashrc if not already there + if ! grep -q 'PYENV_ROOT' ~/.bashrc; then + echo '' >> ~/.bashrc + echo '# pyenv' >> ~/.bashrc + echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc + echo '[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc + echo 'eval "$(pyenv init - bash)"' >> ~/.bashrc + fi + else + echo " pyenv already installed" + export PYENV_ROOT="$HOME/.pyenv" + export PATH="$PYENV_ROOT/bin:$PATH" + eval "$(pyenv init -)" + fi + + # Install Python 3.12 if not present + if ! pyenv versions | grep -q "$PYTHON_VERSION"; then + echo " Building Python $PYTHON_VERSION (this takes ~10 minutes)..." + pyenv install $PYTHON_VERSION + else + echo " Python $PYTHON_VERSION already installed" + fi + pyenv global $PYTHON_VERSION + + # Verify Python version + INSTALLED_PY=$(python --version 2>&1 | cut -d' ' -f2 | cut -d'.' -f1,2) + if [ "$INSTALLED_PY" != "$PYTHON_VERSION" ]; then + echo -e "${RED}Error: Python $PYTHON_VERSION not active. Got: $INSTALLED_PY${NC}" + exit 1 + fi echo -e "${GREEN}[6/12]${NC} Creating Python virtual environment..." echo -e " ${YELLOW}Note: No pre-built venv found. Building from source (20+ min)${NC}" echo -e " ${YELLOW}To speed up future installs, add stegasoo-venv-pi-arm64.tar.gz to rpi/${NC}"