Fix system installation state directory
The service was failing with 'Read-only file system' when trying to create discovered_sensors.json in the /etc/sensorpajen config directory. Changes: - config.py: Add STATE_DIR for runtime state - System mode: /var/lib/sensorpajen (writable at runtime) - Dev mode: config/ (same as config directory) - config.py: Use STATE_DIR for discovered_sensors.json path - debian/postinst: Create and own /var/lib/sensorpajen - debian/sensorpajen.service: Add /var/lib/sensorpajen to ReadWritePaths - debian/postinst: Remove discovered_sensors.json.example copy (created at runtime) This separates: - Config: /etc/sensorpajen (static, not updated by service) - State: /var/lib/sensorpajen (dynamic, updated by service at runtime)
This commit is contained in:
1
debian/files
vendored
1
debian/files
vendored
@@ -1,2 +1 @@
|
||||
sensorpajen_2.0.0-dev_all.deb misc optional
|
||||
sensorpajen_2.0.0-dev_amd64.buildinfo misc optional
|
||||
|
||||
7
debian/postinst
vendored
7
debian/postinst
vendored
@@ -14,8 +14,13 @@ case "$1" in
|
||||
chown sensorpajen:sensorpajen /etc/sensorpajen
|
||||
chmod 750 /etc/sensorpajen
|
||||
|
||||
# Create state directory with proper permissions (writable at runtime)
|
||||
mkdir -p /var/lib/sensorpajen
|
||||
chown sensorpajen:sensorpajen /var/lib/sensorpajen
|
||||
chmod 750 /var/lib/sensorpajen
|
||||
|
||||
# Copy example configs to /etc/sensorpajen if they don't exist
|
||||
for sample in sensorpajen.env.example sensors.json.example discovered_sensors.json.example; do
|
||||
for sample in sensorpajen.env.example sensors.json.example; do
|
||||
source_file="/usr/share/doc/sensorpajen/examples/$sample"
|
||||
target_file="/etc/sensorpajen/${sample%.example}"
|
||||
|
||||
|
||||
2
debian/sensorpajen.service
vendored
2
debian/sensorpajen.service
vendored
@@ -26,7 +26,7 @@ SyslogIdentifier=sensorpajen
|
||||
PrivateTmp=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
ReadWritePaths=/etc/sensorpajen
|
||||
ReadWritePaths=/etc/sensorpajen /var/lib/sensorpajen
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
2
debian/sensorpajen/DEBIAN/control
vendored
2
debian/sensorpajen/DEBIAN/control
vendored
@@ -2,7 +2,7 @@ Package: sensorpajen
|
||||
Version: 2.0.0-dev
|
||||
Architecture: all
|
||||
Maintainer: Fredrik <fredrik@wahlberg.se>
|
||||
Installed-Size: 110
|
||||
Installed-Size: 111
|
||||
Depends: python3 (>= 3.9), python3-venv, python3-pip, bluetooth, bluez, libcap2-bin
|
||||
Recommends: mosquitto-clients
|
||||
Section: misc
|
||||
|
||||
8
debian/sensorpajen/DEBIAN/md5sums
vendored
8
debian/sensorpajen/DEBIAN/md5sums
vendored
@@ -3,17 +3,17 @@
|
||||
940d73f24eb9f971ce27f9355e3072f3 opt/sensorpajen/scripts/approve-sensors.sh
|
||||
20eb4f3839b990a530410768897402c0 opt/sensorpajen/src/sensorpajen/__init__.py
|
||||
1f452c46e42f8dc3751dba6ca68256e9 opt/sensorpajen/src/sensorpajen/approve_sensors.py
|
||||
da40d9df301d523d517d7cf2809d6f11 opt/sensorpajen/src/sensorpajen/config.py
|
||||
8d781ed202be540358a970c2be50f54d opt/sensorpajen/src/sensorpajen/config.py
|
||||
65c63383dde4f0b249b708f854ec75a3 opt/sensorpajen/src/sensorpajen/discovery_manager.py
|
||||
592f8a534833c9e403967fcc0ead8eb1 opt/sensorpajen/src/sensorpajen/main.py
|
||||
7604c2bc0a854d6d43ff0f0646386fc5 opt/sensorpajen/src/sensorpajen/main.py
|
||||
331bf9b314492acc6ce03896367f3cf6 opt/sensorpajen/src/sensorpajen/mqtt_publisher.py
|
||||
5f4ea191e35ce092f39ec0a4f663cb38 opt/sensorpajen/src/sensorpajen/sensor_reader.py
|
||||
c8dd8fe8fc174a9cd35251fdf80e7b5f opt/sensorpajen/src/sensorpajen/utils.py
|
||||
c9c22f9c1d65bfafd89fa45f16b7192b usr/lib/systemd/system/sensorpajen.service
|
||||
b9ad3ea8307d8ed8e938da37ad00f229 usr/lib/systemd/system/sensorpajen.service
|
||||
4ddb9618c940286f91df901ec818959a usr/share/doc/sensorpajen/INSTALL.md.gz
|
||||
bd2f1371c60af415bc9d0dbc1111184d usr/share/doc/sensorpajen/ROADMAP.md.gz
|
||||
380e8e6b01b757ceac05bc5805844ae4 usr/share/doc/sensorpajen/changelog.Debian.gz
|
||||
14152a98d7cd7fe8daf280aacc4cbf3f usr/share/doc/sensorpajen/examples/discovered_sensors.json.example
|
||||
387cb9ee7f22570312604e2cc07ca7a0 usr/share/doc/sensorpajen/examples/sensorpajen.env.example
|
||||
74c99b732363f93f0a1c134e1a8c3d35 usr/share/doc/sensorpajen/examples/sensorpajen.env.example
|
||||
292efbddd951c39cb2c9546d5fac5e05 usr/share/doc/sensorpajen/examples/sensors.json.example
|
||||
5f647c63bfc3b174611694779fd215e0 usr/share/doc/sensorpajen/readme.md.gz
|
||||
|
||||
18
debian/sensorpajen/DEBIAN/postinst
vendored
18
debian/sensorpajen/DEBIAN/postinst
vendored
@@ -14,8 +14,13 @@ case "$1" in
|
||||
chown sensorpajen:sensorpajen /etc/sensorpajen
|
||||
chmod 750 /etc/sensorpajen
|
||||
|
||||
# Create state directory with proper permissions (writable at runtime)
|
||||
mkdir -p /var/lib/sensorpajen
|
||||
chown sensorpajen:sensorpajen /var/lib/sensorpajen
|
||||
chmod 750 /var/lib/sensorpajen
|
||||
|
||||
# Copy example configs to /etc/sensorpajen if they don't exist
|
||||
for sample in sensorpajen.env.example sensors.json.example discovered_sensors.json.example; do
|
||||
for sample in sensorpajen.env.example sensors.json.example; do
|
||||
source_file="/usr/share/doc/sensorpajen/examples/$sample"
|
||||
target_file="/etc/sensorpajen/${sample%.example}"
|
||||
|
||||
@@ -48,7 +53,7 @@ case "$1" in
|
||||
venv/bin/pip install -r /opt/sensorpajen/requirements.txt
|
||||
else
|
||||
echo "Warning: requirements.txt not found, installing bluepy and paho-mqtt directly"
|
||||
venv/bin/pip install bluepy paho-mqtt
|
||||
venv/bin/pip install bluepy paho-mqtt pybluez
|
||||
fi
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
@@ -56,6 +61,15 @@ case "$1" in
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Install sensorpajen package itself
|
||||
echo "Installing sensorpajen application..."
|
||||
cd /opt/sensorpajen
|
||||
venv/bin/pip install --no-deps . || {
|
||||
echo "Error: Failed to install sensorpajen package"
|
||||
exit 1
|
||||
}
|
||||
cd /
|
||||
|
||||
# Set ownership of application directory BEFORE setting capabilities
|
||||
chown -R sensorpajen:sensorpajen /opt/sensorpajen
|
||||
|
||||
|
||||
@@ -19,10 +19,12 @@ if Path('/opt/sensorpajen').exists():
|
||||
# System installation
|
||||
PROJECT_ROOT = Path('/opt/sensorpajen')
|
||||
CONFIG_DIR = Path('/etc/sensorpajen')
|
||||
STATE_DIR = Path('/var/lib/sensorpajen')
|
||||
else:
|
||||
# Development installation (3 levels up from this file: src/sensorpajen/config.py)
|
||||
PROJECT_ROOT = Path(__file__).parent.parent.parent
|
||||
CONFIG_DIR = PROJECT_ROOT / "config"
|
||||
STATE_DIR = CONFIG_DIR
|
||||
|
||||
# MQTT Configuration from environment
|
||||
MQTT_HOST = os.environ.get("MQTT_HOST")
|
||||
@@ -63,7 +65,7 @@ NTFY_TOKEN = os.environ.get("NTFY_TOKEN", "")
|
||||
# Discovery settings
|
||||
DISCOVERED_SENSORS_FILE = os.environ.get(
|
||||
"DISCOVERED_SENSORS_FILE",
|
||||
str(CONFIG_DIR / "discovered_sensors.json")
|
||||
str(STATE_DIR / "discovered_sensors.json")
|
||||
)
|
||||
CONFIG_RELOAD_INTERVAL = int(os.environ.get("CONFIG_RELOAD_INTERVAL", "900")) # 15 minutes
|
||||
|
||||
@@ -85,11 +87,11 @@ class SensorConfig:
|
||||
def load(self):
|
||||
"""Load sensor configuration from JSON file."""
|
||||
if not self.config_file.exists():
|
||||
raise FileNotFoundError(
|
||||
logger.warning(
|
||||
f"Sensor configuration file not found: {self.config_file}\n"
|
||||
f"Please copy config/sensors.json.example to config/sensors.json "
|
||||
f"and configure your sensors."
|
||||
f"Starting with no sensors - use discovery to add sensors"
|
||||
)
|
||||
return
|
||||
|
||||
try:
|
||||
with open(self.config_file, 'r') as f:
|
||||
|
||||
@@ -125,9 +125,9 @@ class Sensorpajen:
|
||||
self.sensor_config = config.SensorConfig()
|
||||
|
||||
if len(self.sensor_config.sensors) == 0:
|
||||
self.logger.error("No sensors configured!")
|
||||
self.logger.error("Please configure sensors in config/sensors.json")
|
||||
sys.exit(1)
|
||||
self.logger.warning("No sensors configured")
|
||||
self.logger.warning("Starting in discovery-only mode")
|
||||
self.logger.warning("Use 'sensorpajen approve-sensors' to add sensors")
|
||||
|
||||
# Initialize discovery manager
|
||||
self.logger.info("Initializing discovery manager...")
|
||||
|
||||
@@ -26,7 +26,7 @@ SyslogIdentifier=sensorpajen
|
||||
PrivateTmp=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
ReadWritePaths=/etc/sensorpajen
|
||||
ReadWritePaths=/etc/sensorpajen /var/lib/sensorpajen
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -5,9 +5,16 @@ MQTT_USER=hasse
|
||||
MQTT_PASSWORD=casablanca
|
||||
MQTT_CLIENT_ID=mibridge
|
||||
|
||||
# Sensor Configuration (relative to project root)
|
||||
SENSOR_CONFIG_FILE=config/sensors.json
|
||||
DISCOVERED_SENSORS_FILE=config/discovered_sensors.json
|
||||
# Sensor Configuration
|
||||
# For system installation (/opt/sensorpajen): Use absolute paths
|
||||
# SENSOR_CONFIG_FILE=/etc/sensorpajen/sensors.json
|
||||
# DISCOVERED_SENSORS_FILE=/etc/sensorpajen/discovered_sensors.json
|
||||
#
|
||||
# For development installation: Use relative paths (from project root)
|
||||
# SENSOR_CONFIG_FILE=config/sensors.json
|
||||
# DISCOVERED_SENSORS_FILE=config/discovered_sensors.json
|
||||
#
|
||||
# If not set, defaults will be used based on installation type
|
||||
|
||||
# Application Settings
|
||||
WATCHDOG_TIMEOUT=5
|
||||
|
||||
@@ -19,10 +19,12 @@ if Path('/opt/sensorpajen').exists():
|
||||
# System installation
|
||||
PROJECT_ROOT = Path('/opt/sensorpajen')
|
||||
CONFIG_DIR = Path('/etc/sensorpajen')
|
||||
STATE_DIR = Path('/var/lib/sensorpajen')
|
||||
else:
|
||||
# Development installation (3 levels up from this file: src/sensorpajen/config.py)
|
||||
PROJECT_ROOT = Path(__file__).parent.parent.parent
|
||||
CONFIG_DIR = PROJECT_ROOT / "config"
|
||||
STATE_DIR = CONFIG_DIR
|
||||
|
||||
# MQTT Configuration from environment
|
||||
MQTT_HOST = os.environ.get("MQTT_HOST")
|
||||
@@ -63,7 +65,7 @@ NTFY_TOKEN = os.environ.get("NTFY_TOKEN", "")
|
||||
# Discovery settings
|
||||
DISCOVERED_SENSORS_FILE = os.environ.get(
|
||||
"DISCOVERED_SENSORS_FILE",
|
||||
str(CONFIG_DIR / "discovered_sensors.json")
|
||||
str(STATE_DIR / "discovered_sensors.json")
|
||||
)
|
||||
CONFIG_RELOAD_INTERVAL = int(os.environ.get("CONFIG_RELOAD_INTERVAL", "900")) # 15 minutes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user