chore: initial project scaffold with admin web, backend, desktop client, and deployment setup

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
This commit is contained in:
2026-03-15 16:32:34 +01:00
commit 830491cb0d
91 changed files with 5279 additions and 0 deletions

14
deploy/.env.example Normal file
View File

@@ -0,0 +1,14 @@
POSTGRES_DB=nexavpn
POSTGRES_USER=nexavpn
POSTGRES_PASSWORD=change-me
DATABASE_URL=postgres://nexavpn:change-me@postgres:5432/nexavpn?sslmode=disable
HTTP_ADDRESS=:8080
APP_ENV=production
JWT_SECRET=replace-with-a-long-random-secret
JWT_ISSUER=nexavpn
ACCESS_TOKEN_TTL_SECONDS=900
REFRESH_TOKEN_TTL_SECONDS=2592000
DEFAULT_DNS_SERVERS=10.20.0.53
DEFAULT_VPN_CIDR=100.96.0.0/24
DEFAULT_GATEWAY_ENDPOINT=vpn.example.com:51820
DEFAULT_GATEWAY_PUBLIC_KEY=replace-me

72
deploy/docker-compose.yml Normal file
View File

@@ -0,0 +1,72 @@
services:
postgres:
image: postgres:17-alpine
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
ports:
- "5432:5432"
volumes:
- postgres-data:/var/lib/postgresql/data
- ../backend/migrations/000001_init.sql:/docker-entrypoint-initdb.d/010_init.sql:ro
- ../backend/seed/001_seed.sql:/docker-entrypoint-initdb.d/020_seed.sql:ro
networks:
- control
backend:
build:
context: ../backend
dockerfile: Dockerfile
env_file:
- .env
depends_on:
- postgres
ports:
- "8080:8080"
networks:
- control
- gateway
admin-web:
build:
context: ../admin-web
dockerfile: Dockerfile
depends_on:
- backend
ports:
- "8081:80"
networks:
- control
reverse-proxy:
image: nginx:1.27-alpine
depends_on:
- backend
- admin-web
ports:
- "80:80"
volumes:
- ./nginx/reverse-proxy.conf:/etc/nginx/conf.d/default.conf:ro
networks:
- control
gateway:
image: alpine:3.21
command: ["sh", "/scripts/gateway-entrypoint.sh"]
cap_add:
- NET_ADMIN
- SYS_MODULE
volumes:
- ./scripts/gateway-entrypoint.sh:/scripts/gateway-entrypoint.sh:ro
- gateway-state:/var/lib/nexavpn
networks:
- gateway
volumes:
postgres-data:
gateway-state:
networks:
control:
gateway:

10
deploy/nginx/admin.conf Normal file
View File

@@ -0,0 +1,10 @@
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri /index.html;
}
}

View File

@@ -0,0 +1,18 @@
server {
listen 80;
server_name _;
location /api/ {
proxy_pass http://backend:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
proxy_pass http://admin-web:80;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

View File

@@ -0,0 +1,9 @@
#!/bin/sh
set -eu
cat <<'EOF'
Bootstrap flow:
1. Run backend migrations from backend/migrations.
2. Seed roles and default settings from backend/seed/001_seed.sql.
3. Insert the first admin user with an Argon2id password hash generated by the backend auth package or a one-off helper.
EOF

View File

@@ -0,0 +1,8 @@
#!/bin/sh
set -eu
echo "NexaVPN gateway helper starting"
echo "This container is a placeholder for WireGuard + nftables sync logic."
echo "Mount generated gateway state into /var/lib/nexavpn and apply rules from there."
tail -f /dev/null