package main import ( "fmt" "os" "path/filepath" ) // Paths mirror the bash profiler's layout so both tools can share on-disk // state. They are resolved relative to the executable's directory (overridable // with AWG_PROFILER_DIR), the Go analogue of the script's SCRIPT_DIR. var ( scriptDir string configFile string dataDir string clientDir string registryFile string statsFile string stateFile string // Directory awg-quick reads interface configs from (AmneziaWG default). awgConfDir = "/etc/amnezia/amneziawg" ) func resolveScriptDir() string { if d := os.Getenv("AWG_PROFILER_DIR"); d != "" { return d } exe, err := os.Executable() if err != nil { die("Cannot determine executable path: %v", err) } if resolved, err := filepath.EvalSymlinks(exe); err == nil { exe = resolved } return filepath.Dir(exe) } func initPaths() { scriptDir = resolveScriptDir() configFile = filepath.Join(scriptDir, "awg_config") dataDir = filepath.Join(scriptDir, "data") clientDir = filepath.Join(scriptDir, "awg_clients") registryFile = filepath.Join(dataDir, "awg_clients.json") statsFile = filepath.Join(dataDir, "awg_stats.json") stateFile = filepath.Join(scriptDir, "awg_state.json") } func usage() { fmt.Print(`AmneziaWG Profiler — server + client management tool (AmneziaWG variant) Usage: awg_profiler [options] SERVER SETUP install-deps Install AmneziaWG, jq, qrencode for this OS and record a deps-installed flag (run this FIRST) init-server Interactive server setup: verifies dependencies are installed, then generates keys + obfuscation parameters, writes config, enables IP forwarding and starts the service (does NOT install packages) SERVER MANAGEMENT server-status Show interface stats and peer list server-start Start AmneziaWG service server-stop Stop AmneziaWG service server-restart Restart AmneziaWG service show-config Print current config (private keys hidden) sync-config Rebuild /.conf from client registry and optionally restart the service CLIENT MANAGEMENT create Create new VPN client; generates keys, .conf and QR code delete Remove client by ID (deletes files + registry entry) disable Set client status to DISABLED enable Set client status to ACTIVE list List all registered clients WEB UI web [--addr host:port] Start the management web UI (default 127.0.0.1:8080). Set AWG_WEB_USER + AWG_WEB_PASS for HTTP Basic auth. [--theme name] Select the design (or AWG_WEB_THEME env): classic original Modern Dark UI (default) glass glassmorphism · Slate + Amber [--ui-mode mode] Colour mode (or AWG_WEB_MODE env): dark force dark palette (default) light force light palette (classic only) auto follow the viewer's OS preference Supported OS: Ubuntu, Debian, Linux Mint, Alpine Linux `) } func main() { initPaths() args := os.Args[1:] cmd := "" if len(args) > 0 { cmd = args[0] } rest := args if len(args) > 0 { rest = args[1:] } switch cmd { case "init-server": initServer() case "install-deps": installDeps() case "server-status": requireBinary("awg") c := loadConfig() osInfo := detectOS() serverStatus(c, osInfo) case "server-start": c := loadConfig() osInfo := detectOS() serviceStart(osInfo, c.Interface) info("AmneziaWG started: %s", c.Interface) case "server-stop": c := loadConfig() osInfo := detectOS() serviceStop(osInfo, c.Interface) info("AmneziaWG stopped: %s", c.Interface) case "server-restart": c := loadConfig() osInfo := detectOS() serviceRestart(osInfo, c.Interface) info("AmneziaWG restarted: %s", c.Interface) case "show-config": showConfig() case "sync-config": // jq is no longer needed: the Go port reads/writes the registry natively. c := loadConfig() osInfo := detectOS() syncConfig(c, osInfo) case "create": requireBinary("awg") requireBinary("qrencode") c := loadConfig() initStorage() createClient(c, detectOS(), rest) case "delete": c := loadConfig() initStorage() deleteClient(c, detectOS(), rest) case "disable": c := loadConfig() initStorage() disableClient(c, detectOS(), rest) case "enable": c := loadConfig() initStorage() enableClient(c, detectOS(), rest) case "list": // load_config enforces that the server has been initialised first. loadConfig() initStorage() listClients() case "web": runWeb(rest) case "--help", "-h", "help", "": usage() default: fmt.Fprintf(os.Stderr, "Unknown command: %s\n\n", cmd) usage() os.Exit(1) } }