docs(deps): describe how plugin dependencies are really installed

The guides said the web service runs as root, that installs pick --user
from os.geteuid(), and quoted a warning and a
PluginManager._install_plugin_dependencies() method that don't exist. The
web unit runs as the installing user; store installs go through
install_requirements_file() and sudo safe_pip_install.sh (root), with a
user-level fallback that says so, and load-time installs run in the
display service's own (root) interpreter.

Manual paths now use the configured plugins directory (plugin-repos/ by
default) instead of plugins/, which store installs no longer use, and
install_plugin_dependencies.sh is described as scanning that directory.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-09-17 08:58:03 -04:00
co-authored by Claude Opus 5
parent df3524305f
commit c3465c35f5
2 changed files with 187 additions and 266 deletions
+77 -82
View File
@@ -1,6 +1,7 @@
# Plugin Dependency Installation Troubleshooting
This guide helps resolve issues with automatic plugin dependency installation in the LEDMatrix system.
This guide helps resolve problems installing a plugin's Python packages. For
how installation works, see the [Plugin Dependency Guide](PLUGIN_DEPENDENCY_GUIDE.md).
## Common Error Symptoms
@@ -10,109 +11,118 @@ ERROR: Could not install packages due to an OSError: [Errno 13] Permission denie
WARNING: The directory '/root/.cache/pip' or its parent directory is not owned or is not writable
```
### Context Mismatch
### Installed for the wrong user
The pip output shown after a web-UI install starts with:
```
WARNING: Installing plugin dependencies for current user (not root).
These will NOT be accessible to the systemd service.
[Root install unavailable (...); installed for the current process's user only.
Packages may not be visible to ledmatrix.service if it runs as a different
user — run scripts/install/configure_web_sudo.sh to fix this.]
```
### Plugin fails to load with `ModuleNotFoundError`
The display service can't see a package the plugin needs.
## Root Cause
Plugin dependencies must be installed in a context accessible to the LEDMatrix systemd service, which runs as root. Permission errors typically occur when:
Plugin packages must be importable by `ledmatrix.service`, which runs as
root. The web interface (`ledmatrix-web.service`) runs as the user who
installed LEDMatrix, so it installs through a sudo helper
(`scripts/fix_perms/safe_pip_install.sh`). Problems usually come from:
1. The pip cache directory has incorrect permissions
2. The process tries to install to user directories without proper permissions
3. Environment variables (like HOME) are not set correctly for the service context
1. The sudoers rule for that helper missing, so the web UI installed the
packages for its own user only
2. Running `python3 run.py` by hand as a normal user, which installs missing
packages into `~/.local/`
3. pip's cache directory not being writable for root
## Solutions
### Solution 1: Use the Manual Installation Script (Recommended)
We provide a helper script that handles dependency installation correctly:
### Solution 1: Restore the sudo rule, then reinstall
```bash
# Run as root to install system-wide (for production)
sudo /home/ledpi/LEDMatrix/scripts/install_plugin_dependencies.sh
cd ~/LEDMatrix
./scripts/install/configure_web_sudo.sh # as the web user, not with sudo
```
# After installation, restart the service
Then reinstall the plugin from the **Plugin Manager** tab, or click
**Reinstall Plugin Deps** on the **Tools** tab.
### Solution 2: Install every plugin's dependencies from the terminal
```bash
sudo ~/LEDMatrix/scripts/install_plugin_dependencies.sh
sudo systemctl restart ledmatrix
```
This script:
- Detects all plugins with requirements.txt files
- Installs dependencies with correct permissions
- Uses `--no-cache-dir` to avoid cache permission issues
- Provides detailed logging for troubleshooting
The script finds each `requirements.txt` in the plugins directory set by
`plugin_system.plugins_directory` in `config/config.json` (default
`plugin-repos/`), installs with `--no-cache-dir`, and reports what it found.
### Solution 2: Manual Installation per Plugin
If you need to install dependencies for a specific plugin:
### Solution 3: Install one plugin's dependencies
```bash
# Navigate to the plugin directory
cd /home/ledpi/LEDMatrix/plugins/PLUGIN-NAME
# Your configured plugins directory; plugin-repos/ by default
cd ~/LEDMatrix/plugin-repos/PLUGIN-NAME
# Install as root (system-wide)
sudo pip3 install --break-system-packages --no-cache-dir -r requirements.txt
sudo python3 -m pip install --break-system-packages --no-cache-dir -r requirements.txt
# Restart the service
sudo systemctl restart ledmatrix
```
### Solution 3: Fix Cache Directory Permissions
### Solution 4: Let the display service install them
If you specifically have cache permission issues:
When a plugin loads, the display service installs any missing requirements
itself, as root:
```bash
sudo systemctl restart ledmatrix
sudo journalctl -u ledmatrix -f # watch for "Installing dependencies for plugin ..."
```
### Solution 5: Fix pip cache permissions
```bash
# Option A: Skip the cache (recommended)
sudo pip3 install --no-cache-dir --break-system-packages -r requirements.txt
sudo python3 -m pip install --no-cache-dir --break-system-packages -r requirements.txt
# Option B: Fix cache permissions (if needed)
# Option B: Fix cache permissions
sudo mkdir -p /root/.cache/pip
sudo chown -R root:root /root/.cache
sudo chmod -R 755 /root/.cache
```
### Solution 4: Install via Web Interface
The web interface handles dependency installation correctly in the service context:
1. Access the web interface (`http://ledpi:5000` or `http://your-pi-ip:5000`)
2. Open the **Plugin Manager** tab (use the **Plugin Store** section to
find the plugin, or **Install from GitHub**)
3. Install the plugin through the web UI
4. The system automatically handles dependency installation in the
service context (which has the right permissions)
## Prevention
### For Plugin Developers
When creating plugins with dependencies:
1. **Keep requirements minimal**: Only include essential packages
2. **Test installation**: Verify your requirements.txt works with:
2. **Test installation** the way the Pi does it:
```bash
sudo pip3 install --break-system-packages --no-cache-dir -r requirements.txt
sudo python3 -m pip install --break-system-packages --no-cache-dir -r requirements.txt
```
3. **Document dependencies**: Note any system packages needed (via apt)
### For Users
1. **Use web interface**: Install plugins via the web UI when possible
2. **Install as root**: When using SSH/terminal, use sudo for plugin installations
3. **Restart service**: After manual installations, restart the ledmatrix service
1. **Use the web interface** to install plugins
2. **Use sudo** for installs from SSH/terminal
3. **Restart the service** after manual installations
## Technical Details
### How Dependency Installation Works
### Where installs happen
The `PluginManager._install_plugin_dependencies()` method:
1. Detects if running as root using `os.geteuid() == 0`
2. If root: Uses system-wide installation with `--break-system-packages --no-cache-dir`
3. If not root: Uses user installation with `--user --break-system-packages --no-cache-dir`
4. The `--no-cache-dir` flag prevents cache-related permission issues
- **Web UI install/update:** `PluginStoreManager._install_dependencies()`
→ `install_requirements_file()` in `src/common/permission_utils.py`, which
runs `sudo -n bash scripts/fix_perms/safe_pip_install.sh <requirements.txt>`.
The helper only accepts the project's `requirements.txt` or one under
`plugin-repos/` or `plugins/`, and runs
`pip install --break-system-packages --ignore-installed` as root. If sudo
refuses, it falls back to a pip install as the web user and says so.
- **Plugin load:** `PluginLoader.install_dependencies()` in
`src/plugin_system/plugin_loader.py` skips satisfied requirements and
otherwise runs `pip install --break-system-packages` with the loading
process's interpreter — root in `ledmatrix.service`.
### Why `--break-system-packages`?
@@ -120,26 +130,20 @@ Debian 12+ (Bookworm) and Raspberry Pi OS based on it implement PEP 668, which p
### Service Context
The ledmatrix.service runs as:
- **User**: root
- **WorkingDirectory**: /home/ledpi/LEDMatrix
- **Python**: /usr/bin/python3
- `ledmatrix.service` runs as **root** with `/usr/bin/python3`
- `ledmatrix-web.service` runs as **the installing user**
Dependencies must be installed in root's Python environment or system-wide to be accessible.
Dependencies must be installed system-wide (as root) to be visible to the
display service.
## Checking Installation
Verify dependencies are installed correctly:
```bash
# Check as root (how the service sees it)
sudo python3 -c "import package_name"
sudo python3 -c "import package_name; print(package_name.__file__)"
# List installed packages
pip3 list
# Check specific package
pip3 show package_name
# A path under /home/<user>/.local/ means a user-only install
python3 -m pip show -f package_name
```
## Getting Help
@@ -151,19 +155,11 @@ If you continue to experience issues:
sudo journalctl -u ledmatrix -f
```
2. Check pip logs (created by manual script):
2. Verify the plugin manifest and requirements (default plugins directory
shown):
```bash
cat /tmp/pip_install_*.log
```
3. Verify plugin manifest is correct:
```bash
cat /home/ledpi/LEDMatrix/plugins/PLUGIN-NAME/manifest.json
```
4. Check plugin requirements:
```bash
cat /home/ledpi/LEDMatrix/plugins/PLUGIN-NAME/requirements.txt
cat ~/LEDMatrix/plugin-repos/PLUGIN-NAME/manifest.json
cat ~/LEDMatrix/plugin-repos/PLUGIN-NAME/requirements.txt
```
## Related Documentation
@@ -171,4 +167,3 @@ If you continue to experience issues:
- [Plugin Dependency Guide](PLUGIN_DEPENDENCY_GUIDE.md)
- [Plugin Development Guide](PLUGIN_DEVELOPMENT_GUIDE.md)
- [Troubleshooting](TROUBLESHOOTING.md)