Initial vibeproxy implementation

Self-contained HTTP/HTTPS/TCP/UDP reverse proxy manager written in Go,
with SQLite storage, a Bootstrap 5 admin UI (Go templates, no JS
framework), and a REST API under /api/v1.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QTXFrNP1imCW7jtfL5SZrw
This commit is contained in:
2026-08-17 10:28:59 -05:00
co-authored by Claude Sonnet 5
commit ba1f7c4c03
105 changed files with 9142 additions and 0 deletions
+177
View File
@@ -0,0 +1,177 @@
-- vibeproxy initial schema
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
must_change_pw INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
);
CREATE TABLE IF NOT EXISTS api_tokens (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
token_hash TEXT NOT NULL UNIQUE,
prefix TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
last_used_at TEXT,
revoked_at TEXT
);
CREATE TABLE IF NOT EXISTS certificates (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
type TEXT NOT NULL, -- letsencrypt|custom
domains TEXT NOT NULL, -- json array
challenge_type TEXT, -- http-01|dns-01
dns_provider TEXT,
cert_path TEXT,
key_path TEXT,
not_before TEXT,
not_after TEXT,
last_renewed_at TEXT,
last_error TEXT,
auto_renew INTEGER NOT NULL DEFAULT 1,
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
);
CREATE TABLE IF NOT EXISTS access_lists (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
default_allow INTEGER NOT NULL DEFAULT 0,
comments TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
);
CREATE TABLE IF NOT EXISTS access_rules (
id INTEGER PRIMARY KEY AUTOINCREMENT,
access_list_id INTEGER NOT NULL REFERENCES access_lists(id) ON DELETE CASCADE,
action TEXT NOT NULL, -- allow|deny
cidr TEXT NOT NULL,
priority INTEGER NOT NULL DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_access_rules_list ON access_rules(access_list_id);
CREATE TABLE IF NOT EXISTS access_list_users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
access_list_id INTEGER NOT NULL REFERENCES access_lists(id) ON DELETE CASCADE,
username TEXT NOT NULL,
password_hash TEXT NOT NULL,
UNIQUE(access_list_id, username)
);
CREATE TABLE IF NOT EXISTS proxy_hosts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
type TEXT NOT NULL DEFAULT 'proxy', -- proxy|redirect
listen_addr TEXT NOT NULL DEFAULT '',
forward_scheme TEXT NOT NULL DEFAULT 'http',
preserve_host_header INTEGER NOT NULL DEFAULT 0,
websocket_support INTEGER NOT NULL DEFAULT 1,
force_https INTEGER NOT NULL DEFAULT 0,
hsts_enabled INTEGER NOT NULL DEFAULT 0,
certificate_id INTEGER REFERENCES certificates(id) ON DELETE SET NULL,
access_list_id INTEGER REFERENCES access_lists(id) ON DELETE SET NULL,
connect_timeout_ms INTEGER NOT NULL DEFAULT 5000,
read_timeout_ms INTEGER NOT NULL DEFAULT 60000,
write_timeout_ms INTEGER NOT NULL DEFAULT 60000,
idle_timeout_ms INTEGER NOT NULL DEFAULT 120000,
load_balancing_method TEXT NOT NULL DEFAULT 'round_robin',
redirect_target_url TEXT NOT NULL DEFAULT '',
redirect_code INTEGER NOT NULL DEFAULT 301,
redirect_preserve_path INTEGER NOT NULL DEFAULT 1,
redirect_preserve_qs INTEGER NOT NULL DEFAULT 1,
enabled INTEGER NOT NULL DEFAULT 1,
comments TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
);
CREATE TABLE IF NOT EXISTS proxy_host_domains (
id INTEGER PRIMARY KEY AUTOINCREMENT,
proxy_host_id INTEGER NOT NULL REFERENCES proxy_hosts(id) ON DELETE CASCADE,
domain TEXT NOT NULL COLLATE NOCASE,
UNIQUE(domain)
);
CREATE INDEX IF NOT EXISTS idx_phd_host ON proxy_host_domains(proxy_host_id);
CREATE INDEX IF NOT EXISTS idx_phd_domain ON proxy_host_domains(domain);
CREATE TABLE IF NOT EXISTS backends (
id INTEGER PRIMARY KEY AUTOINCREMENT,
proxy_host_id INTEGER NOT NULL REFERENCES proxy_hosts(id) ON DELETE CASCADE,
host TEXT NOT NULL,
port INTEGER NOT NULL,
weight INTEGER NOT NULL DEFAULT 1,
enabled INTEGER NOT NULL DEFAULT 1,
health_check_type TEXT NOT NULL DEFAULT 'tcp', -- tcp|http|none
health_check_path TEXT NOT NULL DEFAULT '/',
health_check_status INTEGER NOT NULL DEFAULT 200,
interval_seconds INTEGER NOT NULL DEFAULT 10,
failure_threshold INTEGER NOT NULL DEFAULT 3,
recovery_threshold INTEGER NOT NULL DEFAULT 2
);
CREATE INDEX IF NOT EXISTS idx_backends_host ON backends(proxy_host_id);
CREATE TABLE IF NOT EXISTS custom_headers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
proxy_host_id INTEGER NOT NULL REFERENCES proxy_hosts(id) ON DELETE CASCADE,
direction TEXT NOT NULL, -- request|response
action TEXT NOT NULL, -- set|remove
name TEXT NOT NULL,
value TEXT NOT NULL DEFAULT ''
);
CREATE INDEX IF NOT EXISTS idx_headers_host ON custom_headers(proxy_host_id);
CREATE TABLE IF NOT EXISTS streams (
id INTEGER PRIMARY KEY AUTOINCREMENT,
protocol TEXT NOT NULL, -- tcp|udp
listen_ip TEXT NOT NULL DEFAULT '',
listen_port INTEGER NOT NULL,
destination_host TEXT NOT NULL,
destination_port INTEGER NOT NULL,
connect_timeout_ms INTEGER NOT NULL DEFAULT 5000,
idle_timeout_ms INTEGER NOT NULL DEFAULT 300000,
proxy_protocol INTEGER NOT NULL DEFAULT 0,
enabled INTEGER NOT NULL DEFAULT 1,
comments TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
UNIQUE(protocol, listen_ip, listen_port)
);
CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS request_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL,
proxy_host_id INTEGER,
proxy_host_name TEXT NOT NULL DEFAULT '',
client_ip TEXT NOT NULL DEFAULT '',
method TEXT NOT NULL DEFAULT '',
host TEXT NOT NULL DEFAULT '',
path TEXT NOT NULL DEFAULT '',
status INTEGER NOT NULL DEFAULT 0,
response_size INTEGER NOT NULL DEFAULT 0,
backend TEXT NOT NULL DEFAULT '',
response_time_ms INTEGER NOT NULL DEFAULT 0,
user_agent TEXT NOT NULL DEFAULT ''
);
CREATE INDEX IF NOT EXISTS idx_logs_ts ON request_logs(timestamp);
CREATE INDEX IF NOT EXISTS idx_logs_host ON request_logs(proxy_host_id);
CREATE INDEX IF NOT EXISTS idx_logs_status ON request_logs(status);
CREATE TABLE IF NOT EXISTS audit_logs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
actor TEXT NOT NULL DEFAULT '',
action TEXT NOT NULL,
target TEXT NOT NULL DEFAULT '',
details TEXT NOT NULL DEFAULT ''
);
CREATE INDEX IF NOT EXISTS idx_audit_ts ON audit_logs(timestamp);