Files
wireguard-ui-multi/internal/wireguard/config.go
T
sysopsandClaude Sonnet 5 3b3ffd8ebf Add wireguard-ui-multi core: multi-server DB, WireGuard manager, REST API, UI, installers
Implements the from-scratch multi-server WireGuard management fork per
CLAUDE.md spec: sqlite schema (servers/peers/audit_log/users), Curve25519
key generation, per-interface config rendering + wg-quick/systemd control,
nftables hook scaffolding, session+CSRF-protected REST API with QR code
and config download endpoints, a minimal vanilla-JS web UI, legacy
wg0.conf migration, and both a native installer and a Proxmox LXC
provisioning script (with auto-detected latest Debian template).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 02:53:14 +02:00

87 lines
2.5 KiB
Go

package wireguard
import (
"fmt"
"os"
"path/filepath"
"strings"
"gitea.perlbach24.de/scripte/wireguard-ui-multi/internal/server"
)
// ConfigDir is where per-interface wgX.conf files are written, e.g. /etc/wireguard.
var ConfigDir = "/etc/wireguard"
// RenderConfig builds the wg-quick compatible config text for a server and its peers.
func RenderConfig(srv *server.Server, peers []*server.Peer) string {
var b strings.Builder
fmt.Fprintf(&b, "[Interface]\n")
fmt.Fprintf(&b, "PrivateKey = %s\n", srv.PrivateKey)
fmt.Fprintf(&b, "Address = %s\n", srv.AddressRange)
fmt.Fprintf(&b, "ListenPort = %d\n", srv.ListenPort)
if srv.MTU > 0 {
fmt.Fprintf(&b, "MTU = %d\n", srv.MTU)
}
if srv.DNS != "" {
fmt.Fprintf(&b, "DNS = %s\n", srv.DNS)
}
for _, p := range peers {
if !p.Enabled {
continue
}
b.WriteString("\n[Peer]\n")
fmt.Fprintf(&b, "# %s\n", p.Name)
fmt.Fprintf(&b, "PublicKey = %s\n", p.PublicKey)
if p.PresharedKey != "" {
fmt.Fprintf(&b, "PresharedKey = %s\n", p.PresharedKey)
}
fmt.Fprintf(&b, "AllowedIPs = %s\n", p.AllowedIPs)
if p.PersistentKeepalive > 0 {
fmt.Fprintf(&b, "PersistentKeepalive = %d\n", p.PersistentKeepalive)
}
}
return b.String()
}
// RenderClientConfig builds the config a peer/client would use to connect to srv.
func RenderClientConfig(srv *server.Server, p *server.Peer, endpointHost string) string {
var b strings.Builder
b.WriteString("[Interface]\n")
fmt.Fprintf(&b, "PrivateKey = %s\n", p.PrivateKey)
fmt.Fprintf(&b, "Address = %s\n", p.AllowedIPs)
if srv.DNS != "" {
fmt.Fprintf(&b, "DNS = %s\n", srv.DNS)
}
b.WriteString("\n[Peer]\n")
fmt.Fprintf(&b, "PublicKey = %s\n", srv.PublicKey)
if p.PresharedKey != "" {
fmt.Fprintf(&b, "PresharedKey = %s\n", p.PresharedKey)
}
fmt.Fprintf(&b, "Endpoint = %s:%d\n", endpointHost, srv.ListenPort)
fmt.Fprintf(&b, "AllowedIPs = 0.0.0.0/0, ::/0\n")
if p.PersistentKeepalive > 0 {
fmt.Fprintf(&b, "PersistentKeepalive = %d\n", p.PersistentKeepalive)
}
return b.String()
}
// WriteConfig writes the rendered server config to ConfigDir/<interface>.conf with 0600 perms.
func WriteConfig(srv *server.Server, peers []*server.Peer) error {
if err := os.MkdirAll(ConfigDir, 0700); err != nil {
return err
}
path := filepath.Join(ConfigDir, srv.InterfaceName+".conf")
return os.WriteFile(path, []byte(RenderConfig(srv, peers)), 0600)
}
// ConfigPath returns the on-disk path for a server's config file.
func ConfigPath(srv *server.Server) string {
return filepath.Join(ConfigDir, srv.InterfaceName+".conf")
}