Add monorepo structure for NexaVPN WireGuard control plane including: - .gitignore for node_modules, build artifacts, and environment files - README with project overview, monorepo layout, and quick start guide - Admin web UI with React, Vite, TypeScript, and nginx reverse proxy - API client with type definitions for users, devices, policies, gateways, and audit logs - Admin pages for dashboard, users, devices, policies, g
5.6 KiB
5.6 KiB
PostgreSQL Schema
Core Tables
roles
id uuid primary keyname text unique not nulldescription text not null default ''created_at timestamptz not null default now()updated_at timestamptz not null default now()
users
id uuid primary keyrole_id uuid not null references roles(id)username citext unique not nulldisplay_name text not nullemail citext uniquepassword_hash text not nullis_active boolean not null default truelast_login_at timestamptzcreated_at timestamptz not null default now()updated_at timestamptz not null default now()deleted_at timestamptz
sessions
id uuid primary keyuser_id uuid not null references users(id)ip_address inetuser_agent textlast_seen_at timestamptz not null default now()expires_at timestamptz not nullcreated_at timestamptz not null default now()revoked_at timestamptz
refresh_tokens
id uuid primary keysession_id uuid not null references sessions(id)user_id uuid not null references users(id)token_hash text not nullexpires_at timestamptz not nullcreated_at timestamptz not null default now()revoked_at timestamptz
gateways
id uuid primary keyname text unique not nullendpoint text not nullpublic_key text not nulllisten_port integer not nullvpn_cidr cidr not nulldns_servers text[] not null default '{}'is_active boolean not null default truelast_sync_at timestamptzcreated_at timestamptz not null default now()updated_at timestamptz not null default now()deleted_at timestamptz
devices
id uuid primary keyuser_id uuid not null references users(id)gateway_id uuid references gateways(id)name text not nullplatform text not nullos_version text not null default ''app_version text not null default ''device_fingerprint text not nullpublic_key text not nullstatus text not null default 'active'last_seen_at timestamptzlast_connected_at timestamptzapproved_at timestamptzrevoked_at timestamptzcreated_at timestamptz not null default now()updated_at timestamptz not null default now()deleted_at timestamptz
Unique index:
(user_id, device_fingerprint)wheredeleted_at is null
wireguard_peers
id uuid primary keydevice_id uuid not null references devices(id)gateway_id uuid not null references gateways(id)public_key text unique not nullassigned_ip inet not nullpreshared_key_ciphertext textallowed_ips cidr[] not null default '{}'dns_servers text[] not null default '{}'profile_revision integer not null default 1last_profile_issued_at timestamptzcreated_at timestamptz not null default now()updated_at timestamptz not null default now()deleted_at timestamptz
ip_allocations
id uuid primary keygateway_id uuid not null references gateways(id)device_id uuid references devices(id)address inet not nullstatus text not null default 'allocated'allocated_at timestamptz not null default now()released_at timestamptzcreated_at timestamptz not null default now()updated_at timestamptz not null default now()
Unique indexes:
(gateway_id, address)(device_id)wherestatus = 'allocated'
policies
id uuid primary keyname text unique not nulldescription text not null default ''priority integer not null default 100effect text not null default 'allow'is_active boolean not null default truefull_tunnel boolean not null default falsecreated_by uuid references users(id)created_at timestamptz not null default now()updated_at timestamptz not null default now()deleted_at timestamptz
policy_targets
id uuid primary keypolicy_id uuid not null references policies(id)target_type text not nulltarget_id uuid not nullcreated_at timestamptz not null default now()
Target types:
userdevicegroup
policy_destinations
id uuid primary keypolicy_id uuid not null references policies(id)destination cidr not nulldescription text not null default ''created_at timestamptz not null default now()
groups
id uuid primary keyname text unique not nulldescription text not null default ''created_at timestamptz not null default now()updated_at timestamptz not null default now()deleted_at timestamptz
group_memberships
id uuid primary keygroup_id uuid not null references groups(id)user_id uuid not null references users(id)created_at timestamptz not null default now()
audit_logs
id uuid primary keyactor_user_id uuid references users(id)actor_device_id uuid references devices(id)event_type text not nullentity_type text not nullentity_id uuidstatus text not nullip_address inetmessage text not nullmetadata jsonb not null default '{}'::jsonbcreated_at timestamptz not null default now()
settings
id uuid primary keycategory text not nullkey text not nullvalue jsonb not nullcreated_at timestamptz not null default now()updated_at timestamptz not null default now()
Unique index:
(category, key)
Notes
- UUIDs are generated with
gen_random_uuid(). citextis used for case-insensitive usernames and emails.- Soft deletes are enabled where historical traceability matters.
- Group tables are included now so policy resolution can grow without a destructive migration later.