feat(vpn): VPN on-demand Tailscale + agent studioE5 standalone
- Agent studioE5 standalone en Go (console + systray) - VPN on-demand via tailscaled + tailscale up (authkey Headscale) - Resolver/serveur dans le tailnet studioe5 - Caddy on-demand TLS pour les instances - Nouveaux endpoints serveur /api/internal/send-to-node - Suppression des anciens binaires edubox-agent - Suivi dans SUIVI_VPN_ONDEMAND.md
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// AgentConfig holds user-editable settings for the agent.
|
||||
type AgentConfig struct {
|
||||
Server string `json:"server"`
|
||||
HeadscaleURL string `json:"headscale_url"`
|
||||
HeadscaleAuthKey string `json:"headscale_auth_key"`
|
||||
NodeID string `json:"node_id"`
|
||||
DataDir string `json:"data_dir"`
|
||||
}
|
||||
|
||||
const configFileName = "studioE5-config.json"
|
||||
|
||||
// defaultConfig returns sensible defaults for a first run.
|
||||
func defaultConfig(dataDir string) *AgentConfig {
|
||||
return &AgentConfig{
|
||||
Server: "ws://localhost:3001",
|
||||
HeadscaleURL: "",
|
||||
HeadscaleAuthKey: "",
|
||||
NodeID: defaultNodeID(),
|
||||
DataDir: dataDir,
|
||||
}
|
||||
}
|
||||
|
||||
// configPath returns the absolute path to the config file.
|
||||
func configPath(dataDir string) string {
|
||||
return filepath.Join(dataDir, configFileName)
|
||||
}
|
||||
|
||||
// loadOrCreateConfig loads the config file. If it does not exist, it creates
|
||||
// one with default values and returns it (the caller can then open the settings UI).
|
||||
func loadOrCreateConfig(dataDir string) (*AgentConfig, bool, error) {
|
||||
cp := configPath(dataDir)
|
||||
|
||||
if _, err := os.Stat(cp); err == nil {
|
||||
data, err := os.ReadFile(cp)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
var cfg AgentConfig
|
||||
if err := json.Unmarshal(data, &cfg); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return &cfg, false, nil
|
||||
}
|
||||
|
||||
cfg := defaultConfig(dataDir)
|
||||
if err := saveConfig(dataDir, cfg); err != nil {
|
||||
return nil, true, err
|
||||
}
|
||||
return cfg, true, nil
|
||||
}
|
||||
|
||||
// saveConfig writes the config file to disk.
|
||||
func saveConfig(dataDir string, cfg *AgentConfig) error {
|
||||
cp := configPath(dataDir)
|
||||
data, err := json.MarshalIndent(cfg, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(cp, data, 0644)
|
||||
}
|
||||
Reference in New Issue
Block a user