#!/usr/bin/env bash set -euo pipefail BASE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" MODE="${1:---check}" if [[ "$MODE" != "--check" && "$MODE" != "--apply" ]]; then echo "Usage: $0 [--check|--apply]" >&2 exit 2 fi if ! command -v tailscale >/dev/null 2>&1; then cat <<'EOF' Tailscale n'est pas installé. Installation officielle pour Raspberry Pi OS/Debian : curl -fsSL https://tailscale.com/install.sh | sh Alternative recommandée si vous préférez inspecter chaque paquet : https://pkgs.tailscale.com/stable/#raspbian Après installation seulement : sudo tailscale up --hostname=codexpi Cette commande affiche une URL d'authentification. Le script CodexPi ne la valide jamais à votre place et ne crée aucune clé d'authentification. EOF exit 3 fi echo "Tailscale: $(tailscale version | head -n 1)" STATE="$(tailscale status --json 2>/dev/null | python3 -c 'import json,sys; print(json.load(sys.stdin).get("BackendState", "Unknown"))' 2>/dev/null || echo Unknown)" if [[ "$STATE" != "Running" ]]; then echo "Tailscale est installé mais non connecté (état: $STATE)." echo "Connectez explicitement ce Pi au tailnet avec: sudo tailscale up --hostname=codexpi" exit 4 fi TS_IP="$(tailscale ip -4 | head -n 1)" TS_DNS="$(tailscale status --json | python3 -c 'import json,sys; print(json.load(sys.stdin)["Self"].get("DNSName", "").rstrip("."))')" echo "IP privée Tailscale: $TS_IP" echo "Nom MagicDNS: $TS_DNS" echo "Configuration Serve actuelle:" tailscale serve status || true if [[ "$MODE" == "--check" ]]; then echo "Aucune modification effectuée. Pour appliquer: $0 --apply" exit 0 fi [[ -f "$BASE/.env" ]] || { echo "Le fichier $BASE/.env est absent. Lancez d'abord install.sh." >&2; exit 5; } grep -Eq '^CODEXPI_HOST=127\.0\.0\.1$' "$BASE/.env" || { echo "Refus: CODEXPI_HOST doit être exactement 127.0.0.1" >&2; exit 6; } if ! grep -Eqi '^CODEXPI_COOKIE_SECURE=true$' "$BASE/.env"; then echo "Information: les cookies Secure restent désactivés pour permettre l'accès LAN en HTTP." echo "Tailscale Serve ajoute tout de même HTTPS sur le trajet Tailscale." fi PROXY_PORT="$(sed -n 's/^CODEXPI_PROXY_PORT=//p' "$BASE/.env" | tail -n 1)" PROXY_PORT="${PROXY_PORT:-8765}" [[ "$PROXY_PORT" =~ ^[0-9]+$ ]] || { echo "CODEXPI_PROXY_PORT invalide" >&2; exit 8; } curl --fail --silent --show-error --max-time 4 "http://127.0.0.1:${PROXY_PORT}/proxy-health" >/dev/null || { echo "Le reverse proxy CodexPi ne répond pas sur localhost:${PROXY_PORT}" >&2; exit 8; } FUNNEL_STATUS="$(tailscale funnel status 2>&1 || true)" if [[ -n "$FUNNEL_STATUS" && "$FUNNEL_STATUS" != *"No serve config"* ]]; then echo "Refus prudent: une configuration Tailscale Funnel existe déjà." >&2 echo "Inspectez-la manuellement; CodexPi ne remplacera jamais une publication existante." >&2 exit 9 fi tailscale serve --bg --https=443 "http://127.0.0.1:${PROXY_PORT}" echo tailscale serve status echo "Adresse privée HTTPS: https://$TS_DNS" echo "Cette adresse n'est accessible qu'aux appareils autorisés du tailnet."