RPi: Remove pyenv, use system Python 3.11+

- Rewrite setup.sh to use system Python instead of pyenv
- Add Python version check (3.11-3.14 supported)
- Remove jpegio build steps (jpeglib installs cleanly via pip)
- Simplify prebuilt tarball (just venv, no pyenv)
- Reduce install time: 5-10 min from source (was 15-20 min)
- Update README.md and BUILD_IMAGE.md accordingly

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Aaron D. Lee
2026-01-10 21:35:50 -05:00
parent fae86887e2
commit c058d116b8
3 changed files with 160 additions and 186 deletions

View File

@@ -26,11 +26,11 @@ ssh admin@stegasoo.local
## Step 3: Pre-Setup ## Step 3: Pre-Setup
```bash ```bash
# Take ownership of /opt (for pyenv, jpegio builds) # Take ownership of /opt
sudo chown admin:admin /opt sudo chown admin:admin /opt
# Install git and zstd (not included in Lite image) # Install git (not included in Lite image)
sudo apt-get update && sudo apt-get install -y git zstd jq sudo apt-get update && sudo apt-get install -y git
``` ```
## Step 4: Clone Repo ## Step 4: Clone Repo
@@ -40,37 +40,36 @@ cd /opt
git clone -b 4.2 https://github.com/adlee-was-taken/stegasoo.git stegasoo git clone -b 4.2 https://github.com/adlee-was-taken/stegasoo.git stegasoo
``` ```
## Step 5: Copy Pre-built Tarball (from host) ## Step 5: Run Setup
> **Dev-only asset:** This tarball is for building Pi images, not for end users.
> It's available on [Releases](https://github.com/adlee-was-taken/stegasoo/releases) for image builders.
```bash
# On your host machine:
scp rpi/stegasoo-rpi-runtime-env-arm64.tar.zst admin@stegasoo.local:/opt/stegasoo/rpi/
```
This tarball contains:
- pyenv with Python 3.12 (pre-compiled for ARM64)
- venv with all dependencies (jpegio, scipy, etc.)
Install time: **~2 minutes** (vs 20+ min from source)
## Step 6: Run Setup
```bash ```bash
cd /opt/stegasoo cd /opt/stegasoo
./rpi/setup.sh # Detects local tarball, skips download ./rpi/setup.sh
``` ```
### From-Source Build (optional) The setup script:
- Verifies Python 3.11+ (system Python, no pyenv needed)
- Installs dependencies via apt and pip
- jpeglib installs cleanly (no ARM patching like jpegio)
- Creates and enables systemd service
Install time: **5-10 minutes** (from source)
### Pre-built Venv (optional)
For faster installs, you can provide a pre-built venv tarball:
To build without the pre-built tarball:
```bash ```bash
./rpi/setup.sh --no-prebuilt # Takes 15-20 minutes # On your host machine:
scp rpi/stegasoo-rpi-venv-arm64.tar.zst admin@stegasoo.local:/opt/stegasoo/rpi/
# Then on Pi:
cd /opt/stegasoo && ./rpi/setup.sh # Detects local tarball, skips pip build
``` ```
## Step 7: Test It Works Install time with pre-built: **~2 minutes**
## Step 6: Test It Works
```bash ```bash
sudo systemctl start stegasoo sudo systemctl start stegasoo
@@ -78,7 +77,7 @@ curl -k https://localhost:5000
# Should return HTML # Should return HTML
``` ```
## Step 8: Sanitize for Distribution ## Step 7: Sanitize for Distribution
```bash ```bash
# Full sanitize (for final image - removes WiFi, shuts down) # Full sanitize (for final image - removes WiFi, shuts down)
@@ -98,7 +97,7 @@ This removes:
The script validates all cleanup steps before finishing. The script validates all cleanup steps before finishing.
## Step 9: Pull the Image ## Step 8: Pull the Image
Remove SD card, insert into your Linux machine: Remove SD card, insert into your Linux machine:
@@ -112,7 +111,7 @@ sudo ./rpi/pull-image.sh /dev/sdX stegasoo-rpi-4.2.0.img.zst
The script automatically resizes rootfs to 16GB (for smaller download), preserves auto-expand, and compresses. The script automatically resizes rootfs to 16GB (for smaller download), preserves auto-expand, and compresses.
## Step 10: Distribute ## Step 9: Distribute
Upload `.img.zst` to GitHub Releases. Upload `.img.zst` to GitHub Releases.
@@ -130,36 +129,31 @@ zstdcat stegasoo-rpi-*.img.zst | sudo dd of=/dev/sdX bs=4M status=progress
--- ---
## Creating the Pre-built Tarball ## Creating the Pre-built Venv Tarball
After a successful from-source build, create the pre-built tarball for future installs: After a successful from-source build, create the pre-built tarball for future installs:
```bash ```bash
# On the Pi after successful setup: # On the Pi after successful setup:
cd ~ cd /opt/stegasoo
# Strip caches and tests from venv (295MB → 208MB) # Strip caches and tests from venv (saves ~100MB)
find /opt/stegasoo/venv/ -type d -name '__pycache__' -exec rm -rf {} + 2>/dev/null find 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 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 find venv/ -type d -name 'test' -exec rm -rf {} + 2>/dev/null
# Create venv tarball # Create venv tarball
cd /opt/stegasoo tar -cf - venv/ | zstd -19 -T0 > /tmp/stegasoo-rpi-venv-arm64.tar.zst
tar -cf - venv/ | zstd -19 -T0 > ~/stegasoo-venv.tar.zst
# Create combined tarball (pyenv + venv pointer) # Check size (should be ~40-50MB)
cd ~ ls -lh /tmp/stegasoo-rpi-venv-arm64.tar.zst
tar -cf - .pyenv stegasoo-venv.tar.zst | zstd -19 -T0 > /tmp/stegasoo-rpi-runtime-env-arm64.tar.zst
# Check size (should be ~50-60MB)
ls -lh /tmp/stegasoo-rpi-runtime-env-arm64.tar.zst
``` ```
Pull to host and upload to GitHub releases: Pull to host and upload to GitHub releases:
```bash ```bash
# On host: # On host:
scp admin@stegasoo.local:/tmp/stegasoo-rpi-runtime-env-arm64.tar.zst ./ scp admin@stegasoo.local:/tmp/stegasoo-rpi-venv-arm64.tar.zst ./rpi/
# Upload to GitHub releases as stegasoo-rpi-runtime-env-arm64.tar.zst # Upload to GitHub releases as stegasoo-rpi-venv-arm64.tar.zst
``` ```
--- ---
@@ -169,13 +163,10 @@ scp admin@stegasoo.local:/tmp/stegasoo-rpi-runtime-env-arm64.tar.zst ./
```bash ```bash
# On Pi (after SSH): # On Pi (after SSH):
sudo chown admin:admin /opt sudo chown admin:admin /opt
sudo apt-get update && sudo apt-get install -y git zstd jq sudo apt-get update && sudo apt-get install -y git
cd /opt && git clone -b 4.2 https://github.com/adlee-was-taken/stegasoo.git stegasoo cd /opt && git clone -b 4.2 https://github.com/adlee-was-taken/stegasoo.git stegasoo
# On host (copy tarball): # Run setup:
scp rpi/stegasoo-rpi-runtime-env-arm64.tar.zst admin@stegasoo.local:/opt/stegasoo/rpi/
# On Pi (run setup):
cd /opt/stegasoo && ./rpi/setup.sh cd /opt/stegasoo && ./rpi/setup.sh
sudo systemctl start stegasoo sudo systemctl start stegasoo
curl -k https://localhost:5000 curl -k https://localhost:5000

