Files

188 lines
5.0 KiB
Go
Raw Permalink Normal View History

2026-07-18 10:02:43 +03:00
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 <command> [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-dir>/<iface>.conf from client
registry and optionally restart the service
CLIENT MANAGEMENT
create <name> Create new VPN client; generates keys, .conf and QR
code
delete <id> Remove client by ID (deletes files + registry entry)
disable <id> Set client status to DISABLED
enable <id> 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)
}
}