# Deployment Layout

## Services

- `postgres`
  - primary relational database
- `backend`
  - Go API and migration runner
- `admin-web`
  - static React admin UI served by nginx
- `gateway`
  - WireGuard plus nftables helper container or host-managed service
- `reverse-proxy`
  - TLS termination and routing

## Docker Compose Networks

- `control`
  - backend, postgres, admin-web, reverse-proxy
- `gateway`
  - backend and gateway helper communication

## Volume Layout

- postgres data volume
- backend local state volume for dev logs if needed
- gateway config volume for rendered peer sync

## Bootstrap

1. Start PostgreSQL.
2. Run migrations.
3. Start the backend.
4. Seed roles, settings, and the initial admin user.
5. Start the admin UI and reverse proxy.
6. Register the first gateway.

## Example Commands

```bash
cd deploy
cp .env.example .env
docker compose up -d postgres
docker compose up -d backend admin-web reverse-proxy
```

For SQL bootstrap during early MVP testing:

```bash
psql "$DATABASE_URL" -f backend/migrations/000001_init.sql
psql "$DATABASE_URL" -f backend/seed/001_seed.sql
```

## Gateway Helper Flow

1. Bootstrap an admin and log into the web UI.
2. Open the `Gateways` page and note the gateway ID.
3. Obtain an admin API token through the login flow.
4. Set `NEXAVPN_GATEWAY_ID` and `NEXAVPN_API_TOKEN` in `deploy/.env`.
5. Recreate the `gateway` service.

The helper writes:

- `/var/lib/nexavpn/sync-bundle.json`
- `/var/lib/nexavpn/wg0.generated.conf`
- `/var/lib/nexavpn/nftables.generated.conf`

Current behavior:

- the gateway helper fetches the sync bundle every 15 seconds
- it renders `/etc/wireguard/<iface>.conf`
- it applies nftables rules from generated state
- it enables IPv4 forwarding
- it brings up or resyncs the WireGuard interface

Required environment:

- `NEXAVPN_GATEWAY_ID`
- `NEXAVPN_API_TOKEN`
- `NEXAVPN_GATEWAY_PRIVATE_KEY`
- optional: `NEXAVPN_GATEWAY_INTERFACE`
- optional: `NEXAVPN_UPLINK_INTERFACE`
- optional: `NEXAVPN_ENABLE_MASQUERADE`

Helper scripts:

- `deploy/scripts/generate-gateway-keypair.sh`
- `deploy/scripts/get-admin-token.sh`

Host/runtime note:

- the gateway container expects `/dev/net/tun`
- the host kernel must support WireGuard

## Production Notes

- Terminate TLS at nginx or another reverse proxy.
- Restrict backend and database exposure to private networks.
- Run the gateway with the privileges required for WireGuard and nftables.
- Replace example secrets before deployment.
- Use an external secret manager when available.