View File

@@ -4,7 +4,7 @@ Scripts and resources for deploying Stegasoo on Raspberry Pi.
## Quick Install ## Quick Install
On a fresh Raspberry Pi OS Lite (64-bit) installation: On a fresh Raspberry Pi OS (64-bit) installation:
```bash ```bash
# Pre-setup (git not included in Lite image) # Pre-setup (git not included in Lite image)
@@ -20,9 +20,9 @@ cd stegasoo
## What the Setup Script Does ## What the Setup Script Does
1. **Installs system dependencies** - build tools, libraries 1. **Verifies Python 3.11+** - uses system Python (no pyenv needed)
2. **Installs Python 3.12** - via pyenv (Pi OS ships with 3.13 which is incompatible) 2. **Installs system dependencies** - build tools, libraries
3. **Builds jpegio for ARM** - patches x86-specific flags 3. **Installs jpeglib** - DCT steganography (Python 3.11-3.14 compatible)
4. **Installs Stegasoo** - with web UI and all dependencies 4. **Installs Stegasoo** - with web UI and all dependencies
5. **Creates systemd service** - auto-starts on boot 5. **Creates systemd service** - auto-starts on boot
6. **Enables the service** - ready to start 6. **Enables the service** - ready to start
@@ -30,11 +30,18 @@ cd stegasoo
## Requirements ## Requirements
- Raspberry Pi 4 or 5 - Raspberry Pi 4 or 5
- Raspberry Pi OS Lite (64-bit) - Bookworm or later - Raspberry Pi OS (64-bit) - Bookworm (Python 3.11) or Trixie (Python 3.13)
- 4GB+ RAM recommended (2GB minimum) - 4GB+ RAM recommended (2GB minimum)
- 16GB+ SD card (pre-built images are 16GB) - 16GB+ SD card (pre-built images are 16GB)
- Internet connection - Internet connection
### Python Compatibility
| Raspberry Pi OS | Python | Supported |
|-----------------|--------|-----------|
| Bookworm | 3.11 | Yes |
| Trixie | 3.13 | Yes |
### Performance ### Performance
On a Pi 4 at 2GHz with USB 3.0 NVMe, expect ~60 seconds to encode/decode a 10MB JPEG with full encryption (passphrase + PIN + reference photo). On a Pi 4 at 2GHz with USB 3.0 NVMe, expect ~60 seconds to encode/decode a 10MB JPEG with full encryption (passphrase + PIN + reference photo).

