v1.9.0: Enrolement automatique des capteurs sur le tailnet AirCarto (Tailscale/Headscale)
- 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>
This commit is contained in:
@@ -321,6 +321,28 @@ RemainAfterExit=yes
|
||||
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.
|
||||
@@ -364,6 +386,14 @@ 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.
|
||||
|
||||
57
services/tailscale_bootstrap.sh
Normal file
57
services/tailscale_bootstrap.sh
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/bin/bash
|
||||
# File: /var/www/nebuleair_pro_4g/services/tailscale_bootstrap.sh
|
||||
# Purpose: Enroll the device into the AirCarto Headscale tailnet at boot.
|
||||
# Idempotent: exits cleanly if already enrolled or if authkey is missing.
|
||||
#
|
||||
# Invoked by nebuleair-tailscale-bootstrap.service (one-shot at boot).
|
||||
# Also safe to call manually from update_firmware.sh.
|
||||
|
||||
set -u
|
||||
|
||||
LOGIN_SERVER="https://headscale.aircarto.fr"
|
||||
AUTHKEY_FILE="/etc/tailscale/authkey"
|
||||
DB_FILE="/var/www/nebuleair_pro_4g/sqlite/sensors.db"
|
||||
|
||||
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] tailscale-bootstrap: $1"; }
|
||||
|
||||
if ! command -v tailscale >/dev/null 2>&1; then
|
||||
log "tailscale binary not found, skipping (install via update_firmware.sh)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if tailscale ip -4 >/dev/null 2>&1; then
|
||||
log "already enrolled (IP $(tailscale ip -4)), nothing to do"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ ! -s "$AUTHKEY_FILE" ]]; then
|
||||
log "no authkey at $AUTHKEY_FILE, skipping (will be fetched by update_firmware.sh)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ ! -f "$DB_FILE" ]]; then
|
||||
log "database $DB_FILE not found, cannot derive hostname"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
deviceID=$(sqlite3 "$DB_FILE" "SELECT value FROM config_table WHERE key='deviceID'" 2>/dev/null)
|
||||
if [[ -z "$deviceID" ]]; then
|
||||
log "deviceID empty in config_table, cannot enroll"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Tailscale hostnames must be RFC 1123 (lowercase letters, digits, hyphens).
|
||||
deviceID_clean=$(echo "$deviceID" | tr '[:upper:]' '[:lower:]' | tr -c 'a-z0-9-' '-' | sed 's/-\+/-/g; s/^-//; s/-$//')
|
||||
hostname="nebuleair-pro-${deviceID_clean}"
|
||||
authkey=$(cat "$AUTHKEY_FILE")
|
||||
|
||||
log "enrolling as $hostname..."
|
||||
if tailscale up \
|
||||
--login-server="$LOGIN_SERVER" \
|
||||
--authkey="$authkey" \
|
||||
--hostname="$hostname"; then
|
||||
log "enrollment OK, IP $(tailscale ip -4)"
|
||||
else
|
||||
log "enrollment FAILED (will retry at next boot or update)"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user