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
178 lines
7.6 KiB
SQL
178 lines
7.6 KiB
SQL
-- 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);
|