View File

@@ -10,8 +10,8 @@
# #
# What this script does: # What this script does:
# 1. Installs system dependencies # 1. Installs system dependencies
# 2. Installs Python 3.11+ (uses system Python or pyenv) # 2. Verifies Python 3.11+ (uses system Python)
# 3. Installs jpeglib for DCT steganography (Python 3.13+ compatible) # 3. Installs jpeglib for DCT steganography (Python 3.11-3.14 compatible)
# 4. Installs Stegasoo with web UI # 4. Installs Stegasoo with web UI
# 5. Creates systemd service for auto-start # 5. Creates systemd service for auto-start
# 6. Enables the service # 6. Enables the service
@@ -75,7 +75,6 @@ show_help() {
echo "" echo ""
echo " Available variables:" echo " Available variables:"
echo " INSTALL_DIR Install location (default: /opt/stegasoo)" echo " INSTALL_DIR Install location (default: /opt/stegasoo)"
echo " PYTHON_VERSION Python version (default: 3.12)"
echo " STEGASOO_REPO Git repo URL" echo " STEGASOO_REPO Git repo URL"
echo " STEGASOO_BRANCH Git branch (default: 4.2)" echo " STEGASOO_BRANCH Git branch (default: 4.2)"
echo "" echo ""
@@ -95,7 +94,6 @@ done
# Default configuration # Default configuration
INSTALL_DIR="${INSTALL_DIR:-/opt/stegasoo}" INSTALL_DIR="${INSTALL_DIR:-/opt/stegasoo}"
PYTHON_VERSION="${PYTHON_VERSION:-3.12}"
STEGASOO_REPO="${STEGASOO_REPO:-https://github.com/adlee-was-taken/stegasoo.git}" STEGASOO_REPO="${STEGASOO_REPO:-https://github.com/adlee-was-taken/stegasoo.git}"
STEGASOO_BRANCH="${STEGASOO_BRANCH:-4.2}" STEGASOO_BRANCH="${STEGASOO_BRANCH:-4.2}"
@@ -111,7 +109,7 @@ clear
print_banner "Raspberry Pi Setup" print_banner "Raspberry Pi Setup"
echo "" echo ""
echo " This will install Stegasoo with full DCT support" echo " This will install Stegasoo with full DCT support"
echo " Estimated time: ~2 minutes (pre-built) or 15-20 min (from source)" echo " Estimated time: ~2 minutes (pre-built) or 5-10 min (from source)"
echo "" echo ""
# Check if running on ARM # Check if running on ARM
@@ -122,6 +120,63 @@ if [[ "$ARCH" != "aarch64" && "$ARCH" != "arm64" ]]; then
exit 1 exit 1
fi fi
# =============================================================================
# Python Version Check
# =============================================================================
echo -e "${GREEN}Checking Python version...${NC}"
# Find system Python
SYSTEM_PYTHON=""
for py in python3.14 python3.13 python3.12 python3.11 python3; do
if command -v "$py" &>/dev/null; then
SYSTEM_PYTHON=$(command -v "$py")
break
fi
done
if [ -z "$SYSTEM_PYTHON" ]; then
echo -e "${RED}Error: Python 3 not found.${NC}"
echo "Please install Python 3.11 or later:"
echo " sudo apt-get install python3"
exit 1
fi
# Get version numbers
PY_VERSION=$("$SYSTEM_PYTHON" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
PY_MAJOR=$("$SYSTEM_PYTHON" -c 'import sys; print(sys.version_info.major)')
PY_MINOR=$("$SYSTEM_PYTHON" -c 'import sys; print(sys.version_info.minor)')
echo " Found: $SYSTEM_PYTHON (Python $PY_VERSION)"
# Check version range (3.11 <= version <= 3.14)
if [ "$PY_MAJOR" -ne 3 ]; then
echo -e "${RED}Error: Python 3 required, found Python $PY_MAJOR${NC}"
exit 1
fi
if [ "$PY_MINOR" -lt 11 ]; then
echo -e "${RED}Error: Python 3.11+ required, found Python $PY_VERSION${NC}"
echo ""
echo "Raspberry Pi OS Bookworm ships with Python 3.11."
echo "Raspberry Pi OS Trixie ships with Python 3.13."
echo ""
echo "Please upgrade your Raspberry Pi OS or install Python 3.11+."
exit 1
fi
if [ "$PY_MINOR" -gt 14 ]; then
echo -e "${YELLOW}Warning: Python $PY_VERSION detected.${NC}"
echo "Stegasoo is tested with Python 3.11-3.14."
echo "Newer versions may work but are not officially supported."
read -p "Continue anyway? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
echo -e " ${GREEN}${NC} Python $PY_VERSION supported"
# Check available memory # Check available memory
TOTAL_MEM=$(free -m | awk '/^Mem:/{print $2}') TOTAL_MEM=$(free -m | awk '/^Mem:/{print $2}')
if [ "$TOTAL_MEM" -lt 2000 ]; then if [ "$TOTAL_MEM" -lt 2000 ]; then
@@ -135,8 +190,11 @@ if [ "$TOTAL_MEM" -lt 2000 ]; then
fi fi
fi fi
# Create /opt/stegasoo with proper permissions # =============================================================================
echo -e "${GREEN}[1/12]${NC} Setting up install directory..." # Installation
# =============================================================================
echo -e "${GREEN}[1/9]${NC} Setting up install directory..."
if [ ! -d "$INSTALL_DIR" ]; then if [ ! -d "$INSTALL_DIR" ]; then
sudo mkdir -p "$INSTALL_DIR" sudo mkdir -p "$INSTALL_DIR"
sudo chown "$USER:$USER" "$INSTALL_DIR" sudo chown "$USER:$USER" "$INSTALL_DIR"
@@ -147,7 +205,7 @@ else
echo " $INSTALL_DIR exists, updated ownership" echo " $INSTALL_DIR exists, updated ownership"
fi fi
echo -e "${GREEN}[2/12]${NC} Installing system dependencies..." echo -e "${GREEN}[2/9]${NC} Installing system dependencies..."
sudo apt-get update sudo apt-get update
sudo apt-get install -y \ sudo apt-get install -y \
build-essential \ build-essential \
@@ -169,9 +227,11 @@ sudo apt-get install -y \
libzbar0 \ libzbar0 \
libjpeg-dev \ libjpeg-dev \
python3-dev \ python3-dev \
python3-venv \
python3-pip \
btop btop
echo -e "${GREEN}[3/12]${NC} Installing gum (TUI toolkit)..." echo -e "${GREEN}[3/9]${NC} Installing gum (TUI toolkit)..."
# Add Charm repo for gum # Add Charm repo for gum
if ! command -v gum &>/dev/null; then if ! command -v gum &>/dev/null; then
sudo mkdir -p /etc/apt/keyrings sudo mkdir -p /etc/apt/keyrings
@@ -197,7 +257,7 @@ else
echo " mkcert already installed" echo " mkcert already installed"
fi fi
echo -e "${GREEN}[4/12]${NC} Cloning Stegasoo..." echo -e "${GREEN}[4/9]${NC} Cloning Stegasoo..."
# Clone Stegasoo first (needed to check for pre-built tarball) # Clone Stegasoo first (needed to check for pre-built tarball)
if [ -d "$INSTALL_DIR/.git" ]; then if [ -d "$INSTALL_DIR/.git" ]; then
@@ -211,17 +271,16 @@ else
cd "$INSTALL_DIR" cd "$INSTALL_DIR"
fi fi
# Pre-built environment tarball (skips compile time) # Pre-built venv tarball (skips pip compile time)
# Includes venv with all dependencies PREBUILT_TARBALL="$INSTALL_DIR/rpi/stegasoo-rpi-venv-arm64.tar.zst"
PREBUILT_TARBALL="$INSTALL_DIR/rpi/stegasoo-rpi-runtime-env-arm64.tar.zst" PREBUILT_URL="${PREBUILT_URL:-https://github.com/adlee-was-taken/stegasoo/releases/download/v4.2.0/stegasoo-rpi-venv-arm64.tar.zst}"
PREBUILT_URL="${PREBUILT_URL:-https://github.com/adlee-was-taken/stegasoo/releases/download/v4.2.0/stegasoo-rpi-runtime-env-arm64.tar.zst}"
USE_PREBUILT=true USE_PREBUILT=true
# Use local tarball if present, otherwise will download # Use local tarball if present, otherwise will download
if [ -f "$PREBUILT_TARBALL" ]; then if [ -f "$PREBUILT_TARBALL" ]; then
echo -e "${GREEN}Found local pre-built environment - fast install mode${NC}" echo -e "${GREEN}Found local pre-built venv - fast install mode${NC}"
else else
echo -e "${GREEN}Will download pre-built environment - fast install mode${NC}" echo -e "${GREEN}Will download pre-built venv - fast install mode${NC}"
fi fi
# Allow --no-prebuilt flag to force from-source build # Allow --no-prebuilt flag to force from-source build
@@ -230,44 +289,30 @@ if [[ " $* " =~ " --no-prebuilt " ]] || [[ " $* " =~ " --from-source " ]]; then
echo -e "${YELLOW}Building from source (--no-prebuilt specified)${NC}" echo -e "${YELLOW}Building from source (--no-prebuilt specified)${NC}"
fi fi
# Fast path: use pre-built environment if available echo -e "${GREEN}[5/9]${NC} Setting up Python environment..."
if [ "$USE_PREBUILT" = true ]; then if [ "$USE_PREBUILT" = true ]; then
echo -e "${GREEN}[5/8]${NC} Installing pre-built Python environment..." # Fast path: use pre-built venv
# Download if local file doesn't exist # Download if local file doesn't exist
if [ ! -f "$PREBUILT_TARBALL" ]; then if [ ! -f "$PREBUILT_TARBALL" ]; then
echo " Downloading pre-built environment (~50MB)..." echo " Downloading pre-built venv (~50MB)..."
curl -L -o "$PREBUILT_TARBALL" "$PREBUILT_URL" curl -L -o "$PREBUILT_TARBALL" "$PREBUILT_URL"
fi fi
# Extract pre-built environment (includes pyenv Python + venv) # Extract pre-built venv
echo " Extracting pre-built environment..." echo " Extracting pre-built venv..."
zstd -d "$PREBUILT_TARBALL" --stdout | tar -xf - -C "$HOME" zstd -d "$PREBUILT_TARBALL" --stdout | tar -xf - -C "$INSTALL_DIR"
# Setup pyenv in current shell # Fix venv Python symlinks to point to system Python
export PYENV_ROOT="$HOME/.pyenv" echo " Updating venv to use system Python..."
export PATH="$PYENV_ROOT/bin:$PATH" rm -f "$INSTALL_DIR/venv/bin/python" "$INSTALL_DIR/venv/bin/python3"
eval "$(pyenv init -)" ln -s "$SYSTEM_PYTHON" "$INSTALL_DIR/venv/bin/python"
pyenv global $PYTHON_VERSION ln -s "$SYSTEM_PYTHON" "$INSTALL_DIR/venv/bin/python3"
# Add to .bashrc if not already there # Update pip shebang if needed
if ! grep -q 'PYENV_ROOT' ~/.bashrc; then if [ -f "$INSTALL_DIR/venv/bin/pip" ]; then
echo '' >> ~/.bashrc sed -i "1s|^#!.*|#!$INSTALL_DIR/venv/bin/python|" "$INSTALL_DIR/venv/bin/pip" 2>/dev/null || true
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
# 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 fi
# Activate and verify # Activate and verify
@@ -276,103 +321,34 @@ if [ "$USE_PREBUILT" = true ]; then
echo -e " ${GREEN}${NC} venv Python: $VENV_PY" echo -e " ${GREEN}${NC} venv Python: $VENV_PY"
# Install stegasoo package in editable mode (quick, no compile) # Install stegasoo package in editable mode (quick, no compile)
echo -e "${GREEN}[7/8]${NC} Installing Stegasoo package..." echo " Installing Stegasoo package..."
pip install -e "." --quiet pip install -e "." --quiet
# Adjust step numbers for rest of script
STEP_OFFSET=-4
else else
echo -e "${GREEN}[5/12]${NC} Installing pyenv and Python $PYTHON_VERSION..." # Build from source
echo -e " ${YELLOW}Building from source (this takes 5-10 minutes)${NC}"
# Install pyenv if not present # Create venv with system Python
if [ ! -d "$HOME/.pyenv" ]; then if [ ! -d "$INSTALL_DIR/venv" ]; then
curl https://pyenv.run | bash "$SYSTEM_PYTHON" -m venv "$INSTALL_DIR/venv"
# 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 fi
source "$INSTALL_DIR/venv/bin/activate"
# 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}"
# Create venv with pyenv Python (not system Python)
# Use pyenv which to get actual path (handles 3.12 -> 3.12.12 mapping)
PYENV_PYTHON=$(pyenv which python)
echo " Using Python: $PYENV_PYTHON"
if [ ! -d "venv" ]; then
"$PYENV_PYTHON" -m venv venv
fi
source venv/bin/activate
# Verify we're using the right Python # Verify we're using the right Python
VENV_PY=$(python --version 2>&1 | cut -d' ' -f2 | cut -d'.' -f1,2) VENV_PY=$(python --version 2>&1 | cut -d' ' -f2 | cut -d'.' -f1,2)
echo " venv Python: $VENV_PY" echo " venv Python: $VENV_PY"
echo -e "${GREEN}[7/12]${NC} Building jpegio for ARM..." # Upgrade pip and install build tools
pip install --upgrade pip setuptools wheel
# Clone jpegio # Install stegasoo with all dependencies
JPEGIO_DIR="/tmp/jpegio-build" # jpeglib installs cleanly via pip (no patching needed like jpegio)
rm -rf "$JPEGIO_DIR" echo " Installing dependencies (jpeglib, scipy, etc.)..."
git clone "$JPEGIO_REPO" "$JPEGIO_DIR"
# Apply ARM64 patch
if [ -f "$INSTALL_DIR/rpi/patches/jpegio/apply-patch.sh" ]; then
bash "$INSTALL_DIR/rpi/patches/jpegio/apply-patch.sh" "$JPEGIO_DIR"
else
echo " Applying inline ARM64 patch..."
sed -i "s/cargs.append('-m64')/pass # ARM64 fix/g" "$JPEGIO_DIR/setup.py"
fi
cd "$JPEGIO_DIR"
# Build jpegio into venv
pip install --upgrade pip setuptools wheel cython numpy
pip install .
cd "$INSTALL_DIR"
rm -rf "$JPEGIO_DIR"
echo -e "${GREEN}[8/12]${NC} Installing Stegasoo..."
# Install dependencies (jpegio already in venv, won't re-download)
pip install -e ".[web]" pip install -e ".[web]"
STEP_OFFSET=0
fi fi
echo -e "${GREEN}[9/12]${NC} Creating systemd services..." echo -e " ${GREEN}${NC} Stegasoo installed"
echo -e "${GREEN}[6/9]${NC} Creating systemd services..."
# Create systemd service file for Web UI # Create systemd service file for Web UI
sudo tee /etc/systemd/system/stegasoo.service > /dev/null <<EOF sudo tee /etc/systemd/system/stegasoo.service > /dev/null <<EOF
@@ -416,7 +392,7 @@ RestartSec=5
WantedBy=multi-user.target WantedBy=multi-user.target
EOF EOF
echo -e "${GREEN}[10/12]${NC} Enabling services..." echo -e "${GREEN}[7/9]${NC} Enabling services..."
sudo systemctl daemon-reload sudo systemctl daemon-reload
sudo systemctl enable stegasoo.service sudo systemctl enable stegasoo.service
@@ -442,7 +418,7 @@ else
echo " Can enable later with: sudo systemctl enable --now stegasoo-api" echo " Can enable later with: sudo systemctl enable --now stegasoo-api"
fi fi
echo -e "${GREEN}[11/12]${NC} Setting up user environment..." echo -e "${GREEN}[8/9]${NC} Setting up user environment..."
# Add stegasoo venv and rpi scripts to PATH for all users # Add stegasoo venv and rpi scripts to PATH for all users
sudo tee /etc/profile.d/stegasoo-path.sh > /dev/null <<'PATHEOF' sudo tee /etc/profile.d/stegasoo-path.sh > /dev/null <<'PATHEOF'
@@ -476,7 +452,7 @@ if [ -f "$INSTALL_DIR/docs/stegasoo.1" ]; then
echo " Installed man page (man stegasoo)" echo " Installed man page (man stegasoo)"
fi fi
echo -e "${GREEN}[12/12]${NC} Setting up login banner..." echo -e "${GREEN}[9/9]${NC} Setting up login banner..."
# Create dynamic MOTD script # Create dynamic MOTD script
sudo tee /etc/profile.d/stegasoo-motd.sh > /dev/null <<'MOTDEOF' sudo tee /etc/profile.d/stegasoo-motd.sh > /dev/null <<'MOTDEOF'