package main import ( "flag" "fmt" "log" "os" "path/filepath" "time" ) // version is injected at build time via -ldflags "-X main.version=X.Y.Z" var version = "dev" var ( serverAddr = flag.String("server", "ws://localhost:3001", "Adresse WebSocket du serveur") nodeID = flag.String("node-id", defaultNodeID(), "ID du nœud (défaut: hostname)") dataDir = flag.String("data-dir", "./edubox-data", "Répertoire de données") uiEnabled = flag.Bool("ui", true, "Activer l'interface locale HTMX") headscaleURL = flag.String("headscale-url", "", "URL du serveur Headscale (ex: http://151.80.60.98:8080)") headscaleAuthKey = flag.String("headscale-auth-key", "", "Clé d'authentification Headscale") ) func defaultNodeID() string { h, err := os.Hostname() if err != nil { return "unknown" } return h } func main() { flag.Parse() dd := *dataDir if !filepath.IsAbs(dd) { ex, err := os.Executable() if err == nil { dd = filepath.Join(filepath.Dir(ex), dd) } else { wd, _ := os.Getwd() dd = filepath.Join(wd, dd) } } *dataDir = dd if err := os.MkdirAll(*dataDir, 0755); err != nil { log.Fatalf("Cannot create data-dir: %v", err) } fmt.Printf("EduBox Agent v%s - node: %s - data-dir: %s\n", version, *nodeID, *dataDir) if *uiEnabled { go startUI(*dataDir, *nodeID, *serverAddr) } go startWebSocket(*serverAddr, *nodeID, *dataDir) if *headscaleURL != "" && *headscaleAuthKey != "" { go startTailscaleAndReport(*dataDir, *nodeID, *headscaleURL, *headscaleAuthKey) } select {} } func startTailscaleAndReport(dataDir, nodeID, headscaleURL, authKey string) { tsDir := filepath.Join(dataDir, "tailscale") ip, err := startTailscale(tsDir, nodeID, headscaleURL, authKey) if err != nil { log.Printf("Tailscale error: %v", err) return } log.Printf("Tailscale IP obtained: %s", ip) for { if err := sendMessage(WSMessage{Action: "tailscale_ip", NodeID: nodeID, TailscaleIP: ip}); err != nil { log.Printf("Waiting for WebSocket to send tailscale_ip...") time.Sleep(1 * time.Second) continue } log.Printf("Sent tailscale_ip to server: %s", ip) break } }