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>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
3d6608ef80
commit
3b3ffd8ebf
@@ -0,0 +1,85 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
// DB wraps the sqlite connection used by the whole application.
|
||||
type DB struct {
|
||||
*sql.DB
|
||||
}
|
||||
|
||||
const schema = `
|
||||
CREATE TABLE IF NOT EXISTS servers (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
interface_name TEXT NOT NULL UNIQUE,
|
||||
listen_port INTEGER NOT NULL,
|
||||
private_key TEXT NOT NULL,
|
||||
public_key TEXT NOT NULL,
|
||||
address_range TEXT NOT NULL,
|
||||
dns TEXT DEFAULT '',
|
||||
mtu INTEGER DEFAULT 1420,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS peers (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
server_id INTEGER NOT NULL REFERENCES servers(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT DEFAULT '',
|
||||
public_key TEXT NOT NULL,
|
||||
private_key TEXT DEFAULT '',
|
||||
preshared_key TEXT DEFAULT '',
|
||||
allowed_ips TEXT NOT NULL,
|
||||
endpoint TEXT DEFAULT '',
|
||||
persistent_keepalive INTEGER DEFAULT 25,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
expires_at DATETIME,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS audit_log (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
actor TEXT NOT NULL,
|
||||
action TEXT NOT NULL,
|
||||
target TEXT NOT NULL,
|
||||
detail TEXT DEFAULT '',
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT NOT NULL UNIQUE,
|
||||
password_hash TEXT NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_peers_server_id ON peers(server_id);
|
||||
`
|
||||
|
||||
// Open opens (creating if needed) the sqlite database at path and applies schema.
|
||||
func Open(path string) (*DB, error) {
|
||||
sqlDB, err := sql.Open("sqlite", path+"?_pragma=foreign_keys(1)")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open sqlite: %w", err)
|
||||
}
|
||||
if _, err := sqlDB.Exec(schema); err != nil {
|
||||
sqlDB.Close()
|
||||
return nil, fmt.Errorf("apply schema: %w", err)
|
||||
}
|
||||
return &DB{sqlDB}, nil
|
||||
}
|
||||
|
||||
// LogAudit records an entry in the audit log.
|
||||
func (db *DB) LogAudit(actor, action, target, detail string) error {
|
||||
_, err := db.Exec(`INSERT INTO audit_log (actor, action, target, detail) VALUES (?, ?, ?, ?)`,
|
||||
actor, action, target, detail)
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user