- installation_part1.sh: install paquet Tailscale + sudoers /usr/bin/tailscale - services/tailscale_bootstrap.sh (nouveau): script idempotent d'enrolement au boot - services/setup_services.sh: service systemd nebuleair-tailscale-bootstrap (one-shot) - update_firmware.sh: nouvelle etape 3d 'Bootstrap Tailscale' (self-heal install + fetch authkey depuis data.nebuleair.fr/pro_4G/get_tailscale_key.php + enrolement). Fallback HTTPS->HTTP en attendant le cert TLS cote serveur. Permet l'acces SSH distant aux 200 capteurs deployes via le tailnet une fois que leur client a clique sur 'Update' dans l'admin web. Necessite l'endpoint serveur get_tailscale_key.php en place sur data.nebuleair.fr (a deployer en parallele cote AirCarto, auth par deviceID + rate limit + audit log). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
413 lines
12 KiB
Bash
413 lines
12 KiB
Bash
#!/bin/bash
|
|
# File: /var/www/nebuleair_pro_4g/services/setup_services.sh
|
|
# Purpose: Set up all systemd services for NebuleAir data collection
|
|
# to install:
|
|
# sudo chmod +x /var/www/nebuleair_pro_4g/services/setup_services.sh
|
|
# sudo /var/www/nebuleair_pro_4g/services/setup_services.sh
|
|
|
|
echo "Setting up NebuleAir systemd services and timers..."
|
|
|
|
# Create directory for logs if it doesn't exist
|
|
mkdir -p /var/www/nebuleair_pro_4g/logs
|
|
|
|
# Create service and timer files for NPM Data
|
|
cat > /etc/systemd/system/nebuleair-npm-data.service << 'EOL'
|
|
[Unit]
|
|
Description=NebuleAir NPM Data Collection Service
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/bin/python3 /var/www/nebuleair_pro_4g/NPM/get_data_modbus_v3.py
|
|
User=root
|
|
WorkingDirectory=/var/www/nebuleair_pro_4g
|
|
StandardOutput=append:/var/www/nebuleair_pro_4g/logs/npm_service.log
|
|
StandardError=append:/var/www/nebuleair_pro_4g/logs/npm_service_errors.log
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOL
|
|
|
|
cat > /etc/systemd/system/nebuleair-npm-data.timer << 'EOL'
|
|
[Unit]
|
|
Description=Run NebuleAir NPM Data Collection every 10 seconds
|
|
Requires=nebuleair-npm-data.service
|
|
|
|
[Timer]
|
|
OnBootSec=10s
|
|
OnUnitActiveSec=10s
|
|
AccuracySec=1s
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
EOL
|
|
|
|
# Create service and timer files for Envea Data
|
|
cat > /etc/systemd/system/nebuleair-envea-data.service << 'EOL'
|
|
[Unit]
|
|
Description=NebuleAir Envea Data Collection Service
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/bin/python3 /var/www/nebuleair_pro_4g/envea/read_value_v2.py
|
|
User=root
|
|
WorkingDirectory=/var/www/nebuleair_pro_4g
|
|
StandardOutput=append:/var/www/nebuleair_pro_4g/logs/envea_service.log
|
|
StandardError=append:/var/www/nebuleair_pro_4g/logs/envea_service_errors.log
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOL
|
|
|
|
cat > /etc/systemd/system/nebuleair-envea-data.timer << 'EOL'
|
|
[Unit]
|
|
Description=Run NebuleAir Envea Data Collection every 10 seconds
|
|
Requires=nebuleair-envea-data.service
|
|
|
|
[Timer]
|
|
OnBootSec=10s
|
|
OnUnitActiveSec=10s
|
|
AccuracySec=1s
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
EOL
|
|
|
|
# Create service and timer files for SARA Data (No Lock File Needed)
|
|
cat > /etc/systemd/system/nebuleair-sara-data.service << 'EOL'
|
|
[Unit]
|
|
Description=NebuleAir SARA Data Transmission Service
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/bin/python3 -u /var/www/nebuleair_pro_4g/loop/SARA_send_data_v2.py
|
|
User=root
|
|
WorkingDirectory=/var/www/nebuleair_pro_4g
|
|
StandardOutput=append:/var/www/nebuleair_pro_4g/logs/sara_service.log
|
|
StandardError=append:/var/www/nebuleair_pro_4g/logs/sara_service_errors.log
|
|
RuntimeMaxSec=200s
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOL
|
|
|
|
cat > /etc/systemd/system/nebuleair-sara-data.timer << 'EOL'
|
|
[Unit]
|
|
Description=Run NebuleAir SARA Data Transmission every 60 seconds
|
|
Requires=nebuleair-sara-data.service
|
|
|
|
[Timer]
|
|
OnBootSec=60s
|
|
OnUnitActiveSec=60s
|
|
AccuracySec=1s
|
|
# This is the key setting that prevents overlap
|
|
Persistent=true
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
EOL
|
|
|
|
# Create service and timer files for BME280 Data
|
|
cat > /etc/systemd/system/nebuleair-bme280-data.service << 'EOL'
|
|
[Unit]
|
|
Description=NebuleAir BME280 Data Collection Service
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/bin/python3 /var/www/nebuleair_pro_4g/BME280/get_data_v2.py
|
|
User=root
|
|
WorkingDirectory=/var/www/nebuleair_pro_4g
|
|
StandardOutput=append:/var/www/nebuleair_pro_4g/logs/bme280_service.log
|
|
StandardError=append:/var/www/nebuleair_pro_4g/logs/bme280_service_errors.log
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOL
|
|
|
|
cat > /etc/systemd/system/nebuleair-bme280-data.timer << 'EOL'
|
|
[Unit]
|
|
Description=Run NebuleAir BME280 Data Collection every 120 seconds
|
|
Requires=nebuleair-bme280-data.service
|
|
|
|
[Timer]
|
|
OnBootSec=120s
|
|
OnUnitActiveSec=120s
|
|
AccuracySec=1s
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
EOL
|
|
|
|
# Create service and timer files for MPPT Data
|
|
cat > /etc/systemd/system/nebuleair-mppt-data.service << 'EOL'
|
|
[Unit]
|
|
Description=NebuleAir MPPT Data Collection Service
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/bin/python3 /var/www/nebuleair_pro_4g/MPPT/read.py
|
|
User=root
|
|
WorkingDirectory=/var/www/nebuleair_pro_4g
|
|
StandardOutput=append:/var/www/nebuleair_pro_4g/logs/mppt_service.log
|
|
StandardError=append:/var/www/nebuleair_pro_4g/logs/mppt_service_errors.log
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOL
|
|
|
|
cat > /etc/systemd/system/nebuleair-mppt-data.timer << 'EOL'
|
|
[Unit]
|
|
Description=Run NebuleAir MPPT Data Collection every 120 seconds
|
|
Requires=nebuleair-mppt-data.service
|
|
|
|
[Timer]
|
|
OnBootSec=120s
|
|
OnUnitActiveSec=120s
|
|
AccuracySec=1s
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
EOL
|
|
|
|
# Create service and timer files for noise Data (every minutes)
|
|
cat > /etc/systemd/system/nebuleair-noise-data.service << 'EOL'
|
|
[Unit]
|
|
Description=NebuleAir noise Data Collection Service
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/bin/python3 /var/www/nebuleair_pro_4g/sound_meter/NSRT_mk4_get_data.py
|
|
User=root
|
|
WorkingDirectory=/var/www/nebuleair_pro_4g
|
|
StandardOutput=append:/var/www/nebuleair_pro_4g/logs/noise_service.log
|
|
StandardError=append:/var/www/nebuleair_pro_4g/logs/noise_service_errors.log
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOL
|
|
|
|
cat > /etc/systemd/system/nebuleair-noise-data.timer << 'EOL'
|
|
[Unit]
|
|
Description=Run NebuleAir MPPT Data Collection every 120 seconds
|
|
Requires=nebuleair-noise-data.service
|
|
|
|
[Timer]
|
|
OnBootSec=60s
|
|
OnUnitActiveSec=60s
|
|
AccuracySec=1s
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
EOL
|
|
|
|
# Create service and timer files for MH-Z19 CO2 Data
|
|
cat > /etc/systemd/system/nebuleair-mhz19-data.service << 'EOL'
|
|
[Unit]
|
|
Description=NebuleAir MH-Z19 CO2 Data Collection Service
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/bin/python3 /var/www/nebuleair_pro_4g/MH-Z19/write_data.py
|
|
User=root
|
|
WorkingDirectory=/var/www/nebuleair_pro_4g
|
|
StandardOutput=append:/var/www/nebuleair_pro_4g/logs/mhz19_service.log
|
|
StandardError=append:/var/www/nebuleair_pro_4g/logs/mhz19_service_errors.log
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOL
|
|
|
|
cat > /etc/systemd/system/nebuleair-mhz19-data.timer << 'EOL'
|
|
[Unit]
|
|
Description=Run NebuleAir MH-Z19 CO2 Data Collection every 120 seconds
|
|
Requires=nebuleair-mhz19-data.service
|
|
|
|
[Timer]
|
|
OnBootSec=120s
|
|
OnUnitActiveSec=120s
|
|
AccuracySec=1s
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
EOL
|
|
|
|
# Create service and timer files for Database Cleanup
|
|
cat > /etc/systemd/system/nebuleair-db-cleanup-data.service << 'EOL'
|
|
[Unit]
|
|
Description=NebuleAir Database Cleanup Service
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/bin/python3 /var/www/nebuleair_pro_4g/sqlite/flush_old_data.py
|
|
User=root
|
|
WorkingDirectory=/var/www/nebuleair_pro_4g
|
|
StandardOutput=append:/var/www/nebuleair_pro_4g/logs/db_cleanup_service.log
|
|
StandardError=append:/var/www/nebuleair_pro_4g/logs/db_cleanup_service_errors.log
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOL
|
|
|
|
cat > /etc/systemd/system/nebuleair-db-cleanup-data.timer << 'EOL'
|
|
[Unit]
|
|
Description=Run NebuleAir Database Cleanup daily
|
|
Requires=nebuleair-db-cleanup-data.service
|
|
|
|
[Timer]
|
|
OnBootSec=1h
|
|
OnUnitActiveSec=24h
|
|
AccuracySec=1h
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
EOL
|
|
|
|
# Create service and timer files for WiFi Power Save
|
|
cat > /etc/systemd/system/nebuleair-wifi-powersave.service << 'EOL'
|
|
[Unit]
|
|
Description=NebuleAir WiFi Power Save Service
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/bin/python3 /var/www/nebuleair_pro_4g/wifi/power_save.py
|
|
User=root
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOL
|
|
|
|
cat > /etc/systemd/system/nebuleair-wifi-powersave.timer << 'EOL'
|
|
[Unit]
|
|
Description=NebuleAir WiFi Power Save Timer (10 minutes after boot)
|
|
After=network-online.target
|
|
|
|
[Timer]
|
|
# Run 10 minutes after system boot
|
|
OnBootSec=10min
|
|
# Don't persist timer across reboots
|
|
Persistent=false
|
|
|
|
[Install]
|
|
WantedBy=timers.target
|
|
EOL
|
|
|
|
# Create service file for CPU Power Mode (runs once at boot)
|
|
cat > /etc/systemd/system/nebuleair-cpu-power.service << 'EOL'
|
|
[Unit]
|
|
Description=NebuleAir CPU Power Mode Service
|
|
After=multi-user.target
|
|
Wants=multi-user.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/usr/bin/python3 /var/www/nebuleair_pro_4g/power/apply_cpu_mode_from_db.py
|
|
User=root
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
RemainAfterExit=yes
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOL
|
|
|
|
# Create service file for Tailscale Bootstrap (one-shot at boot)
|
|
# Enrolls the device in the AirCarto Headscale tailnet if an authkey is
|
|
# present at /etc/tailscale/authkey and the device is not already enrolled.
|
|
# Safe to run repeatedly: idempotent and no-op when already enrolled.
|
|
cat > /etc/systemd/system/nebuleair-tailscale-bootstrap.service << 'EOL'
|
|
[Unit]
|
|
Description=NebuleAir Tailscale Bootstrap (enroll on tailnet at boot)
|
|
After=network-online.target tailscaled.service
|
|
Wants=network-online.target tailscaled.service
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=/var/www/nebuleair_pro_4g/services/tailscale_bootstrap.sh
|
|
User=root
|
|
StandardOutput=append:/var/www/nebuleair_pro_4g/logs/tailscale_bootstrap.log
|
|
StandardError=append:/var/www/nebuleair_pro_4g/logs/tailscale_bootstrap_errors.log
|
|
RemainAfterExit=yes
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOL
|
|
|
|
# Create service file for RTC Save to DB (long-running service, no timer)
|
|
# Unmask first in case it was previously masked (symlink to /dev/null)
|
|
# so the cat below writes a real file, not into /dev/null.
|
|
systemctl unmask rtc_save_to_db.service 2>/dev/null || true
|
|
cat > /etc/systemd/system/rtc_save_to_db.service << 'EOL'
|
|
[Unit]
|
|
Description=RTC Save to DB Script
|
|
After=network.target
|
|
|
|
[Service]
|
|
ExecStart=/usr/bin/python3 /var/www/nebuleair_pro_4g/RTC/save_to_db.py
|
|
Restart=always
|
|
RestartSec=1
|
|
User=root
|
|
WorkingDirectory=/var/www/nebuleair_pro_4g
|
|
StandardOutput=append:/var/www/nebuleair_pro_4g/logs/rtc_save_to_db.log
|
|
StandardError=append:/var/www/nebuleair_pro_4g/logs/rtc_save_to_db_errors.log
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOL
|
|
|
|
# Reload systemd to recognize new services
|
|
systemctl daemon-reload
|
|
|
|
# Enable and start all timers
|
|
echo "Enabling and starting all services..."
|
|
for service in npm envea sara bme280 mppt mhz19 db-cleanup noise; do
|
|
systemctl enable nebuleair-$service-data.timer
|
|
systemctl start nebuleair-$service-data.timer
|
|
echo "Started nebuleair-$service-data timer"
|
|
done
|
|
|
|
# Enable and start WiFi power save timer (separate naming convention)
|
|
systemctl enable nebuleair-wifi-powersave.timer
|
|
systemctl start nebuleair-wifi-powersave.timer
|
|
echo "Started nebuleair-wifi-powersave timer"
|
|
|
|
# Enable and start CPU power mode service (runs once at boot)
|
|
systemctl enable nebuleair-cpu-power.service
|
|
systemctl start nebuleair-cpu-power.service
|
|
echo "Started nebuleair-cpu-power service"
|
|
|
|
# Enable Tailscale bootstrap service (runs once at boot to enroll on tailnet)
|
|
# Ensure the bootstrap script is executable — git config core.fileMode=false
|
|
# strips the executable bit on pull, so chmod +x here is required.
|
|
chmod +x /var/www/nebuleair_pro_4g/services/tailscale_bootstrap.sh
|
|
systemctl enable nebuleair-tailscale-bootstrap.service
|
|
systemctl start nebuleair-tailscale-bootstrap.service
|
|
echo "Started nebuleair-tailscale-bootstrap service"
|
|
|
|
# Enable and start RTC Save to DB service (long-running, no timer)
|
|
# Use restart instead of start to pick up new content if the service was
|
|
# already running with an older version of the file.
|
|
systemctl enable rtc_save_to_db.service
|
|
systemctl restart rtc_save_to_db.service
|
|
echo "Started rtc_save_to_db service"
|
|
|
|
echo "Checking status of all timers..."
|
|
systemctl list-timers | grep nebuleair
|
|
|
|
echo "Setup complete. All NebuleAir services are now running."
|
|
echo "To check the status of a specific service:"
|
|
echo " sudo systemctl status nebuleair-npm-data.service"
|
|
echo "To view logs for a specific service:"
|
|
echo " sudo journalctl -u nebuleair-npm-data.service"
|
|
echo "To restart a specific timer:"
|
|
echo " sudo systemctl restart nebuleair-npm-data.timer" |