#!/bin/bash # # Stegasoo Raspberry Pi Setup Script # Tested on: Raspberry Pi 4/5 with Raspberry Pi OS (64-bit) # # Usage: # curl -sSL https://raw.githubusercontent.com/adlee-was-taken/stegasoo/4.2/rpi/setup.sh | bash # # or # wget -qO- https://raw.githubusercontent.com/adlee-was-taken/stegasoo/4.2/rpi/setup.sh | bash # # What this script does: # 1. Installs system dependencies # 2. Verifies Python 3.11+ (uses system Python) # 3. Installs jpeglib for DCT steganography (Python 3.11-3.14 compatible) # 4. Installs Stegasoo with web UI # 5. Creates systemd service for auto-start # 6. Enables the service # set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' GRAY='\033[0;90m' BOLD='\033[1m' NC='\033[0m' # No Color # Source banner.sh if available (for local runs), otherwise define inline SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)" if [ -f "$SCRIPT_DIR/banner.sh" ]; then source "$SCRIPT_DIR/banner.sh" else # Inline banner functions for curl-pipe execution print_gradient_line() { echo -e "\033[38;5;93m══════════════\033[38;5;99m══════════════\033[38;5;105m══════════════\033[38;5;117m══════════════\033[0m" } print_banner() { local subtitle="$1" echo "" print_gradient_line echo -e "\033[0;90m · . · . * · . * · . * · . * · . * · . ·\033[0m" echo -e "\033[38;5;220m ___ _____ ___ ___ _ ___ ___ ___\033[0m" echo -e "\033[38;5;220m / __||_ _|| __| / __| /_\\ / __| / _ \\ / _ \\\\\033[0m" echo -e "\033[38;5;220m \\__ \\ | | | _| | (_ | / _ \\ \\__ \\ | (_) || (_) |\033[0m" echo -e "\033[38;5;220m |___/ |_| |___| \\___//_/ \\_\\|___/ \\___/ \\___/\033[0m" echo -e "\033[0;90m · . · . * · . * · . * · . * · . * · . ·\033[0m" print_gradient_line if [ -n "$subtitle" ]; then echo -e "\033[1;37m ${subtitle}\033[0m" print_gradient_line fi } fi # Show help show_help() { echo "Stegasoo Raspberry Pi Setup Script" echo "" echo "Usage: $0 [options]" echo "" echo "Options:" echo " -h, --help Show this help message" echo " --no-prebuilt Build from source instead of using pre-built venv" echo " --from-source Same as --no-prebuilt" echo "" echo "Configuration:" echo " Config files are loaded in order (later overrides earlier):" echo " 1. /etc/stegasoo.conf" echo " 2. ~/.config/stegasoo/stegasoo.conf" echo " 3. Environment variables" echo "" echo " Available variables:" echo " INSTALL_DIR Install location (default: /opt/stegasoo)" echo " STEGASOO_REPO Git repo URL" echo " STEGASOO_BRANCH Git branch (default: 4.2)" echo "" echo " Example:" echo " export INSTALL_DIR=\"/home/pi/stegasoo\"" echo " ./setup.sh" echo "" exit 0 } # Parse args for arg in "$@"; do case $arg in -h|--help) show_help ;; esac done # Default configuration INSTALL_DIR="${INSTALL_DIR:-/opt/stegasoo}" STEGASOO_REPO="${STEGASOO_REPO:-https://github.com/adlee-was-taken/stegasoo.git}" STEGASOO_BRANCH="${STEGASOO_BRANCH:-4.2}" # Load config files (system, then user - user overrides system) for config_file in "/etc/stegasoo.conf" "$HOME/.config/stegasoo/stegasoo.conf"; do if [ -f "$config_file" ]; then # shellcheck source=/dev/null source "$config_file" fi done clear print_banner "Raspberry Pi Setup" echo "" echo " This will install Stegasoo with full DCT support" echo " Estimated time: ~2 minutes (pre-built) or 5-10 min (from source)" echo "" # Check if running on ARM ARCH=$(uname -m) if [[ "$ARCH" != "aarch64" && "$ARCH" != "arm64" ]]; then echo -e "${RED}Error: This script is for ARM64 systems (Raspberry Pi).${NC}" echo "Detected architecture: $ARCH" exit 1 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 TOTAL_MEM=$(free -m | awk '/^Mem:/{print $2}') if [ "$TOTAL_MEM" -lt 2000 ]; then echo -e "${YELLOW}Warning: Less than 2GB RAM detected ($TOTAL_MEM MB).${NC}" echo "Stegasoo Web UI requires ~768MB for Argon2 operations." echo "Consider using a Pi with more RAM for best results." read -p "Continue anyway? [y/N] " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 1 fi fi # ============================================================================= # Installation # ============================================================================= echo -e "${GREEN}[1/9]${NC} Setting up install directory..." if [ ! -d "$INSTALL_DIR" ]; then sudo mkdir -p "$INSTALL_DIR" sudo chown "$USER:$USER" "$INSTALL_DIR" echo " Created $INSTALL_DIR" else # Ensure current user owns it sudo chown "$USER:$USER" "$INSTALL_DIR" echo " $INSTALL_DIR exists, updated ownership" fi echo -e "${GREEN}[2/9]${NC} Installing system dependencies..." sudo apt-get update sudo apt-get install -y \ build-essential \ git \ curl \ zstd \ libssl-dev \ zlib1g-dev \ libbz2-dev \ libreadline-dev \ libsqlite3-dev \ libncursesw5-dev \ xz-utils \ tk-dev \ libxml2-dev \ libxmlsec1-dev \ libffi-dev \ liblzma-dev \ libzbar0 \ libjpeg-dev \ python3-dev \ python3-venv \ python3-pip \ btop echo -e "${GREEN}[3/9]${NC} Installing gum (TUI toolkit)..." # Add Charm repo for gum if ! command -v gum &>/dev/null; then sudo mkdir -p /etc/apt/keyrings curl -fsSL https://repo.charm.sh/apt/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/charm.gpg echo "deb [signed-by=/etc/apt/keyrings/charm.gpg] https://repo.charm.sh/apt/ * *" | sudo tee /etc/apt/sources.list.d/charm.list sudo apt-get update sudo apt-get install -y gum else echo " gum already installed" fi # Install mkcert for browser-trusted certificates (no warning screen!) echo " Installing mkcert for trusted HTTPS certificates..." if ! command -v mkcert &>/dev/null; then sudo apt-get install -y libnss3-tools # Download mkcert for ARM64 sudo curl -sL "https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-arm64" -o /usr/local/bin/mkcert sudo chmod +x /usr/local/bin/mkcert # Install local CA (makes certs trusted on this Pi) mkcert -install 2>/dev/null || true echo " mkcert installed" else echo " mkcert already installed" fi echo -e "${GREEN}[4/9]${NC} Cloning Stegasoo..." # Clone Stegasoo first (needed to check for pre-built tarball) if [ -d "$INSTALL_DIR/.git" ]; then echo " Stegasoo directory exists, updating..." cd "$INSTALL_DIR" git fetch origin git checkout "$STEGASOO_BRANCH" git pull origin "$STEGASOO_BRANCH" else git clone -b "$STEGASOO_BRANCH" "$STEGASOO_REPO" "$INSTALL_DIR" cd "$INSTALL_DIR" fi # Pre-built venv tarball (skips pip compile time) PREBUILT_TARBALL="$INSTALL_DIR/rpi/stegasoo-rpi-venv-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}" USE_PREBUILT=true # Use local tarball if present, otherwise will download if [ -f "$PREBUILT_TARBALL" ]; then echo -e "${GREEN}Found local pre-built venv - fast install mode${NC}" else echo -e "${GREEN}Will download pre-built venv - fast install mode${NC}" fi # Allow --no-prebuilt flag to force from-source build if [[ " $* " =~ " --no-prebuilt " ]] || [[ " $* " =~ " --from-source " ]]; then USE_PREBUILT=false echo -e "${YELLOW}Building from source (--no-prebuilt specified)${NC}" fi echo -e "${GREEN}[5/9]${NC} Setting up Python environment..." if [ "$USE_PREBUILT" = true ]; then # Fast path: use pre-built venv # Download if local file doesn't exist if [ ! -f "$PREBUILT_TARBALL" ]; then echo " Downloading pre-built venv (~50MB)..." curl -L -o "$PREBUILT_TARBALL" "$PREBUILT_URL" fi # Extract pre-built venv echo " Extracting pre-built venv..." zstd -d "$PREBUILT_TARBALL" --stdout | tar -xf - -C "$INSTALL_DIR" # Fix venv Python symlinks to point to system Python echo " Updating venv to use system Python..." rm -f "$INSTALL_DIR/venv/bin/python" "$INSTALL_DIR/venv/bin/python3" ln -s "$SYSTEM_PYTHON" "$INSTALL_DIR/venv/bin/python" ln -s "$SYSTEM_PYTHON" "$INSTALL_DIR/venv/bin/python3" # Update pip shebang if needed if [ -f "$INSTALL_DIR/venv/bin/pip" ]; then sed -i "1s|^#!.*|#!$INSTALL_DIR/venv/bin/python|" "$INSTALL_DIR/venv/bin/pip" 2>/dev/null || true fi # Activate and verify 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" # Install stegasoo package in editable mode (quick, no compile) echo " Installing Stegasoo package..." pip install -e "." --quiet else # Build from source echo -e " ${YELLOW}Building from source (this takes 5-10 minutes)${NC}" # Create venv with system Python if [ ! -d "$INSTALL_DIR/venv" ]; then "$SYSTEM_PYTHON" -m venv "$INSTALL_DIR/venv" fi source "$INSTALL_DIR/venv/bin/activate" # Verify we're using the right Python VENV_PY=$(python --version 2>&1 | cut -d' ' -f2 | cut -d'.' -f1,2) echo " venv Python: $VENV_PY" # Upgrade pip and install build tools pip install --upgrade pip setuptools wheel # Install jpeglib (no ARM64 wheel, PyPI tarball missing headers - use GitHub) echo " Installing jpeglib for ARM64..." JPEGLIB_WORKDIR=$(mktemp -d) cd "$JPEGLIB_WORKDIR" # Clone from GitHub (PyPI source tarball is missing .h files) echo " Cloning jpeglib from GitHub..." git clone --depth 1 --branch 1.0.2 https://github.com/martinbenes1996/jpeglib.git cd jpeglib CJPEGLIB="src/jpeglib/cjpeglib" # Fix broken include paths in setup.py (uses jpeglib/ but files are in src/jpeglib/) ln -s src/jpeglib jpeglib # Download libjpeg headers (not included in repo either) # Each version needs its matching headers (APIs changed between versions) echo " Downloading libjpeg headers..." # 6b curl -sL "https://www.ijg.org/files/jpegsrc.v6b.tar.gz" | tar -xzf - cp jpeg-6b/*.h "$CJPEGLIB/6b/" # 7 curl -sL "https://www.ijg.org/files/jpegsrc.v7.tar.gz" | tar -xzf - cp jpeg-7/*.h "$CJPEGLIB/7/" # 8 series curl -sL "https://www.ijg.org/files/jpegsrc.v8d.tar.gz" | tar -xzf - for v in 8 8a 8b 8c 8d; do cp jpeg-8d/*.h "$CJPEGLIB/$v/" done # 9 series curl -sL "https://www.ijg.org/files/jpegsrc.v9f.tar.gz" | tar -xzf - for v in 9 9a 9b 9c 9d 9e 9f; do cp jpeg-9f/*.h "$CJPEGLIB/$v/" done echo " Downloading libjpeg-turbo headers..." curl -sL "https://github.com/libjpeg-turbo/libjpeg-turbo/archive/refs/tags/2.1.0.tar.gz" | tar -xzf - for v in turbo120 turbo130 turbo140 turbo150 turbo200 turbo210; do cp libjpeg-turbo-2.1.0/*.h "$CJPEGLIB/$v/" 2>/dev/null || true done echo " Downloading mozjpeg headers..." curl -sL "https://github.com/mozilla/mozjpeg/archive/refs/tags/v4.0.3.tar.gz" | tar -xzf - for v in mozjpeg101 mozjpeg201 mozjpeg300 mozjpeg403; do cp mozjpeg-4.0.3/*.h "$CJPEGLIB/$v/" 2>/dev/null || true done # Build and install echo " Building jpeglib (this takes a few minutes)..." pip install . cd "$INSTALL_DIR" rm -rf "$JPEGLIB_WORKDIR" # Install remaining dependencies echo " Installing remaining dependencies..." pip install -e ".[web]" fi echo -e " ${GREEN}✓${NC} Stegasoo installed" echo -e "${GREEN}[6/9]${NC} Creating systemd services..." # Create systemd service file for Web UI sudo tee /etc/systemd/system/stegasoo.service > /dev/null < /dev/null < /dev/null <<'PATHEOF' # Stegasoo CLI and scripts if [ -d /opt/stegasoo/venv/bin ]; then export PATH="/opt/stegasoo/venv/bin:$PATH" fi if [ -d /opt/stegasoo/rpi ]; then export PATH="/opt/stegasoo/rpi:$PATH" fi PATHEOF sudo chmod 644 /etc/profile.d/stegasoo-path.sh echo " Added stegasoo to PATH" # Install custom bashrc if not already customized if [ -f "$INSTALL_DIR/rpi/skel/.bashrc" ]; then if ! grep -q "Stegasoo Pi" ~/.bashrc 2>/dev/null; then cp "$INSTALL_DIR/rpi/skel/.bashrc" ~/.bashrc source ~/.bashrc 2>/dev/null || true echo " Installed custom .bashrc" else echo " Custom .bashrc already installed" fi fi # Install man page if [ -f "$INSTALL_DIR/docs/stegasoo.1" ]; then sudo mkdir -p /usr/local/share/man/man1 sudo cp "$INSTALL_DIR/docs/stegasoo.1" /usr/local/share/man/man1/ sudo mandb -q 2>/dev/null || true echo " Installed man page (man stegasoo)" fi echo -e "${GREEN}[9/9]${NC} Setting up login banner..." # Create dynamic MOTD script sudo tee /etc/profile.d/stegasoo-motd.sh > /dev/null <<'MOTDEOF' # Stegasoo login banner if systemctl is-active --quiet stegasoo 2>/dev/null; then PI_IP=$(hostname -I | awk '{print $1}') # Check if HTTPS and port 443 are configured if systemctl show stegasoo -p Environment 2>/dev/null | grep -q "STEGASOO_HTTPS_ENABLED=true"; then # Check for port 443 redirect (iptables-restore service means 443 is configured) if systemctl is-enabled --quiet iptables-restore 2>/dev/null; then STEGASOO_URL="https://$PI_IP" else STEGASOO_URL="https://$PI_IP:5000" fi else STEGASOO_URL="http://$PI_IP:5000" fi echo "" echo -e "\033[38;5;93m══════════════\033[38;5;99m══════════════\033[38;5;105m══════════════\033[38;5;117m══════════════\033[0m" echo -e "\033[0;90m · . · . * · . * · . * · . * · . * · . ·\033[0m" echo -e "\033[38;5;220m ___ _____ ___ ___ _ ___ ___ ___\033[0m" echo -e "\033[38;5;220m / __||_ _|| __| / __| /_\\ / __| / _ \\ / _ \\\\\033[0m" echo -e "\033[38;5;220m \\__ \\ | | | _| | (_ | / _ \\ \\__ \\ | (_) || (_) |\033[0m" echo -e "\033[38;5;220m |___/ |_| |___| \\___//_/ \\_\\|___/ \\___/ \\___/\033[0m" echo -e "\033[0;90m · . · . * · . * · . * · . * · . * · . ·\033[0m" echo -e "\033[38;5;93m══════════════\033[38;5;99m══════════════\033[38;5;105m══════════════\033[38;5;117m══════════════\033[0m" # Show CPU stats if overclocked (read configured freq, not current idle freq) CONFIG_FILE="" if [ -f /boot/firmware/config.txt ]; then CONFIG_FILE="/boot/firmware/config.txt" elif [ -f /boot/config.txt ]; then CONFIG_FILE="/boot/config.txt"; fi CPU_MHZ="" CPU_TEMP="" if [ -n "$CONFIG_FILE" ] && grep -qE "^arm_freq=" "$CONFIG_FILE" 2>/dev/null; then CPU_MHZ=$(grep "^arm_freq=" "$CONFIG_FILE" | cut -d= -f2) CPU_TEMP=$(vcgencmd measure_temp 2>/dev/null | cut -d= -f2) fi # Compact two-column layout echo -e " 🚀 Stegasoo running 🌐 \033[0;33m$STEGASOO_URL\033[0m" if [ -n "$CPU_MHZ" ] && [ -n "$CPU_TEMP" ]; then # Temp emoji: ice<50, cool 50-70, fire>70 TEMP_NUM=$(echo "$CPU_TEMP" | grep -oE "[0-9]+" | head -1) if [ -n "$TEMP_NUM" ]; then if [ "$TEMP_NUM" -ge 70 ]; then TEMP_EMOJI="🔥" elif [ "$TEMP_NUM" -ge 50 ]; then TEMP_EMOJI="😎" else TEMP_EMOJI="🧊" fi else TEMP_EMOJI="🌡" fi echo -e " \033[0;35m⚡\033[0m ${CPU_MHZ} MHz ${TEMP_EMOJI} ${CPU_TEMP}" fi echo -e "\033[38;5;93m══════════════\033[38;5;99m══════════════\033[38;5;105m══════════════\033[38;5;117m══════════════\033[0m" echo "" else echo "" echo -e " \033[0;31m●\033[0m Stegasoo is not running" echo -e " Start with: sudo systemctl start stegasoo" echo "" fi MOTDEOF sudo chmod 644 /etc/profile.d/stegasoo-motd.sh echo " Created login banner" # Shorten the default Debian MOTD boilerplate echo "Debian GNU/Linux · License: /usr/share/doc/*/copyright" | sudo tee /etc/motd > /dev/null echo " Shortened system MOTD" echo "" echo -e "${BOLD}Installation Complete!${NC}" echo -e "${BLUE}-------------------------------------------------------${NC}" echo "" echo -e "Stegasoo installed to: ${YELLOW}$INSTALL_DIR${NC}" echo "" # ============================================================================= # Interactive Configuration # ============================================================================= echo -e "${BOLD}Configuration${NC}" echo -e "${BLUE}-------------------------------------------------------${NC}" echo "" # Track configuration choices ENABLE_HTTPS="false" USE_PORT_443="false" CHANNEL_KEY="" # --- HTTPS Configuration --- echo -e "${GREEN}HTTPS Configuration${NC}" echo " HTTPS encrypts traffic with a self-signed certificate." echo " (Browser will show a security warning - this is normal for self-signed certs)" echo "" read -p "Enable HTTPS? [y/N] " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then ENABLE_HTTPS="true" echo -e " ${GREEN}✓${NC} HTTPS will be enabled" # --- Port 443 Configuration --- echo "" echo -e "${GREEN}Port Configuration${NC}" echo " Standard HTTPS port is 443 (no port needed in URL)." echo " This requires iptables to redirect 443 → 5000." echo "" read -p "Use standard port 443? [y/N] " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then USE_PORT_443="true" echo -e " ${GREEN}✓${NC} Port 443 will be configured" else echo -e " ${YELLOW}→${NC} Using default port 5000" fi else echo -e " ${YELLOW}→${NC} Using HTTP (unencrypted)" fi # --- Channel Key Configuration --- echo "" echo -e "${GREEN}Channel Key Configuration${NC}" echo " A channel key creates a private encoding channel." echo " Only users with the same key can decode each other's images." echo "" read -p "Generate a private channel key? [y/N] " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then # Generate channel key and save encrypted to config CHANNEL_KEY=$($INSTALL_DIR/venv/bin/python -c " from stegasoo.channel import generate_channel_key, set_channel_key key = generate_channel_key() set_channel_key(key, 'user') # Saves encrypted to ~/.stegasoo/channel.key print(key) ") echo -e " ${GREEN}✓${NC} Channel key generated: ${YELLOW}$CHANNEL_KEY${NC}" echo -e " ${GREEN}✓${NC} Key saved (encrypted) to ~/.stegasoo/channel.key" echo "" echo -e " ${RED}IMPORTANT: Save this key!${NC} You'll need to share it with anyone" echo " who should be able to decode your images." else echo -e " ${YELLOW}→${NC} Using public mode (no channel isolation)" fi # ============================================================================= # Apply Configuration # ============================================================================= echo "" echo -e "${BLUE}Applying configuration...${NC}" # Update systemd service with configuration sudo tee /etc/systemd/system/stegasoo.service > /dev/null < /dev/null; then echo " Using mkcert for browser-trusted certificates..." cd "$CERT_DIR" mkcert -key-file server.key -cert-file server.crt \ "$PI_HOSTNAME" "$PI_HOSTNAME.local" localhost "$LOCAL_IP" 127.0.0.1 ::1 # Copy CA to web-accessible location for easy device setup CA_ROOT=$(mkcert -CAROOT) CA_DIR="$INSTALL_DIR/frontends/web/static/ca" mkdir -p "$CA_DIR" cp "$CA_ROOT/rootCA.pem" "$CA_DIR/" echo -e " ${GREEN}✓${NC} Trusted certificates generated with mkcert" echo -e " ${CYAN}Tip:${NC} New devices can get the CA from: http://$PI_HOSTNAME.local/static/ca/rootCA.pem" else # Fallback to self-signed (shows browser warning) echo " Using self-signed certificate (browser will show warning)" echo " Tip: Install mkcert for trusted certs without warnings" openssl req -x509 -newkey rsa:2048 \ -keyout "$CERT_DIR/server.key" \ -out "$CERT_DIR/server.crt" \ -days 365 -nodes \ -subj "/O=Stegasoo/CN=$PI_HOSTNAME" \ -addext "subjectAltName=DNS:$PI_HOSTNAME,DNS:$PI_HOSTNAME.local,DNS:localhost,IP:$LOCAL_IP,IP:127.0.0.1" \ 2>/dev/null echo -e " ${GREEN}✓${NC} Self-signed certificates generated" fi # Fix permissions chmod 600 "$CERT_DIR/server.key" chown -R "$USER:$USER" "$CERT_DIR" fi # Setup port 443 redirect if requested if [ "$USE_PORT_443" = "true" ]; then echo " Setting up port 443 redirect..." # Install iptables if needed if ! command -v iptables &> /dev/null; then sudo apt-get install -y iptables fi # Add redirect rule sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 5000 sudo sh -c 'iptables-save > /etc/iptables.rules' # Create systemd service to restore rules on boot sudo tee /etc/systemd/system/iptables-restore.service > /dev/null <