Files
edubox/agent/main.go
T
root 852171cc59 feat(vpn): intégration Tailscale/Headscale + URLs publiques par sous-domaine
- Ajout d'un conteneur Tailscale côté serveur pour joindre les agents via IPs Tailscale
- Configuration Headscale exposé en HTTPS via Caddy (headscale.alfrednobel.edudeploy.com)
- Caddy configuré pour les sous-domaines avec TLS on-demand
- Middleware et route proxy Next.js pour router les sous-domaines vers les agents
- Ajout du champ domain sur Establishment et affichage de l'URL publique dans le dashboard
- Agent Windows v0.2.3 avec proxy Tailscale par instance pour contourner Docker Desktop
- Templates WordPress/PrestaShop bindés sur 0.0.0.0 pour être accessibles via Tailscale
2026-06-12 21:41:56 +00:00

85 lines
2.1 KiB
Go

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
}
}