diff --git a/debian/README.md b/debian/README.md index fe7a12d..86bcd4d 100644 --- a/debian/README.md +++ b/debian/README.md @@ -287,16 +287,51 @@ Common issues: - sensors.json is empty - Bluetooth adapter not available -### Bluetooth Capability Not Set +### Bluetooth Permission Error: "Operation not permitted" + +If the service fails with `PermissionError: [Errno 1] Operation not permitted`: ```bash -# Manually set capability +# Check current capabilities +getcap $(readlink -f /opt/sensorpajen/venv/bin/python3) +# Should show: cap_net_admin,cap_net_raw+eip +``` + +**Solution 1: Re-apply file capabilities** (Quick fix) + +```bash +# Set capabilities on Python executable sudo setcap cap_net_raw,cap_net_admin+eip $(readlink -f /opt/sensorpajen/venv/bin/python3) # Verify getcap $(readlink -f /opt/sensorpajen/venv/bin/python3) + +# Restart service +sudo systemctl restart sensorpajen ``` +**Solution 2: Add user to bluetooth group** + +```bash +sudo usermod -aG bluetooth sensorpajen +sudo systemctl restart sensorpajen +``` + +**Solution 3: Verify systemd capabilities** + +The service file uses `AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN` as a fallback. Verify it's configured: + +```bash +sudo systemctl cat sensorpajen | grep -A2 Capabilities +``` + +**Why this happens**: File capabilities can be lost when: +- Python is upgraded/reinstalled +- Filesystem is mounted with `nosuid` +- The venv is recreated + +The systemd service now uses both `AmbientCapabilities` (modern approach) and file capabilities (setcap) for maximum compatibility. + ## Development Workflow ### Making Changes diff --git a/debian/postinst b/debian/postinst index 175e399..93d3444 100755 --- a/debian/postinst +++ b/debian/postinst @@ -8,6 +8,12 @@ case "$1" in useradd --system --no-create-home --shell /usr/sbin/nologin sensorpajen echo "Created system user: sensorpajen" fi + + # Add sensorpajen user to bluetooth group if it exists (for BLE access) + if getent group bluetooth > /dev/null; then + usermod -aG bluetooth sensorpajen || true + echo "Added sensorpajen user to bluetooth group" + fi # Create config directory with proper permissions mkdir -p /etc/sensorpajen @@ -77,14 +83,20 @@ case "$1" in chown -R sensorpajen:sensorpajen /opt/sensorpajen # Set Bluetooth capabilities on Python executable (after ownership change) + # Note: The systemd service also uses AmbientCapabilities as a fallback PYTHON_PATH=$(readlink -f /opt/sensorpajen/venv/bin/python3) if command -v setcap >/dev/null 2>&1; then - setcap cap_net_raw,cap_net_admin+eip "$PYTHON_PATH" || { - echo "Warning: setcap failed. You may need to run Bluetooth operations as root." - echo "Try: sudo setcap cap_net_raw,cap_net_admin+eip $PYTHON_PATH" - } + if setcap cap_net_raw,cap_net_admin+eip "$PYTHON_PATH" 2>/dev/null; then + echo "Bluetooth capabilities set on $PYTHON_PATH" + getcap "$PYTHON_PATH" || true + else + echo "Warning: setcap failed. Relying on systemd AmbientCapabilities instead." + echo "If Bluetooth access fails, manually run:" + echo " sudo setcap cap_net_raw,cap_net_admin+eip $PYTHON_PATH" + fi else echo "Warning: setcap not found (install libcap2-bin package)" + echo "Relying on systemd AmbientCapabilities for Bluetooth access" fi # v2 installed a unit into /etc/systemd/system/, which overrides packaged units diff --git a/debian/sensorpajen.service b/debian/sensorpajen.service index afcebf7..dc3048f 100644 --- a/debian/sensorpajen.service +++ b/debian/sensorpajen.service @@ -14,7 +14,8 @@ ExecStart=/opt/sensorpajen/venv/bin/python -m sensorpajen.main Restart=always RestartSec=10 -# Bluetooth capabilities require this to be false +# Bluetooth capabilities +AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN NoNewPrivileges=false # Logging diff --git a/systemd/sensorpajen.service b/systemd/sensorpajen.service index 8fae6db..601f750 100644 --- a/systemd/sensorpajen.service +++ b/systemd/sensorpajen.service @@ -12,21 +12,9 @@ ExecStart=%h/sensorpajen/.venv/bin/python -m sensorpajen.main Restart=always RestartSec=10 -# Bluetooth capabilities (alternative to setcap) -# Note: This requires systemd to be run with proper permissions -# If this doesn't work, use setcap on the Python binary instead -#AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN - -# Logging -StandardOutput=journal -StandardError=journal -SyslogIdentifier=sensorpajen - -# Security -# Note: NoNewPrivileges=true can prevent file capabilities from working -# We need capabilities for Bluetooth access, so we can't use it -#NoNewPrivileges=true -PrivateTmp=true +# Bluetooth capabilities +AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN +NoNewPrivileges=false [Install] WantedBy=default.target