Phase 6 Complete: Systemd Service Creation
- Created systemd/sensorpajen.service user service unit - Uses %h for portability across systems - Loads environment from EnvironmentFile - Auto-restart with bluetooth capabilities - Comprehensive security settings - Created systemd/README.md - Installation instructions - Service management commands - Troubleshooting guide - Log viewing examples - Updated ROADMAP.md to mark Phase 6 complete
This commit is contained in:
91
ROADMAP.md
91
ROADMAP.md
@@ -161,9 +161,11 @@ Using relative paths for portability across systems:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Phase 3: Configuration Migration ✓ TODO
|
### Phase 3: Configuration Migration ✅ DONE (2025-12-27)
|
||||||
**Goal**: Replace .ini file with JSON and environment variables
|
**Goal**: Replace .ini file with JSON and environment variables
|
||||||
|
|
||||||
|
**Notes**: Templates created in Phase 1, successfully tested on Raspberry Pi
|
||||||
|
|
||||||
#### Tasks:
|
#### Tasks:
|
||||||
1. Create sensor mapping converter script
|
1. Create sensor mapping converter script
|
||||||
- Read sensorer.ini
|
- Read sensorer.ini
|
||||||
@@ -234,9 +236,11 @@ config/sensorpajen.env
|
|||||||
debian/files
|
debian/files
|
||||||
debian/*.log
|
debian/*.log
|
||||||
debian/*.substvars
|
debian/*.substvars
|
||||||
### Phase 4: Virtual Environment & Dependencies ✓ TODO
|
### Phase 4: Virtual Environment & Dependencies ✅ DONE (2025-12-27)
|
||||||
**Goal**: Set up isolated Python environment
|
**Goal**: Set up isolated Python environment
|
||||||
|
|
||||||
|
**Notes**: Tested on Raspberry Pi, paho-mqtt v2.x compatibility fixed
|
||||||
|
|
||||||
#### Tasks:
|
#### Tasks:
|
||||||
1. Create virtual environment:
|
1. Create virtual environment:
|
||||||
```bash
|
```bash
|
||||||
@@ -262,75 +266,34 @@ config/sensorpajen.env
|
|||||||
|
|
||||||
4. Document virtual environment usage in README
|
4. Document virtual environment usage in README
|
||||||
|
|
||||||
---
|
---✅ DONE (2025-12-27)
|
||||||
|
|
||||||
### Phase 5: Bluetooth Permissions ✓ TODO
|
|
||||||
**Goal**: Allow non-root user to access Bluetooth
|
**Goal**: Allow non-root user to access Bluetooth
|
||||||
|
|
||||||
|
**Notes**: Tested on Raspberry Pi with setcap on actual Python binary
|
||||||
|
### Phase 5: Bluetooth Permissions ✅ DONE (2025-12-27)
|
||||||
|
**Goal**: Allow non-root user to access Bluetooth
|
||||||
|
|
||||||
|
**Notes**: Tested on Raspberry Pi with setcap on actual Python binary
|
||||||
|
|
||||||
#### Tasks:
|
#### Tasks:
|
||||||
1. Add user to bluetooth group:
|
- ✅ Bluetooth capabilities set with setcap
|
||||||
```bash
|
- ✅ Documented in SETUP_ON_PI.md with correct readlink -f usage
|
||||||
sudo usermod -a -G bluetooth fredrik
|
- ✅ Tested successfully on Raspberry Pi
|
||||||
```
|
|
||||||
|
|
||||||
2. Set capabilities on Python interpreter (if needed):
|
---
|
||||||
```bash
|
|
||||||
sudo setcap 'cap_net_raw,cap_net_admin+eip' .venv/bin/python3
|
|
||||||
```%h/sensorpajen
|
|
||||||
EnvironmentFile=%h/sensorpajen/config/sensorpajen.env
|
|
||||||
ExecStart=%h/sensorpajen/.venv/bin/python -m sensorpajen.main
|
|
||||||
Restart=always
|
|
||||||
RestartSec=10
|
|
||||||
|
|
||||||
# Bluetooth capabilities
|
|
||||||
AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN
|
|
||||||
|
|
||||||
# Logging
|
|
||||||
StandardOutput=journal
|
|
||||||
StandardError=journal
|
|
||||||
SyslogIdentifier=sensorpajen
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=default.target
|
|
||||||
```
|
|
||||||
|
|
||||||
Note: `%h` expands to the user's home directorycription=Sensorpajen - Bluetooth Temperature Sensor Monitor
|
|
||||||
After=network.target bluetooth.target
|
|
||||||
Wants=bluetooth.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
WorkingDirectory=/home/fredrik/dev/sensorpajen
|
|
||||||
EnvironmentFile=/home/fredrik/.config/sensorpajen/sensorpajen.env
|
|
||||||
ExecStart=/home/fredrik/dev/sensorpajen/.venv/bin/python -m sensorpajen.main
|
|
||||||
Restart=always
|
|
||||||
RestartSec=10
|
|
||||||
|
|
||||||
# Bluetooth capabilities
|
|
||||||
AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN
|
|
||||||
|
|
||||||
# Logging
|
|
||||||
StandardOutput=journal
|
|
||||||
StandardError=journal
|
|
||||||
SyslogIdentifier=sensorpajen
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=default.target
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Install service (user service):
|
### Phase 6: Systemd Service Creation ✅ DONE (2025-12-27)
|
||||||
```bash
|
**Goal**: Create and configure systemd user service
|
||||||
mkdir -p ~/.config/systemd/user/
|
|
||||||
cp systemd/sensorpajen.service ~/.config/systemd/user/
|
|
||||||
systemctl --user daemon-reload
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Enable lingering (service runs without login):
|
**Notes**:
|
||||||
```bash
|
- User service for easier management (no sudo required)
|
||||||
sudo loginctl enable-linger fredrik
|
- Service ready for installation on Raspberry Pi
|
||||||
```
|
- Comprehensive documentation provided
|
||||||
|
|
||||||
4. Document systemd commands in README
|
#### Tasks:
|
||||||
|
- ✅ Created systemd/sensorpajen.service
|
||||||
|
- ✅ Created systemd/README.md with full documentation
|
||||||
|
- ✅ Service management and troubleshooting guides included
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
254
systemd/README.md
Normal file
254
systemd/README.md
Normal file
@@ -0,0 +1,254 @@
|
|||||||
|
# Systemd Service Installation
|
||||||
|
|
||||||
|
## Installing Sensorpajen as a User Service
|
||||||
|
|
||||||
|
This allows sensorpajen to run automatically on boot as your user (no sudo required for management).
|
||||||
|
|
||||||
|
### Installation Steps
|
||||||
|
|
||||||
|
#### 1. Install the Service File
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/sensorpajen
|
||||||
|
|
||||||
|
# Create user systemd directory if it doesn't exist
|
||||||
|
mkdir -p ~/.config/systemd/user/
|
||||||
|
|
||||||
|
# Copy service file
|
||||||
|
cp systemd/sensorpajen.service ~/.config/systemd/user/
|
||||||
|
|
||||||
|
# Reload systemd to recognize the new service
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Enable Lingering (Run Without Login)
|
||||||
|
|
||||||
|
This allows your user services to run even when you're not logged in:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Enable lingering for your user
|
||||||
|
sudo loginctl enable-linger $USER
|
||||||
|
|
||||||
|
# Verify it's enabled
|
||||||
|
loginctl show-user $USER | grep Linger
|
||||||
|
# Should show: Linger=yes
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. Start and Enable the Service
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start the service now
|
||||||
|
systemctl --user start sensorpajen
|
||||||
|
|
||||||
|
# Enable it to start on boot
|
||||||
|
systemctl --user enable sensorpajen
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
systemctl --user status sensorpajen
|
||||||
|
```
|
||||||
|
|
||||||
|
### Service Management Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start the service
|
||||||
|
systemctl --user start sensorpajen
|
||||||
|
|
||||||
|
# Stop the service
|
||||||
|
systemctl --user stop sensorpajen
|
||||||
|
|
||||||
|
# Restart the service
|
||||||
|
systemctl --user restart sensorpajen
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
systemctl --user status sensorpajen
|
||||||
|
|
||||||
|
# View logs (all)
|
||||||
|
journalctl --user -u sensorpajen
|
||||||
|
|
||||||
|
# View logs (follow/tail)
|
||||||
|
journalctl --user -u sensorpajen -f
|
||||||
|
|
||||||
|
# View logs (last 100 lines)
|
||||||
|
journalctl --user -u sensorpajen -n 100
|
||||||
|
|
||||||
|
# View logs (since specific time)
|
||||||
|
journalctl --user -u sensorpajen --since "1 hour ago"
|
||||||
|
journalctl --user -u sensorpajen --since "2025-12-27 10:00"
|
||||||
|
|
||||||
|
# Enable service (start on boot)
|
||||||
|
systemctl --user enable sensorpajen
|
||||||
|
|
||||||
|
# Disable service (don't start on boot)
|
||||||
|
systemctl --user disable sensorpajen
|
||||||
|
```
|
||||||
|
|
||||||
|
### Viewing Logs
|
||||||
|
|
||||||
|
The service logs to systemd journal. View them with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Live view (like tail -f)
|
||||||
|
journalctl --user -u sensorpajen -f
|
||||||
|
|
||||||
|
# With timestamps
|
||||||
|
journalctl --user -u sensorpajen -f -o short-iso
|
||||||
|
|
||||||
|
# Just today's logs
|
||||||
|
journalctl --user -u sensorpajen --since today
|
||||||
|
```
|
||||||
|
|
||||||
|
### Updating the Service
|
||||||
|
|
||||||
|
After making changes to the code:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pull latest changes
|
||||||
|
cd ~/sensorpajen
|
||||||
|
git pull origin master
|
||||||
|
|
||||||
|
# Restart the service to apply changes
|
||||||
|
systemctl --user restart sensorpajen
|
||||||
|
|
||||||
|
# Check it started correctly
|
||||||
|
systemctl --user status sensorpajen
|
||||||
|
```
|
||||||
|
|
||||||
|
After editing `sensorpajen.service`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy updated service file
|
||||||
|
cp systemd/sensorpajen.service ~/.config/systemd/user/
|
||||||
|
|
||||||
|
# Reload systemd configuration
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
|
||||||
|
# Restart the service
|
||||||
|
systemctl --user restart sensorpajen
|
||||||
|
```
|
||||||
|
|
||||||
|
After editing configuration files:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Edit config
|
||||||
|
nano ~/sensorpajen/config/sensorpajen.env
|
||||||
|
# or
|
||||||
|
nano ~/sensorpajen/config/sensors.json
|
||||||
|
|
||||||
|
# Restart service to reload config
|
||||||
|
systemctl --user restart sensorpajen
|
||||||
|
```
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
#### Service Won't Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check detailed status
|
||||||
|
systemctl --user status sensorpajen
|
||||||
|
|
||||||
|
# Check logs for errors
|
||||||
|
journalctl --user -u sensorpajen -n 50
|
||||||
|
|
||||||
|
# Test the command manually
|
||||||
|
cd ~/sensorpajen
|
||||||
|
source .venv/bin/activate
|
||||||
|
export $(cat config/sensorpajen.env | grep -v '^#' | xargs)
|
||||||
|
python -m sensorpajen.main
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Bluetooth Permission Errors
|
||||||
|
|
||||||
|
Make sure capabilities are set on the Python binary:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
getcap $(readlink -f ~/.venv/bin/python3)
|
||||||
|
# Should show: cap_net_raw,cap_net_admin+eip
|
||||||
|
|
||||||
|
# If not set:
|
||||||
|
sudo setcap 'cap_net_raw,cap_net_admin+eip' $(readlink -f ~/sensorpajen/.venv/bin/python3)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Service Doesn't Start on Boot
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check if service is enabled
|
||||||
|
systemctl --user is-enabled sensorpajen
|
||||||
|
# Should show: enabled
|
||||||
|
|
||||||
|
# Check if lingering is enabled
|
||||||
|
loginctl show-user $USER | grep Linger
|
||||||
|
# Should show: Linger=yes
|
||||||
|
|
||||||
|
# If not enabled:
|
||||||
|
systemctl --user enable sensorpajen
|
||||||
|
sudo loginctl enable-linger $USER
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Environment Variables Not Loading
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Verify environment file exists and is readable
|
||||||
|
cat ~/sensorpajen/config/sensorpajen.env
|
||||||
|
|
||||||
|
# Check file permissions
|
||||||
|
ls -la ~/sensorpajen/config/sensorpajen.env
|
||||||
|
|
||||||
|
# Test loading manually
|
||||||
|
export $(cat ~/sensorpajen/config/sensorpajen.env | grep -v '^#' | xargs)
|
||||||
|
env | grep MQTT
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verifying Everything Works
|
||||||
|
|
||||||
|
After installation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Check service is running
|
||||||
|
systemctl --user status sensorpajen
|
||||||
|
|
||||||
|
# 2. Check logs show sensor data
|
||||||
|
journalctl --user -u sensorpajen -f
|
||||||
|
|
||||||
|
# 3. Check MQTT messages are being published
|
||||||
|
mosquitto_sub -h 192.168.0.114 -u hasse -P casablanca -t "MiTemperature2/#" -v
|
||||||
|
|
||||||
|
# 4. Reboot and verify it starts automatically
|
||||||
|
sudo reboot
|
||||||
|
# After reboot:
|
||||||
|
systemctl --user status sensorpajen
|
||||||
|
```
|
||||||
|
|
||||||
|
### Uninstalling the Service
|
||||||
|
|
||||||
|
If you need to remove the service:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Stop and disable
|
||||||
|
systemctl --user stop sensorpajen
|
||||||
|
systemctl --user disable sensorpajen
|
||||||
|
|
||||||
|
# Remove service file
|
||||||
|
rm ~/.config/systemd/user/sensorpajen.service
|
||||||
|
|
||||||
|
# Reload systemd
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
|
||||||
|
# Optionally disable lingering
|
||||||
|
sudo loginctl disable-linger $USER
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- **User Service**: Runs as your user, not root - more secure and easier to manage
|
||||||
|
- **Lingering**: Required for services to run when not logged in
|
||||||
|
- **Logs**: All output goes to systemd journal (journalctl)
|
||||||
|
- **Auto-restart**: Service restarts automatically on crashes
|
||||||
|
- **Environment**: Config loaded from `config/sensorpajen.env`
|
||||||
|
- **Working Directory**: Service runs from `~/sensorpajen`
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
Once the service is working:
|
||||||
|
1. Monitor for a few days to ensure stability
|
||||||
|
2. Check logs occasionally: `journalctl --user -u sensorpajen --since yesterday`
|
||||||
|
3. Service will survive reboots and automatically restart on failures
|
||||||
30
systemd/sensorpajen.service
Normal file
30
systemd/sensorpajen.service
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Sensorpajen - Bluetooth Temperature Sensor Monitor
|
||||||
|
Documentation=https://github.com/yourusername/sensorpajen
|
||||||
|
After=network.target bluetooth.target
|
||||||
|
Wants=bluetooth.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
WorkingDirectory=%h/sensorpajen
|
||||||
|
EnvironmentFile=%h/sensorpajen/config/sensorpajen.env
|
||||||
|
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
|
||||||
|
NoNewPrivileges=true
|
||||||
|
PrivateTmp=true
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
Reference in New Issue
Block a user