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:
PaulVua
2026-05-19 11:58:19 +02:00
parent c593b152e8
commit b008b486ae
6 changed files with 194 additions and 1 deletions

View File

@@ -79,6 +79,7 @@ sudo chmod 755 /var/www/nebuleair_pro_4g/SARA/*.py
sudo chmod 755 /var/www/nebuleair_pro_4g/envea/*.py
sudo chmod 755 /var/www/nebuleair_pro_4g/MPPT/*.py 2>/dev/null
sudo chmod 755 /var/www/nebuleair_pro_4g/wifi/*.py 2>/dev/null
sudo chmod 755 /var/www/nebuleair_pro_4g/services/*.sh 2>/dev/null
check_status "File permissions update"
# Step 3b: Ensure Apache/PHP config allows file uploads
@@ -125,6 +126,77 @@ else
print_status "⚠ setup_services.sh not found, skipping"
fi
# Step 3d: Bootstrap Tailscale (install + fetch authkey + enroll on tailnet)
# Self-heal for sensors deployed before v1.9.0 that never had Tailscale.
# - Installs the tailscale binary if missing.
# - Drops a sudoers rule in /etc/sudoers.d/ (safer than touching /etc/sudoers).
# - Fetches the preauth key from data.nebuleair.fr if not already on disk.
# HTTPS → HTTP fallback because data.nebuleair.fr may not have TLS yet.
# TODO: drop the HTTP fallback once the cert is in place.
# - Triggers the bootstrap script to enroll on the tailnet.
print_status ""
print_status "Step 3d: Bootstrap Tailscale..."
# 3d.1: Install tailscale binary if absent
if ! command -v tailscale >/dev/null 2>&1; then
print_status "Installing Tailscale..."
curl -fsSL https://tailscale.com/install.sh | sh
check_status "Tailscale install"
else
print_status " Tailscale already installed ($(tailscale version | head -1))"
fi
# 3d.2: Self-heal sudoers rule (for sensors installed pre-v1.9.0)
TAILSCALE_SUDOERS=/etc/sudoers.d/nebuleair-tailscale
if [ ! -f "$TAILSCALE_SUDOERS" ]; then
echo "www-data ALL=(ALL) NOPASSWD: /usr/bin/tailscale *" | sudo tee "$TAILSCALE_SUDOERS" > /dev/null
sudo chmod 0440 "$TAILSCALE_SUDOERS"
if sudo visudo -c -f "$TAILSCALE_SUDOERS" >/dev/null 2>&1; then
print_status "✓ Sudoers rule for tailscale added"
else
sudo rm -f "$TAILSCALE_SUDOERS"
print_status "⚠ Tailscale sudoers rule failed validation, removed"
fi
fi
# 3d.3: Fetch preauth key from data.nebuleair.fr if not already present
AUTHKEY_FILE=/etc/tailscale/authkey
if [ ! -s "$AUTHKEY_FILE" ]; then
deviceID=$(sqlite3 /var/www/nebuleair_pro_4g/sqlite/sensors.db \
"SELECT value FROM config_table WHERE key='deviceID'" 2>/dev/null)
if [ -z "$deviceID" ]; then
print_status "⚠ deviceID empty, cannot fetch tailscale authkey"
else
print_status "Fetching tailscale authkey for deviceID=$deviceID..."
URL_HTTPS="https://data.nebuleair.fr/pro_4G/get_tailscale_key.php?deviceID=${deviceID}"
URL_HTTP="http://data.nebuleair.fr/pro_4G/get_tailscale_key.php?deviceID=${deviceID}"
authkey=$(curl -fsS --max-time 30 "$URL_HTTPS" 2>/dev/null || \
curl -fsS --max-time 30 "$URL_HTTP" 2>/dev/null || true)
if [[ "$authkey" == hskey-auth-* ]]; then
sudo mkdir -p /etc/tailscale
echo "$authkey" | sudo tee "$AUTHKEY_FILE" > /dev/null
sudo chmod 600 "$AUTHKEY_FILE"
sudo chown root:root "$AUTHKEY_FILE"
print_status "✓ Tailscale authkey stored at $AUTHKEY_FILE"
else
print_status "⚠ Could not fetch tailscale authkey (server unreachable or invalid response)"
fi
fi
else
print_status " Tailscale authkey already present"
fi
# 3d.4: Trigger the bootstrap (idempotent, no-op if already enrolled)
BOOTSTRAP=/var/www/nebuleair_pro_4g/services/tailscale_bootstrap.sh
if [ -x "$BOOTSTRAP" ]; then
sudo "$BOOTSTRAP" || print_status "⚠ Tailscale bootstrap returned non-zero (see logs/tailscale_bootstrap.log)"
elif [ -f "$BOOTSTRAP" ]; then
sudo chmod +x "$BOOTSTRAP"
sudo "$BOOTSTRAP" || print_status "⚠ Tailscale bootstrap returned non-zero (see logs/tailscale_bootstrap.log)"
else
print_status "⚠ Bootstrap script not found at $BOOTSTRAP"
fi
# Step 4: Restart critical services if they exist
print_status ""
print_status "Step 4: Managing system services..."