From 55fe0d068a196d85f2fa6358774d5eac58bc26a9 Mon Sep 17 00:00:00 2001 From: Chuck Date: Fri, 30 Jan 2026 10:44:57 -0500 Subject: [PATCH 1/8] fix(install): exclude rpi-rgb-led-matrix from permission normalization The permission normalization step in first_time_install.sh was running chmod 644 on all files, which stripped executable bits from compiled library files (librgbmatrix.so.1) after make build-python created them. This caused LED panels to not work after fresh installation until users manually ran chmod on the rpi-rgb-led-matrix-master directory. Fixes #224 Co-Authored-By: Claude Opus 4.5 --- first_time_install.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/first_time_install.sh b/first_time_install.sh index 31365de03..77eee3267 100644 --- a/first_time_install.sh +++ b/first_time_install.sh @@ -1212,19 +1212,21 @@ CURRENT_STEP="Normalize project file permissions" echo "Step 11.1: Normalizing project file and directory permissions..." echo "--------------------------------------------------------------" -# Normalize directory permissions (exclude VCS metadata and plugin directories) +# Normalize directory permissions (exclude VCS metadata, plugin directories, and compiled libraries) find "$PROJECT_ROOT_DIR" \ -path "$PROJECT_ROOT_DIR/plugins" -prune -o \ -path "$PROJECT_ROOT_DIR/plugin-repos" -prune -o \ -path "$PROJECT_ROOT_DIR/scripts/dev/plugins" -prune -o \ + -path "$PROJECT_ROOT_DIR/rpi-rgb-led-matrix-master" -prune -o \ -path "*/.git*" -prune -o \ -type d -exec chmod 755 {} \; 2>/dev/null || true -# Set default file permissions (exclude plugin directories) +# Set default file permissions (exclude plugin directories and compiled libraries) find "$PROJECT_ROOT_DIR" \ -path "$PROJECT_ROOT_DIR/plugins" -prune -o \ -path "$PROJECT_ROOT_DIR/plugin-repos" -prune -o \ -path "$PROJECT_ROOT_DIR/scripts/dev/plugins" -prune -o \ + -path "$PROJECT_ROOT_DIR/rpi-rgb-led-matrix-master" -prune -o \ -path "*/.git*" -prune -o \ -type f -exec chmod 644 {} \; 2>/dev/null || true From 629a5d7e1ce62ef8e4119dd311c4123885819490 Mon Sep 17 00:00:00 2001 From: Chuck Date: Fri, 30 Jan 2026 11:06:41 -0500 Subject: [PATCH 2/8] fix(install): resolve install script issues and speed up web UI startup Issues addressed: - Remove redundant python3-pillow from apt (Debian maps it to python3-pil) - Only upgrade pip, not setuptools/wheel (they conflict with apt versions) - Remove separate apt numpy install (pip handles it from requirements.txt) - Install web interface deps during first-time setup, not on every startup - Add marker file (.web_deps_installed) to skip redundant pip installs - Add user-friendly message about wait time after installation The web UI was taking 30-60+ seconds to start because it ran pip install on every startup. Now it only installs dependencies on first run. Fixes #208 Co-Authored-By: Claude Opus 4.5 --- first_time_install.sh | 52 ++++++++++++++---------- scripts/utils/start_web_conditionally.py | 24 ++++++++--- 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/first_time_install.sh b/first_time_install.sh index 77eee3267..e9d124c31 100644 --- a/first_time_install.sh +++ b/first_time_install.sh @@ -271,7 +271,7 @@ apt_update # Install required system packages echo "Installing Python packages and dependencies..." -apt_install python3-pip python3-venv python3-dev python3-pil python3-pil.imagetk python3-pillow build-essential python3-setuptools python3-wheel cython3 scons cmake ninja-build +apt_install python3-pip python3-venv python3-dev python3-pil python3-pil.imagetk build-essential python3-setuptools python3-wheel cython3 scons cmake ninja-build # Install additional system dependencies that might be needed echo "Installing additional system dependencies..." @@ -661,18 +661,7 @@ CURRENT_STEP="Install project Python dependencies" echo "Step 5: Installing Python project dependencies..." echo "-----------------------------------------------" -# Install numpy via apt first (pre-built binary, much faster than building from source) -echo "Installing numpy via apt (pre-built binary for faster installation)..." -if ! python3 -c "import numpy" >/dev/null 2>&1; then - apt_install python3-numpy - echo "✓ numpy installed via apt" -else - NUMPY_VERSION=$(python3 -c "import numpy; print(numpy.__version__)" 2>/dev/null || echo "unknown") - echo "✓ numpy already installed (version: $NUMPY_VERSION)" -fi -echo "" - -# Install main project Python dependencies +# Install main project Python dependencies (numpy will be installed via pip from requirements.txt) cd "$PROJECT_ROOT_DIR" if [ -f "$PROJECT_ROOT_DIR/requirements.txt" ]; then echo "Reading requirements from: $PROJECT_ROOT_DIR/requirements.txt" @@ -681,10 +670,10 @@ if [ -f "$PROJECT_ROOT_DIR/requirements.txt" ]; then echo "Checking pip version..." python3 -m pip --version - # Upgrade pip, setuptools, and wheel for better compatibility - echo "Upgrading pip, setuptools, and wheel..." - python3 -m pip install --break-system-packages --upgrade pip setuptools wheel || { - echo "⚠ Warning: Failed to upgrade pip/setuptools/wheel, continuing anyway..." + # Upgrade pip for better compatibility (setuptools/wheel are already installed via apt) + echo "Upgrading pip..." + python3 -m pip install --break-system-packages --upgrade pip || { + echo "⚠ Warning: Failed to upgrade pip, continuing anyway..." } # Count total packages for progress @@ -812,6 +801,20 @@ else fi echo "" +# Install web interface dependencies +echo "Installing web interface dependencies..." +if [ -f "$PROJECT_ROOT_DIR/web_interface/requirements.txt" ]; then + python3 -m pip install --break-system-packages -r "$PROJECT_ROOT_DIR/web_interface/requirements.txt" || { + echo "⚠ Warning: Some web interface dependencies failed to install" + } + echo "✓ Web interface dependencies installed" + # Create marker file to indicate dependencies are installed + touch "$PROJECT_ROOT_DIR/.web_deps_installed" +else + echo "⚠ web_interface/requirements.txt not found; skipping" +fi +echo "" + CURRENT_STEP="Build and install rpi-rgb-led-matrix" echo "Step 6: Building and installing rpi-rgb-led-matrix..." echo "-----------------------------------------------------" @@ -1543,26 +1546,31 @@ echo "==========================================" echo "Important Notes" echo "==========================================" echo "" -echo "1. For group changes to take effect:" +echo "1. PLEASE BE PATIENT after reboot!" +echo " - The web interface may take up to 5 minutes to start on first boot" +echo " - Services need time to initialize after installation" +echo " - Wait at least 2-3 minutes before checking service status" +echo "" +echo "2. For group changes to take effect:" echo " - Log out and log back in to your SSH session, OR" echo " - Run: newgrp systemd-journal" echo "" -echo "2. If you cannot access the web UI:" +echo "3. If you cannot access the web UI:" echo " - Check that the web service is running: sudo systemctl status ledmatrix-web" echo " - Verify firewall allows port 5000: sudo ufw status (if using UFW)" echo " - Check network connectivity: ping -c 3 8.8.8.8" echo " - If WiFi is not connected, connect to LEDMatrix-Setup AP network" echo "" -echo "3. SSH Access:" +echo "4. SSH Access:" echo " - SSH must be configured during initial Pi setup (via Raspberry Pi Imager or raspi-config)" echo " - This installation script does not configure SSH credentials" echo "" -echo "4. Useful Commands:" +echo "5. Useful Commands:" echo " - Check service status: sudo systemctl status ledmatrix.service" echo " - View logs: journalctl -u ledmatrix-web.service -f" echo " - Start/stop display: sudo systemctl start/stop ledmatrix.service" echo "" -echo "5. Configuration Files:" +echo "6. Configuration Files:" echo " - Main config: $PROJECT_ROOT_DIR/config/config.json" echo " - Secrets: $PROJECT_ROOT_DIR/config/config_secrets.json" echo "" diff --git a/scripts/utils/start_web_conditionally.py b/scripts/utils/start_web_conditionally.py index 0c79efa6d..b8f6e3513 100644 --- a/scripts/utils/start_web_conditionally.py +++ b/scripts/utils/start_web_conditionally.py @@ -8,6 +8,13 @@ PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) CONFIG_FILE = os.path.join(PROJECT_DIR, 'config', 'config.json') WEB_INTERFACE_SCRIPT = os.path.join(PROJECT_DIR, 'web_interface', 'start.py') +# Marker file created by first_time_install.sh to indicate dependencies are installed +DEPS_MARKER = os.path.join(PROJECT_DIR, '.web_deps_installed') + + +def dependencies_installed(): + """Check if dependencies were installed during first-time setup.""" + return os.path.exists(DEPS_MARKER) def install_dependencies(): """Install required dependencies using system Python.""" @@ -85,11 +92,18 @@ def main(): if is_enabled: print("Configuration 'web_display_autostart' is enabled. Starting web interface...") - - # Install dependencies - if not install_dependencies(): - print("Failed to install dependencies. Exiting.") - sys.exit(1) + + # Only install dependencies if not already done during first-time setup + if not dependencies_installed(): + print("First run detected: Installing dependencies...") + if not install_dependencies(): + print("Failed to install dependencies. Exiting.") + sys.exit(1) + # Create marker file after successful install + Path(DEPS_MARKER).touch() + print("Dependencies installed and marker file created.") + else: + print("Dependencies already installed (marker file found). Skipping installation.") try: # Replace the current process with web_interface.py using system Python From fabb084c3e167bb2d2dfd3f0e9a5efb15eafbfe4 Mon Sep 17 00:00:00 2001 From: Chuck Date: Fri, 30 Jan 2026 11:22:14 -0500 Subject: [PATCH 3/8] fix(install): prevent duplicate web dependency installation Step 7 was installing web dependencies again even though they were already installed in Step 5. Now Step 7 checks for the .web_deps_installed marker file and skips the installation if it already exists. Co-Authored-By: Claude Opus 4.5 --- first_time_install.sh | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/first_time_install.sh b/first_time_install.sh index e9d124c31..e65932f60 100644 --- a/first_time_install.sh +++ b/first_time_install.sh @@ -906,24 +906,31 @@ CURRENT_STEP="Install web interface dependencies" echo "Step 7: Installing web interface dependencies..." echo "------------------------------------------------" -# Install web interface dependencies -echo "Installing Python dependencies for web interface..." -cd "$PROJECT_ROOT_DIR" - -# Try to install dependencies using the smart installer if available -if [ -f "$PROJECT_ROOT_DIR/scripts/install_dependencies_apt.py" ]; then - echo "Using smart dependency installer..." - python3 "$PROJECT_ROOT_DIR/scripts/install_dependencies_apt.py" +# Check if web dependencies were already installed (marker created in Step 5) +if [ -f "$PROJECT_ROOT_DIR/.web_deps_installed" ]; then + echo "✓ Web interface dependencies already installed (marker file found)" else - echo "Using pip to install dependencies..." - if [ -f "$PROJECT_ROOT_DIR/requirements_web_v2.txt" ]; then - python3 -m pip install --break-system-packages -r requirements_web_v2.txt + # Install web interface dependencies + echo "Installing Python dependencies for web interface..." + cd "$PROJECT_ROOT_DIR" + + # Try to install dependencies using the smart installer if available + if [ -f "$PROJECT_ROOT_DIR/scripts/install_dependencies_apt.py" ]; then + echo "Using smart dependency installer..." + python3 "$PROJECT_ROOT_DIR/scripts/install_dependencies_apt.py" else - echo "⚠ requirements_web_v2.txt not found; skipping web dependency install" + echo "Using pip to install dependencies..." + if [ -f "$PROJECT_ROOT_DIR/requirements_web_v2.txt" ]; then + python3 -m pip install --break-system-packages -r requirements_web_v2.txt + else + echo "⚠ requirements_web_v2.txt not found; skipping web dependency install" + fi fi -fi -echo "✓ Web interface dependencies installed" + # Create marker file to indicate dependencies are installed + touch "$PROJECT_ROOT_DIR/.web_deps_installed" + echo "✓ Web interface dependencies installed" +fi echo "" CURRENT_STEP="Install web interface service" From 0f3edcca4e707df59112d0214c77ffedc998c6f9 Mon Sep 17 00:00:00 2001 From: Chuck Date: Fri, 30 Jan 2026 11:26:37 -0500 Subject: [PATCH 4/8] fix(install): only create web deps marker on successful install The .web_deps_installed marker file should only be created when pip install actually succeeds. Previously it was created regardless of the pip exit status, which could cause subsequent runs to skip installing missing dependencies. Co-Authored-By: Claude Opus 4.5 --- first_time_install.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/first_time_install.sh b/first_time_install.sh index e65932f60..0146279ae 100644 --- a/first_time_install.sh +++ b/first_time_install.sh @@ -804,12 +804,14 @@ echo "" # Install web interface dependencies echo "Installing web interface dependencies..." if [ -f "$PROJECT_ROOT_DIR/web_interface/requirements.txt" ]; then - python3 -m pip install --break-system-packages -r "$PROJECT_ROOT_DIR/web_interface/requirements.txt" || { + if python3 -m pip install --break-system-packages -r "$PROJECT_ROOT_DIR/web_interface/requirements.txt"; then + echo "✓ Web interface dependencies installed" + # Create marker file to indicate dependencies are installed + touch "$PROJECT_ROOT_DIR/.web_deps_installed" + else echo "⚠ Warning: Some web interface dependencies failed to install" - } - echo "✓ Web interface dependencies installed" - # Create marker file to indicate dependencies are installed - touch "$PROJECT_ROOT_DIR/.web_deps_installed" + echo " The web interface may not work correctly until dependencies are installed" + fi else echo "⚠ web_interface/requirements.txt not found; skipping" fi From d090f5ed033f17405796cd6503e6af3d9959c62d Mon Sep 17 00:00:00 2001 From: Chuck Date: Fri, 30 Jan 2026 12:17:32 -0500 Subject: [PATCH 5/8] fix(install): create config files before starting services The services were being started before config files existed, causing the web service to fail with "config.json not found". Reordered steps so config files are created (Step 4) before services are installed and started (Step 4.1). Co-Authored-By: Claude Opus 4.5 --- first_time_install.sh | 72 +++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/first_time_install.sh b/first_time_install.sh index 0146279ae..8877ffc55 100644 --- a/first_time_install.sh +++ b/first_time_install.sh @@ -511,43 +511,9 @@ find "$PLUGIN_REPOS_DIR" -type f -exec chmod 664 {} \; echo "✓ Plugin-repos directory permissions fixed" echo "" -CURRENT_STEP="Install main LED Matrix service" -echo "Step 4: Installing main LED Matrix service..." -echo "---------------------------------------------" - -# Run the main service installation (idempotent) -# Note: install_service.sh always overwrites the service file, so it will update paths automatically -if [ -f "$PROJECT_ROOT_DIR/scripts/install/install_service.sh" ]; then - echo "Running main service installation/update..." - bash "$PROJECT_ROOT_DIR/scripts/install/install_service.sh" - echo "✓ Main LED Matrix service installed/updated" -else - echo "✗ Main service installation script not found at $PROJECT_ROOT_DIR/scripts/install/install_service.sh" - echo "Please ensure you are running this script from the project root: $PROJECT_ROOT_DIR" - exit 1 -fi - -# Configure Python capabilities for hardware timing -echo "Configuring Python capabilities for hardware timing..." -if [ -f "/usr/bin/python3.13" ]; then - sudo setcap 'cap_sys_nice=eip' /usr/bin/python3.13 2>/dev/null || echo "⚠ Could not set cap_sys_nice on python3.13 (may need manual setup)" - echo "✓ Python3.13 capabilities configured" -elif [ -f "/usr/bin/python3" ]; then - PYTHON_VER=$(python3 --version 2>&1 | grep -oP '(?<=Python )\d\.\d+' || echo "unknown") - if command -v setcap >/dev/null 2>&1; then - sudo setcap 'cap_sys_nice=eip' /usr/bin/python3 2>/dev/null || echo "⚠ Could not set cap_sys_nice on python3" - echo "✓ Python3 capabilities configured (version: $PYTHON_VER)" - else - echo "⚠ setcap not found, skipping capability configuration" - fi -else - echo "⚠ Python3 not found, skipping capability configuration" -fi -echo "" - CURRENT_STEP="Ensure configuration files exist" -echo "Step 4.1: Ensuring configuration files exist..." -echo "------------------------------------------------" +echo "Step 4: Ensuring configuration files exist..." +echo "----------------------------------------------" # Ensure config directory exists mkdir -p "$PROJECT_ROOT_DIR/config" @@ -657,6 +623,40 @@ else fi echo "" +CURRENT_STEP="Install main LED Matrix service" +echo "Step 4.1: Installing main LED Matrix service..." +echo "------------------------------------------------" + +# Run the main service installation (idempotent) +# Note: install_service.sh always overwrites the service file, so it will update paths automatically +if [ -f "$PROJECT_ROOT_DIR/scripts/install/install_service.sh" ]; then + echo "Running main service installation/update..." + bash "$PROJECT_ROOT_DIR/scripts/install/install_service.sh" + echo "✓ Main LED Matrix service installed/updated" +else + echo "✗ Main service installation script not found at $PROJECT_ROOT_DIR/scripts/install/install_service.sh" + echo "Please ensure you are running this script from the project root: $PROJECT_ROOT_DIR" + exit 1 +fi + +# Configure Python capabilities for hardware timing +echo "Configuring Python capabilities for hardware timing..." +if [ -f "/usr/bin/python3.13" ]; then + sudo setcap 'cap_sys_nice=eip' /usr/bin/python3.13 2>/dev/null || echo "⚠ Could not set cap_sys_nice on python3.13 (may need manual setup)" + echo "✓ Python3.13 capabilities configured" +elif [ -f "/usr/bin/python3" ]; then + PYTHON_VER=$(python3 --version 2>&1 | grep -oP '(?<=Python )\d\.\d+' || echo "unknown") + if command -v setcap >/dev/null 2>&1; then + sudo setcap 'cap_sys_nice=eip' /usr/bin/python3 2>/dev/null || echo "⚠ Could not set cap_sys_nice on python3" + echo "✓ Python3 capabilities configured (version: $PYTHON_VER)" + else + echo "⚠ setcap not found, skipping capability configuration" + fi +else + echo "⚠ Python3 not found, skipping capability configuration" +fi +echo "" + CURRENT_STEP="Install project Python dependencies" echo "Step 5: Installing Python project dependencies..." echo "-----------------------------------------------" From b4b2d99bcd67c3c481c395dd4ba1d2654a2b2f5e Mon Sep 17 00:00:00 2001 From: Chuck Date: Fri, 30 Jan 2026 12:18:18 -0500 Subject: [PATCH 6/8] fix(install): remove pip upgrade step (apt version is sufficient) The apt-installed pip cannot be upgraded because it doesn't have a RECORD file. Since the apt version (25.1.1) is already recent enough, we can skip the upgrade step entirely. Co-Authored-By: Claude Opus 4.5 --- first_time_install.sh | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/first_time_install.sh b/first_time_install.sh index 8877ffc55..632922d0e 100644 --- a/first_time_install.sh +++ b/first_time_install.sh @@ -666,16 +666,10 @@ cd "$PROJECT_ROOT_DIR" if [ -f "$PROJECT_ROOT_DIR/requirements.txt" ]; then echo "Reading requirements from: $PROJECT_ROOT_DIR/requirements.txt" - # Check pip version and upgrade if needed + # Check pip version (apt-installed pip is sufficient, no upgrade needed) echo "Checking pip version..." python3 -m pip --version - - # Upgrade pip for better compatibility (setuptools/wheel are already installed via apt) - echo "Upgrading pip..." - python3 -m pip install --break-system-packages --upgrade pip || { - echo "⚠ Warning: Failed to upgrade pip, continuing anyway..." - } - + # Count total packages for progress TOTAL_PACKAGES=$(grep -v '^#' "$PROJECT_ROOT_DIR/requirements.txt" | grep -v '^$' | wc -l) echo "Found $TOTAL_PACKAGES package(s) to install" From 644deaf57195ce075272eacfebb901b2e32da89d Mon Sep 17 00:00:00 2001 From: Chuck Date: Fri, 30 Jan 2026 12:33:03 -0500 Subject: [PATCH 7/8] fix(install): reorder script to install services after dependencies Moved main LED Matrix service installation (Step 7.5) to after all Python dependencies are installed (Steps 5-7). Previously services were being started before pip packages and rgbmatrix were ready, causing startup failures. New order: - Step 5: Python pip dependencies - Step 6: rpi-rgb-led-matrix build - Step 7: Web interface dependencies - Step 7.5: Main LED Matrix service (moved here) - Step 8: Web interface service Co-Authored-By: Claude Opus 4.5 --- first_time_install.sh | 69 ++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/first_time_install.sh b/first_time_install.sh index 632922d0e..0bb4c8fec 100644 --- a/first_time_install.sh +++ b/first_time_install.sh @@ -623,40 +623,6 @@ else fi echo "" -CURRENT_STEP="Install main LED Matrix service" -echo "Step 4.1: Installing main LED Matrix service..." -echo "------------------------------------------------" - -# Run the main service installation (idempotent) -# Note: install_service.sh always overwrites the service file, so it will update paths automatically -if [ -f "$PROJECT_ROOT_DIR/scripts/install/install_service.sh" ]; then - echo "Running main service installation/update..." - bash "$PROJECT_ROOT_DIR/scripts/install/install_service.sh" - echo "✓ Main LED Matrix service installed/updated" -else - echo "✗ Main service installation script not found at $PROJECT_ROOT_DIR/scripts/install/install_service.sh" - echo "Please ensure you are running this script from the project root: $PROJECT_ROOT_DIR" - exit 1 -fi - -# Configure Python capabilities for hardware timing -echo "Configuring Python capabilities for hardware timing..." -if [ -f "/usr/bin/python3.13" ]; then - sudo setcap 'cap_sys_nice=eip' /usr/bin/python3.13 2>/dev/null || echo "⚠ Could not set cap_sys_nice on python3.13 (may need manual setup)" - echo "✓ Python3.13 capabilities configured" -elif [ -f "/usr/bin/python3" ]; then - PYTHON_VER=$(python3 --version 2>&1 | grep -oP '(?<=Python )\d\.\d+' || echo "unknown") - if command -v setcap >/dev/null 2>&1; then - sudo setcap 'cap_sys_nice=eip' /usr/bin/python3 2>/dev/null || echo "⚠ Could not set cap_sys_nice on python3" - echo "✓ Python3 capabilities configured (version: $PYTHON_VER)" - else - echo "⚠ setcap not found, skipping capability configuration" - fi -else - echo "⚠ Python3 not found, skipping capability configuration" -fi -echo "" - CURRENT_STEP="Install project Python dependencies" echo "Step 5: Installing Python project dependencies..." echo "-----------------------------------------------" @@ -929,6 +895,41 @@ else fi echo "" +CURRENT_STEP="Install main LED Matrix service" +echo "Step 7.5: Installing main LED Matrix service..." +echo "------------------------------------------------" + +# Run the main service installation (idempotent) +# Note: install_service.sh always overwrites the service file, so it will update paths automatically +# This step runs AFTER all Python dependencies are installed (Steps 5-7) +if [ -f "$PROJECT_ROOT_DIR/scripts/install/install_service.sh" ]; then + echo "Running main service installation/update..." + bash "$PROJECT_ROOT_DIR/scripts/install/install_service.sh" + echo "✓ Main LED Matrix service installed/updated" +else + echo "✗ Main service installation script not found at $PROJECT_ROOT_DIR/scripts/install/install_service.sh" + echo "Please ensure you are running this script from the project root: $PROJECT_ROOT_DIR" + exit 1 +fi + +# Configure Python capabilities for hardware timing +echo "Configuring Python capabilities for hardware timing..." +if [ -f "/usr/bin/python3.13" ]; then + sudo setcap 'cap_sys_nice=eip' /usr/bin/python3.13 2>/dev/null || echo "⚠ Could not set cap_sys_nice on python3.13 (may need manual setup)" + echo "✓ Python3.13 capabilities configured" +elif [ -f "/usr/bin/python3" ]; then + PYTHON_VER=$(python3 --version 2>&1 | grep -oP '(?<=Python )\d\.\d+' || echo "unknown") + if command -v setcap >/dev/null 2>&1; then + sudo setcap 'cap_sys_nice=eip' /usr/bin/python3 2>/dev/null || echo "⚠ Could not set cap_sys_nice on python3" + echo "✓ Python3 capabilities configured (version: $PYTHON_VER)" + else + echo "⚠ setcap not found, skipping capability configuration" + fi +else + echo "⚠ Python3 not found, skipping capability configuration" +fi +echo "" + CURRENT_STEP="Install web interface service" echo "Step 8: Installing web interface service..." echo "-------------------------------------------" From 7952c113098bd89a06d57541f0027e01b9216883 Mon Sep 17 00:00:00 2001 From: Chuck Date: Fri, 30 Jan 2026 12:45:59 -0500 Subject: [PATCH 8/8] fix(install): update step list and fix setcap symlink handling - Updated step list header to match actual step order after reordering (Step 4 is now "Ensure configuration files exist", added Step 7.5 for main service, added Step 8.1 for systemd permissions) - Fixed Python capabilities configuration: - Check if setcap command exists before attempting to use it - Resolve symlinks with readlink -f to get the real binary path - Only print success message when setcap actually succeeds - Print clear warning with helpful info when setcap fails Co-Authored-By: Claude Opus 4.5 --- first_time_install.sh | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/first_time_install.sh b/first_time_install.sh index 0bb4c8fec..0f9024326 100644 --- a/first_time_install.sh +++ b/first_time_install.sh @@ -220,11 +220,13 @@ echo "1. Install system dependencies" echo "2. Fix cache permissions" echo "3. Fix assets directory permissions" echo "3.1. Fix plugin directory permissions" -echo "4. Install main LED Matrix service" +echo "4. Ensure configuration files exist" echo "5. Install Python project dependencies (requirements.txt)" echo "6. Build and install rpi-rgb-led-matrix and test import" echo "7. Install web interface dependencies" +echo "7.5. Install main LED Matrix service" echo "8. Install web interface service" +echo "8.1. Harden systemd unit file permissions" echo "8.5. Install WiFi monitor service" echo "9. Configure web interface permissions" echo "10. Configure passwordless sudo access" @@ -914,19 +916,35 @@ fi # Configure Python capabilities for hardware timing echo "Configuring Python capabilities for hardware timing..." -if [ -f "/usr/bin/python3.13" ]; then - sudo setcap 'cap_sys_nice=eip' /usr/bin/python3.13 2>/dev/null || echo "⚠ Could not set cap_sys_nice on python3.13 (may need manual setup)" - echo "✓ Python3.13 capabilities configured" -elif [ -f "/usr/bin/python3" ]; then - PYTHON_VER=$(python3 --version 2>&1 | grep -oP '(?<=Python )\d\.\d+' || echo "unknown") - if command -v setcap >/dev/null 2>&1; then - sudo setcap 'cap_sys_nice=eip' /usr/bin/python3 2>/dev/null || echo "⚠ Could not set cap_sys_nice on python3" - echo "✓ Python3 capabilities configured (version: $PYTHON_VER)" + +# Check if setcap is available first +if ! command -v setcap >/dev/null 2>&1; then + echo "⚠ setcap not found, skipping capability configuration" + echo " Install libcap2-bin if you need hardware timing capabilities" +else + # Find the Python binary and resolve symlinks to get the real binary + PYTHON_BIN="" + PYTHON_VER="" + if [ -f "/usr/bin/python3.13" ]; then + PYTHON_BIN=$(readlink -f /usr/bin/python3.13) + PYTHON_VER="3.13" + elif [ -f "/usr/bin/python3" ]; then + PYTHON_BIN=$(readlink -f /usr/bin/python3) + PYTHON_VER=$(python3 --version 2>&1 | grep -oP '(?<=Python )\d+\.\d+' || echo "unknown") + fi + + if [ -n "$PYTHON_BIN" ] && [ -f "$PYTHON_BIN" ]; then + echo "Setting cap_sys_nice on $PYTHON_BIN (Python $PYTHON_VER)..." + if sudo setcap 'cap_sys_nice=eip' "$PYTHON_BIN" 2>/dev/null; then + echo "✓ Python $PYTHON_VER capabilities configured ($PYTHON_BIN)" + else + echo "⚠ Could not set cap_sys_nice on $PYTHON_BIN" + echo " This may require manual setup or running as root" + echo " The LED display may have timing issues without this capability" + fi else - echo "⚠ setcap not found, skipping capability configuration" + echo "⚠ Python3 not found, skipping capability configuration" fi -else - echo "⚠ Python3 not found, skipping capability configuration" fi echo ""