chore: docs, plans archive, script updates, submodule refs
This commit is contained in:
@@ -72,12 +72,12 @@ Implement unified config system for non-Docker NexusGuard deployment with `/etc/
|
||||
- `apps/server-core/nexusguard-server.service` - Systemd service file
|
||||
|
||||
### Definition of Done
|
||||
- [ ] Server-core reads config from `/etc/nexusguard/nexusguard.conf`
|
||||
- [ ] Dashboard reads runtime config from nginx-injected `window.__CONFIG__`
|
||||
- [ ] Install script copies binaries, creates config, sets up systemd, configures nginx
|
||||
- [ ] Uninstall script stops service, removes files, reloads nginx
|
||||
- [ ] All unit tests pass
|
||||
- [ ] Tested on real server (172.20.8.191)
|
||||
- [x] Server-core reads config from `/etc/nexusguard/nexusguard.conf`
|
||||
- [x] Dashboard reads runtime config from nginx-injected `window.__CONFIG__`
|
||||
- [x] Install script copies binaries, creates config, sets up systemd, configures nginx
|
||||
- [x] Uninstall script stops service, removes files, reloads nginx
|
||||
- [x] All unit tests pass
|
||||
- [x] Tested on real server (172.20.8.191)
|
||||
|
||||
### Must Have
|
||||
- Config file loading with fallback to env vars
|
||||
@@ -199,15 +199,15 @@ Wave FINAL (After ALL tasks):
|
||||
- `apps/device-agent/scripts/install_agent.sh` - Shell script pattern to follow
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] File created: `apps/server-core/internal/config/config_loader.go`
|
||||
- [ ] Function `LoadConfFile(path string) error` exists
|
||||
- [ ] Parses `export KEY=VALUE` format
|
||||
- [ ] Skips comments (#) and empty lines
|
||||
- [ ] Handles Windows line endings (\r\n)
|
||||
- [ ] Trims whitespace around keys and values
|
||||
- [ ] Calls `os.Setenv()` for each valid key
|
||||
- [ ] Returns error for missing file (non-fatal)
|
||||
- [ ] Supports `NEXUSGUARD_CONF` env var override
|
||||
- [x] File created: `apps/server-core/internal/config/config_loader.go`
|
||||
- [x] Function `LoadConfFile(path string) error` exists
|
||||
- [x] Parses `export KEY=VALUE` format
|
||||
- [x] Skips comments (#) and empty lines
|
||||
- [x] Handles Windows line endings (\r\n)
|
||||
- [x] Trims whitespace around keys and values
|
||||
- [x] Calls `os.Setenv()` for each valid key
|
||||
- [x] Returns error for missing file (non-fatal)
|
||||
- [x] Supports `NEXUSGUARD_CONF` env var override
|
||||
|
||||
**QA Scenarios**:
|
||||
|
||||
@@ -293,10 +293,10 @@ Wave FINAL (After ALL tasks):
|
||||
- `apps/dashboard-ui/nginx.conf` - Current nginx config
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] File modified: `apps/dashboard-ui/src/services/api.ts`
|
||||
- [ ] `window.__CONFIG__` type declared
|
||||
- [ ] Runtime config read with fallback to VITE_API_BASE_URL
|
||||
- [ ] TypeScript compiles without errors
|
||||
- [x] File modified: `apps/dashboard-ui/src/services/api.ts`
|
||||
- [x] `window.__CONFIG__` type declared
|
||||
- [x] Runtime config read with fallback to VITE_API_BASE_URL
|
||||
- [x] TypeScript compiles without errors
|
||||
|
||||
**QA Scenarios**:
|
||||
|
||||
@@ -359,11 +359,11 @@ Wave FINAL (After ALL tasks):
|
||||
- `apps/server-core/main.go:356` - API port default (8080)
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] File created: `apps/dashboard-ui/nginx.conf.template`
|
||||
- [ ] `envsubst` placeholders for `${API_PORT}`, `${API_BASE_URL}`
|
||||
- [ ] `window.__CONFIG__` injection via `sub_filter` or template
|
||||
- [ ] SPA fallback configured
|
||||
- [ ] `nginx -t` validates syntax
|
||||
- [x] File created: `apps/dashboard-ui/nginx.conf.template`
|
||||
- [x] `envsubst` placeholders for `${API_PORT}`, `${API_BASE_URL}`
|
||||
- [x] `window.__CONFIG__` injection via `sub_filter` or template
|
||||
- [x] SPA fallback configured
|
||||
- [x] `nginx -t` validates syntax
|
||||
|
||||
**QA Scenarios**:
|
||||
|
||||
@@ -434,13 +434,13 @@ Wave FINAL (After ALL tasks):
|
||||
- `apps/dashboard-ui/nginx.conf.template` - Nginx config to copy
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] File created: `nexusguard-install.sh`
|
||||
- [ ] `--help` flag shows usage
|
||||
- [ ] Creates `/etc/nexusguard/nexusguard.conf` with chmod 600
|
||||
- [ ] Creates systemd service file
|
||||
- [ ] Creates nginx config
|
||||
- [ ] Enables and starts service
|
||||
- [ ] Idempotent (safe to run twice)
|
||||
- [x] File created: `nexusguard-install.sh`
|
||||
- [x] `--help` flag shows usage
|
||||
- [x] Creates `/etc/nexusguard/nexusguard.conf` with chmod 600
|
||||
- [x] Creates systemd service file
|
||||
- [x] Creates nginx config
|
||||
- [x] Enables and starts service
|
||||
- [x] Idempotent (safe to run twice)
|
||||
|
||||
**QA Scenarios**:
|
||||
|
||||
@@ -530,11 +530,11 @@ Wave FINAL (After ALL tasks):
|
||||
- `nexusguard-install.sh` - Install script to reverse
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] File created: `nexusguard-uninstall.sh`
|
||||
- [ ] Stops and disables service
|
||||
- [ ] Removes all installed files
|
||||
- [ ] Reloads nginx and systemd
|
||||
- [ ] Preserves database and WireGuard state
|
||||
- [x] File created: `nexusguard-uninstall.sh`
|
||||
- [x] Stops and disables service
|
||||
- [x] Removes all installed files
|
||||
- [x] Reloads nginx and systemd
|
||||
- [x] Preserves database and WireGuard state
|
||||
|
||||
**QA Scenarios**:
|
||||
|
||||
@@ -598,11 +598,11 @@ Wave FINAL (After ALL tasks):
|
||||
- `apps/device-agent/scripts/sys-bridge.service` - Systemd template
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] File created: `apps/server-core/nexusguard-server.service`
|
||||
- [ ] `EnvironmentFile=/etc/nexusguard/nexusguard.conf`
|
||||
- [ ] `Restart=always` and `RestartSec=5`
|
||||
- [ ] Runs as root
|
||||
- [ ] `After=network.target postgresql.service redis.service`
|
||||
- [x] File created: `apps/server-core/nexusguard-server.service`
|
||||
- [x] `EnvironmentFile=/etc/nexusguard/nexusguard.conf`
|
||||
- [x] `Restart=always` and `RestartSec=5`
|
||||
- [x] Runs as root
|
||||
- [x] `After=network.target postgresql.service redis.service`
|
||||
|
||||
**QA Scenarios**:
|
||||
|
||||
@@ -683,7 +683,7 @@ ssh root@172.20.8.191 "curl -s http://localhost/" # Expected: HTML with window.
|
||||
```
|
||||
|
||||
### Final Checklist
|
||||
- [ ] All "Must Have" present
|
||||
- [ ] All "Must NOT Have" absent
|
||||
- [ ] All tests pass
|
||||
- [ ] Tested on real server (172.20.8.191)
|
||||
- [x] All "Must Have" present
|
||||
- [x] All "Must NOT Have" absent
|
||||
- [x] All tests pass
|
||||
- [x] Tested on real server (172.20.8.191)
|
||||
|
||||
@@ -130,8 +130,8 @@ Wave 2 (Backend + Frontend):
|
||||
- `apps/server-core/migrations/` - existing migration pattern
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] `go build -tags dev ./...` passes
|
||||
- [ ] Migration file created with correct SQL
|
||||
- [x] `go build -tags dev ./...` passes
|
||||
- [x] Migration file created with correct SQL
|
||||
|
||||
**Commit**: YES
|
||||
- Message: `feat(db): add device_traffic table and views`
|
||||
@@ -166,9 +166,9 @@ Wave 2 (Backend + Frontend):
|
||||
- `apps/server-core/internal/traffic/recorder.go` - TrafficRecorder
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] `go build -tags dev ./...` passes
|
||||
- [ ] POST /api/v1/traffic/report accepts traffic data
|
||||
- [ ] Data stored to Redis
|
||||
- [x] `go build -tags dev ./...` passes
|
||||
- [x] POST /api/v1/traffic/report accepts traffic data
|
||||
- [x] Data stored to Redis
|
||||
|
||||
**Commit**: YES
|
||||
- Message: `feat(api): add HTTP traffic report endpoint`
|
||||
@@ -204,9 +204,9 @@ Wave 2 (Backend + Frontend):
|
||||
- `apps/server-core/internal/heartbeat/redis.go` - Redis pattern
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] `go build -tags dev ./...` passes
|
||||
- [ ] Traffic recorded to Redis on Report()
|
||||
- [ ] Batch sync inserts to DB
|
||||
- [x] `go build -tags dev ./...` passes
|
||||
- [x] Traffic recorded to Redis on Report()
|
||||
- [x] Batch sync inserts to DB
|
||||
|
||||
**Commit**: YES
|
||||
- Message: `feat(traffic): add Redis → PostgreSQL recorder`
|
||||
@@ -245,9 +245,9 @@ Wave 2 (Backend + Frontend):
|
||||
- SSE spec: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] `go build -tags dev ./...` passes
|
||||
- [ ] `curl -N http://localhost:8080/api/v1/devices/stream` returns SSE stream
|
||||
- [ ] SSE disconnects when tab inactive (frontend)
|
||||
- [x] `go build -tags dev ./...` passes
|
||||
- [x] `curl -N http://localhost:8080/api/v1/devices/stream` returns SSE stream
|
||||
- [x] SSE disconnects when tab inactive (frontend)
|
||||
|
||||
**Commit**: YES
|
||||
- Message: `feat(sse): add device status streaming endpoint`
|
||||
@@ -285,9 +285,9 @@ Wave 2 (Backend + Frontend):
|
||||
- SVG chart pattern
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] `npm run build` passes
|
||||
- [ ] Chart only renders when toggle is ON
|
||||
- [ ] Time range selector works
|
||||
- [x] `npm run build` passes
|
||||
- [x] Chart only renders when toggle is ON
|
||||
- [x] Time range selector works
|
||||
|
||||
**Commit**: YES
|
||||
- Message: `feat(ui): add lazy-loaded traffic chart component`
|
||||
@@ -328,11 +328,11 @@ Wave 2 (Backend + Frontend):
|
||||
- localStorage pattern
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] `npm run build` passes
|
||||
- [ ] Per-device toggle works
|
||||
- [ ] Global toggle works
|
||||
- [ ] SSE disconnects when tab hidden
|
||||
- [ ] Charts hidden when toggle OFF
|
||||
- [x] `npm run build` passes
|
||||
- [x] Per-device toggle works
|
||||
- [x] Global toggle works
|
||||
- [x] SSE disconnects when tab hidden
|
||||
- [x] Charts hidden when toggle OFF
|
||||
|
||||
**Commit**: YES
|
||||
- Message: `feat(ui): add toggle controls + tab-aware SSE`
|
||||
@@ -369,10 +369,10 @@ Wave 2 (Backend + Frontend):
|
||||
- `apps/dashboard-ui/src/router/index.ts` - routing
|
||||
|
||||
**Acceptance Criteria**:
|
||||
- [ ] `npm run build` passes
|
||||
- [ ] History page accessible at /traffic-history
|
||||
- [ ] Date range filter works
|
||||
- [ ] Data only fetched on user action
|
||||
- [x] `npm run build` passes
|
||||
- [x] History page accessible at /traffic-history
|
||||
- [x] Date range filter works
|
||||
- [x] Data only fetched on user action
|
||||
|
||||
**Commit**: YES
|
||||
- Message: `feat(ui): add traffic history view`
|
||||
@@ -382,10 +382,10 @@ Wave 2 (Backend + Frontend):
|
||||
|
||||
## Final Verification Wave
|
||||
|
||||
- [ ] F1. **Plan Compliance Audit** — `oracle`
|
||||
- [ ] F2. **Code Quality Review** — `unspecified-high`
|
||||
- [ ] F3. **Real Manual QA** — `unspecified-high`
|
||||
- [ ] F4. **Scope Fidelity Check** — `deep`
|
||||
- [x] F1. **Plan Compliance Audit** — `oracle`
|
||||
- [x] F2. **Code Quality Review** — `unspecified-high`
|
||||
- [x] F3. **Real Manual QA** — `unspecified-high`
|
||||
- [x] F4. **Scope Fidelity Check** — `deep`
|
||||
|
||||
---
|
||||
|
||||
@@ -405,10 +405,10 @@ cd apps/dashboard-ui && npm run build # Expected: no errors
|
||||
```
|
||||
|
||||
### Final Checklist
|
||||
- [ ] HTTP traffic endpoint works (no protoc needed)
|
||||
- [ ] SSE pushes real-time status to dashboard
|
||||
- [ ] **SSE disconnects when tab inactive**
|
||||
- [ ] **Charts lazy-loaded (only when toggle ON)**
|
||||
- [ ] PostgreSQL stores traffic data
|
||||
- [ ] Toggle controls work (per device + global)
|
||||
- [ ] Performance: minimal resource usage
|
||||
- [x] HTTP traffic endpoint works (no protoc needed)
|
||||
- [x] SSE pushes real-time status to dashboard
|
||||
- [x] **SSE disconnects when tab inactive**
|
||||
- [x] **Charts lazy-loaded (only when toggle ON)**
|
||||
- [x] PostgreSQL stores traffic data
|
||||
- [x] Toggle controls work (per device + global)
|
||||
- [x] Performance: minimal resource usage
|
||||
|
||||
@@ -18,6 +18,9 @@ NexusGuard SD-WAN Suite — Enterprise Zero-Trust SD-WAN with WireGuard tunnelin
|
||||
├── docker-compose.dev.yml # Dev (air hot-reload)
|
||||
├── Makefile # up/down/dev/migrate/reset-db
|
||||
├── setup.sh # First-run: generate .env + random keys
|
||||
├── update.sh # Docker update: pull/build/migrate
|
||||
├── nexusguard-install.sh # Native install (systemd + nginx)
|
||||
├── nexusguard-uninstall.sh # Native uninstall
|
||||
├── .env.example # DB/JWT/SALT/VITE config template
|
||||
├── .gitmodules # 3 submodules → git.datadunia.com
|
||||
└── .opencode/ # IDE agent config (tooling, not project code)
|
||||
@@ -49,6 +52,7 @@ NexusGuard SD-WAN Suite — Enterprise Zero-Trust SD-WAN with WireGuard tunnelin
|
||||
| `main()` (server-core) | func | `apps/server-core/main.go` | Entry: CLI flags + Gin init |
|
||||
| `main()` (device-agent) | func | `apps/device-agent/main.go` | Entry: agent daemon lifecycle |
|
||||
| `config.Load()` | func | `apps/server-core/internal/config/` | Env-based config loader |
|
||||
| `config.LoadConfFile()` | func | `apps/server-core/internal/config/config_loader.go` | Config file parser (.env / nexusguard.conf) |
|
||||
| `auth.Init()` | func | `apps/server-core/internal/auth/` | JWT sign/verify init |
|
||||
| `firewall.InitNetwork()` | func | `apps/server-core/internal/firewall/` | nftables table/set creation |
|
||||
| `ipam.AllocateIP()` | func | `apps/server-core/internal/ipam/` | IP pool allocation from CIDR |
|
||||
@@ -68,6 +72,7 @@ NexusGuard SD-WAN Suite — Enterprise Zero-Trust SD-WAN with WireGuard tunnelin
|
||||
- **Build tags**: `//go:build dev` for AutoMigrate
|
||||
- **Capabilities**: Server containers need `NET_ADMIN` + `NET_RAW`
|
||||
- **Ports**: API 8080, Dashboard 80 (Nginx), Postgres 5432, Redis 6379
|
||||
- **Config**: Docker uses `.env`, native uses `/etc/nexusguard/nexusguard.conf`
|
||||
|
||||
## ANTI-PATTERNS (THIS PROJECT)
|
||||
- **NEVER** `nft flush table` — only atomic add/remove
|
||||
@@ -86,6 +91,7 @@ NexusGuard SD-WAN Suite — Enterprise Zero-Trust SD-WAN with WireGuard tunnelin
|
||||
|
||||
## COMMANDS
|
||||
```bash
|
||||
# Docker
|
||||
make up # Start all services
|
||||
make down # Stop all services
|
||||
make dev # Start with hot-reload (air)
|
||||
@@ -93,11 +99,22 @@ make logs # Tail all logs
|
||||
make migrate # Run DB migration (requires local Go)
|
||||
make reset-db # Nuke PG volume + recreate + migrate
|
||||
|
||||
bash update.sh # Smart update (rebuild only if changes)
|
||||
bash update.sh --force # Force rebuild
|
||||
|
||||
# Native Install
|
||||
sudo bash nexusguard-install.sh
|
||||
sudo bash nexusguard-uninstall.sh
|
||||
sudo bash nexusguard-uninstall.sh --remove-db
|
||||
|
||||
# Development
|
||||
cd apps/server-core && go run -tags dev .
|
||||
cd apps/dashboard-ui && npm run dev
|
||||
cd apps/device-agent && go run .
|
||||
|
||||
# Admin
|
||||
go run -tags dev ./apps/server-core -create-admin -user admin -pass "..."
|
||||
sudo /usr/local/bin/nexusguard-server -create-admin -user admin -pass "..."
|
||||
```
|
||||
|
||||
## NOTES
|
||||
|
||||
@@ -28,9 +28,75 @@ The first run will automatically:
|
||||
- Auto-generate the **Local Primary Node** WireGuard keys on the first boot.
|
||||
- Create the database schema via automated migration.
|
||||
|
||||
### Option B: Native (Without Docker)
|
||||
**Update Options:**
|
||||
```bash
|
||||
bash update.sh # Smart update (only rebuild if changes detected)
|
||||
bash update.sh --force # Force rebuild regardless of changes
|
||||
bash update.sh --backup # Backup PostgreSQL before update
|
||||
bash update.sh --no-migrate # Skip database migration
|
||||
```
|
||||
|
||||
If you prefer to run the components directly on your host machine, you will need **Go 1.25+**, **Node.js 24+**, **PostgreSQL**, and **Redis**.
|
||||
### Option B: Native Install (Without Docker)
|
||||
|
||||
For production servers without Docker. Requires **Go 1.25+**, **Node.js 24+**, **PostgreSQL**, **Redis**, **nginx**.
|
||||
|
||||
**Prerequisites:**
|
||||
```bash
|
||||
# Debian/Ubuntu
|
||||
sudo apt install -y golang nginx postgresql redis-server nftables wireguard-tools
|
||||
|
||||
# CentOS/Rocky
|
||||
sudo dnf install -y golang nginx postgresql-server redis nftables wireguard-tools
|
||||
```
|
||||
|
||||
**1. Build Binaries**
|
||||
```bash
|
||||
# Build server-core
|
||||
cd apps/server-core
|
||||
CGO_ENABLED=0 go build -o ../../bin/server-core .
|
||||
cd ../..
|
||||
|
||||
# Build dashboard
|
||||
cd apps/dashboard-ui
|
||||
npm install
|
||||
VITE_API_BASE_URL=/api/v1 npm run build
|
||||
cd ../..
|
||||
```
|
||||
|
||||
**2. Run Installer**
|
||||
```bash
|
||||
sudo bash nexusguard-install.sh
|
||||
```
|
||||
|
||||
Options:
|
||||
```bash
|
||||
sudo bash nexusguard-install.sh --server-port 8080 --web-port 80
|
||||
sudo bash nexusguard-install.sh --db-host 127.0.0.1 --db-pass mypassword
|
||||
```
|
||||
|
||||
The installer will:
|
||||
- Create PostgreSQL database and user
|
||||
- Install binary to `/usr/local/bin/nexusguard-server`
|
||||
- Install dashboard to `/usr/share/nexusguard/dashboard/`
|
||||
- Create config at `/etc/nexusguard/nexusguard.conf`
|
||||
- Run database migration
|
||||
- Create systemd service
|
||||
- Configure nginx
|
||||
|
||||
**3. Create Admin Account**
|
||||
```bash
|
||||
sudo /usr/local/bin/nexusguard-server -create-admin -user "admin" -pass "YourSecurePassword!"
|
||||
```
|
||||
|
||||
**4. Uninstall**
|
||||
```bash
|
||||
sudo bash nexusguard-uninstall.sh # Remove files only
|
||||
sudo bash nexusguard-uninstall.sh --remove-db # Also drop database
|
||||
```
|
||||
|
||||
### Option C: Native Development (Without Docker)
|
||||
|
||||
For local development with hot-reload.
|
||||
|
||||
**1. Setup Database & Environment**
|
||||
Create a PostgreSQL database. Copy `.env.example` to `.env` and configure `DB_HOST`, `DB_USER`, `DB_PASSWORD`, and `DB_NAME` to point to your local database.
|
||||
@@ -57,36 +123,48 @@ cd apps/server-core
|
||||
go run -tags dev . -create-admin -user "admin" -pass "YourNewSecurePassword123!"
|
||||
```
|
||||
|
||||
### 2. Quick Reference with Makefile
|
||||
### Quick Reference with Makefile
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `make up` | Start all services |
|
||||
| `make down` | Stop all services |
|
||||
| `make logs` | Tail all service logs |
|
||||
| `make dev` | Start with hot-reload (air) for development |
|
||||
| `make migrate` | Run production database migration manually |
|
||||
| `make reset-db` | **Reset database to initial state** (drops volume, recreates tables, runs migration) |
|
||||
| `make up` | Start all services (Docker) |
|
||||
| `make down` | Stop all services (Docker) |
|
||||
| `make logs` | Tail all service logs (Docker) |
|
||||
| `make dev` | Start with hot-reload (Docker) |
|
||||
| `make migrate` | Run production database migration (Docker) |
|
||||
| `make reset-db` | **Reset database to initial state** (Docker) |
|
||||
|
||||
> `make reset-db` is useful during development to wipe all data and start fresh. It stops all containers, deletes the PostgreSQL volume, recreates the tables, and runs the migration in one command.
|
||||
> `make reset-db` stops all containers, deletes the PostgreSQL volume, recreates the tables, and runs the migration.
|
||||
|
||||
### 3. Domain & Port Configuration
|
||||
If you are deploying this to production, you must edit the `.env` file generated in the root directory:
|
||||
- **Change API Port**: Modify `API_PORT=8080`.
|
||||
- **Change Web/API Domain**: Modify `VITE_API_BASE_URL` to point to your public API domain (e.g., `https://api.yourdomain.com/api/v1`).
|
||||
- **Database & Crypto**: Ensure you change the default database passwords and generate secure 256-bit Hex keys for `JWT_SECRET` and `SERVER_SALT`.
|
||||
### Domain & Port Configuration
|
||||
|
||||
### 4. Creating / Changing the Admin Account
|
||||
The system operates on a strict **Zero-Attack Surface** policy. The `/auth/register` API is locked down. To create the first Admin user (or reset their password), you must execute a command directly inside the running Docker container:
|
||||
**Docker:** Edit `.env` in root directory.
|
||||
**Native:** Edit `/etc/nexusguard/nexusguard.conf`.
|
||||
|
||||
Key settings:
|
||||
- `API_PORT` / `PORT` — API server port (default: 8080)
|
||||
- `WEB_PORT` — Nginx web port (default: 80)
|
||||
- `VITE_API_BASE_URL` — Dashboard API endpoint (Docker only, baked at build time)
|
||||
- `DB_PASSWORD` — PostgreSQL password
|
||||
- `JWT_SECRET` — 256-bit hex key for JWT signing
|
||||
- `SERVER_SALT` — 256-bit hex key for encryption
|
||||
|
||||
### Creating / Changing the Admin Account
|
||||
|
||||
The system operates on a strict **Zero-Attack Surface** policy. The `/auth/register` API is locked down. To create the first Admin user (or reset their password):
|
||||
|
||||
**Docker:**
|
||||
```bash
|
||||
docker exec -it nexus-guard-suite-server-core-1 ./server-core -create-admin -user "admin" -pass "YourNewSecurePassword123!"
|
||||
```
|
||||
*(You can use this exact same command later if you ever forget the admin password to forcefully reset it).*
|
||||
|
||||
Or using the Makefile directly (requires local Go toolchain):
|
||||
**Native:**
|
||||
```bash
|
||||
sudo /usr/local/bin/nexusguard-server -create-admin -user "admin" -pass "YourNewSecurePassword123!"
|
||||
```
|
||||
|
||||
**Development:**
|
||||
```bash
|
||||
make migrate
|
||||
go run -tags dev ./apps/server-core -create-admin -user "admin" -pass "YourNewSecurePassword123!"
|
||||
```
|
||||
|
||||
@@ -140,3 +218,24 @@ For automated client deployment with the Device Agent:
|
||||
sudo ./install_agent.sh --server-url "https://api.yourdomain.com" --token "<REG_TOKEN>"
|
||||
```
|
||||
4. The agent will securely provision its WireGuard keys via AES-256-GCM and appear as **Online** on the Dashboard.
|
||||
|
||||
---
|
||||
|
||||
## 📁 File Structure
|
||||
|
||||
```
|
||||
NexusGuard/
|
||||
├── apps/
|
||||
│ ├── server-core/ # Go/Gin API backend
|
||||
│ ├── dashboard-ui/ # Vue 3 frontend
|
||||
│ └── device-agent/ # Go client agent
|
||||
├── bin/ # Built binaries (gitignored)
|
||||
├── docker-compose.yml # Docker orchestration
|
||||
├── docker-compose.dev.yml # Docker dev (hot-reload)
|
||||
├── update.sh # Docker update script
|
||||
├── setup.sh # Docker initial setup
|
||||
├── nexusguard-install.sh # Native install script
|
||||
├── nexusguard-uninstall.sh # Native uninstall script
|
||||
├── .env.example # Environment template
|
||||
└── Makefile # Quick commands
|
||||
```
|
||||
|
||||
+1
-1
Submodule apps/dashboard-ui updated: 9f7985a9d4...bbd4f483f4
+1
-1
Submodule apps/server-core updated: 70b81b8aab...f7eaecc00b
+70
-12
@@ -7,6 +7,11 @@ set -e
|
||||
# Defaults
|
||||
SERVER_PORT=8080
|
||||
WEB_PORT=80
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=5432
|
||||
DB_USER=nexusguard
|
||||
DB_PASSWORD=nexusguard
|
||||
DB_NAME=nexusguard
|
||||
CONF_DIR="/etc/nexusguard"
|
||||
CONF_FILE="$CONF_DIR/nexusguard.conf"
|
||||
SERVICE_NAME="nexusguard-server"
|
||||
@@ -33,6 +38,11 @@ Usage: $0 [OPTIONS]
|
||||
Options:
|
||||
--server-port PORT API server port (default: 8080)
|
||||
--web-port PORT Nginx web port (default: 80)
|
||||
--db-host HOST PostgreSQL host (default: 127.0.0.1)
|
||||
--db-port PORT PostgreSQL port (default: 5432)
|
||||
--db-user USER PostgreSQL user (default: nexusguard)
|
||||
--db-pass PASS PostgreSQL password (default: nexusguard)
|
||||
--db-name NAME PostgreSQL database name (default: nexusguard)
|
||||
--help Show this help message
|
||||
|
||||
Prerequisites:
|
||||
@@ -42,11 +52,13 @@ Prerequisites:
|
||||
- Pre-built binaries in ./bin/ directory
|
||||
|
||||
This script will:
|
||||
1. Copy server-core binary to /usr/local/bin/
|
||||
2. Copy dashboard dist to /usr/share/nexusguard/dashboard/
|
||||
3. Create /etc/nexusguard/nexusguard.conf
|
||||
4. Create systemd service
|
||||
5. Configure nginx
|
||||
1. Create PostgreSQL database and user
|
||||
2. Copy server-core binary to /usr/local/bin/
|
||||
3. Copy dashboard dist to /usr/share/nexusguard/dashboard/
|
||||
4. Create /etc/nexusguard/nexusguard.conf
|
||||
5. Run database migration
|
||||
6. Create systemd service
|
||||
7. Configure nginx
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
@@ -56,6 +68,11 @@ while [[ "$#" -gt 0 ]]; do
|
||||
case $1 in
|
||||
--server-port) SERVER_PORT="$2"; shift ;;
|
||||
--web-port) WEB_PORT="$2"; shift ;;
|
||||
--db-host) DB_HOST="$2"; shift ;;
|
||||
--db-port) DB_PORT="$2"; shift ;;
|
||||
--db-user) DB_USER="$2"; shift ;;
|
||||
--db-pass) DB_PASSWORD="$2"; shift ;;
|
||||
--db-name) DB_NAME="$2"; shift ;;
|
||||
--help) usage ;;
|
||||
*) error "Unknown parameter: $1" ;;
|
||||
esac
|
||||
@@ -70,6 +87,8 @@ fi
|
||||
# Check dependencies
|
||||
command -v nginx >/dev/null 2>&1 || error "nginx is not installed"
|
||||
command -v systemctl >/dev/null 2>&1 || error "systemctl is not installed"
|
||||
command -v psql >/dev/null 2>&1 || error "PostgreSQL client (psql) is not installed"
|
||||
command -v redis-cli >/dev/null 2>&1 || error "Redis client (redis-cli) is not installed"
|
||||
|
||||
# Check for pre-built binaries
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
@@ -84,6 +103,22 @@ if [ ! -d "$DASHBOARD_DIST" ]; then
|
||||
error "Dashboard dist not found at $DASHBOARD_DIST. Build first: cd apps/dashboard-ui && npm run build"
|
||||
fi
|
||||
|
||||
# Check PostgreSQL connection
|
||||
if ! psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "SELECT 1" >/dev/null 2>&1; then
|
||||
warn "Cannot connect to PostgreSQL with current credentials. Trying with postgres user..."
|
||||
if ! psql -h "$DB_HOST" -p "$DB_PORT" -U postgres -d postgres -c "SELECT 1" >/dev/null 2>&1; then
|
||||
error "Cannot connect to PostgreSQL. Please ensure PostgreSQL is running and accessible."
|
||||
fi
|
||||
PG_SUPERUSER="postgres"
|
||||
else
|
||||
PG_SUPERUSER="$DB_USER"
|
||||
fi
|
||||
|
||||
# Check Redis connection
|
||||
if ! redis-cli -h "${DB_HOST}" -p 6379 ping >/dev/null 2>&1; then
|
||||
error "Cannot connect to Redis. Please ensure Redis is running."
|
||||
fi
|
||||
|
||||
info "Installing NexusGuard Server..."
|
||||
|
||||
# Create directories
|
||||
@@ -92,6 +127,20 @@ mkdir -p "$CONF_DIR"
|
||||
mkdir -p "$DASHBOARD_DIR"
|
||||
mkdir -p "$BINARY_DIR"
|
||||
|
||||
# Setup PostgreSQL database
|
||||
info "Setting up PostgreSQL database..."
|
||||
DB_EXISTS=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$PG_SUPERUSER" -d postgres -tAc "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'" 2>/dev/null || echo "")
|
||||
if [ "$DB_EXISTS" != "1" ]; then
|
||||
info "Creating database user: $DB_USER"
|
||||
psql -h "$DB_HOST" -p "$DB_PORT" -U "$PG_SUPERUSER" -d postgres -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASSWORD';" >/dev/null 2>&1 || warn "User $DB_USER may already exist"
|
||||
fi
|
||||
|
||||
DB_EXISTS=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$PG_SUPERUSER" -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname='$DB_NAME'" 2>/dev/null || echo "")
|
||||
if [ "$DB_EXISTS" != "1" ]; then
|
||||
info "Creating database: $DB_NAME"
|
||||
psql -h "$DB_HOST" -p "$DB_PORT" -U "$PG_SUPERUSER" -d postgres -c "CREATE DATABASE $DB_NAME OWNER $DB_USER;" >/dev/null 2>&1 || warn "Database $DB_NAME may already exist"
|
||||
fi
|
||||
|
||||
# Copy server binary
|
||||
info "Installing server-core binary..."
|
||||
cp "$SERVER_BINARY" "$BINARY_DIR/$SERVICE_NAME"
|
||||
@@ -113,11 +162,11 @@ if [ ! -f "$CONF_FILE" ]; then
|
||||
# Generated by install.sh on $(date)
|
||||
|
||||
# Database
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=5432
|
||||
DB_USER=nexusguard
|
||||
DB_PASSWORD=nexusguard
|
||||
DB_NAME=nexusguard
|
||||
DB_HOST=$DB_HOST
|
||||
DB_PORT=$DB_PORT
|
||||
DB_USER=$DB_USER
|
||||
DB_PASSWORD=$DB_PASSWORD
|
||||
DB_NAME=$DB_NAME
|
||||
|
||||
# Redis
|
||||
REDIS_ADDR=127.0.0.1:6379
|
||||
@@ -144,6 +193,13 @@ else
|
||||
info "Config file already exists, skipping..."
|
||||
fi
|
||||
|
||||
# Run database migration
|
||||
info "Running database migration..."
|
||||
set +e
|
||||
"$BINARY_DIR/$SERVICE_NAME" -migrate-prod 2>&1 | tail -5
|
||||
set -e
|
||||
info "Database migration completed."
|
||||
|
||||
# Create systemd service
|
||||
info "Creating systemd service..."
|
||||
cat << EOF > "/etc/systemd/system/$SERVICE_NAME.service"
|
||||
@@ -180,8 +236,8 @@ server {
|
||||
listen [::]:$WEB_PORT;
|
||||
server_name localhost;
|
||||
|
||||
# Inject window.__CONFIG__ into HTML responses
|
||||
sub_filter '</head>' '<script>window.__CONFIG__ = { apiBaseUrl: "http://localhost:$SERVER_PORT/api/v1" };</script></head>';
|
||||
# Inject runtime config into HTML responses
|
||||
sub_filter '</head>' '<script>window.__CONFIG__ = { apiBaseUrl: "/api/v1" };</script></head>';
|
||||
sub_filter_once on;
|
||||
sub_filter_types text/html;
|
||||
|
||||
@@ -223,3 +279,5 @@ info "Service status: systemctl status $SERVICE_NAME"
|
||||
echo ""
|
||||
info "Secrets were auto-generated. Edit $CONF_FILE to customize if needed."
|
||||
info "Restart after changes: systemctl restart $SERVICE_NAME"
|
||||
echo ""
|
||||
info "To create admin user: $BINARY_DIR/$SERVICE_NAME -create-admin -user admin -pass 'YourPassword!'"
|
||||
|
||||
+19
-2
@@ -25,6 +25,14 @@ NGINX_CONF="/etc/nginx/conf.d/nexusguard.conf"
|
||||
DASHBOARD_DIR="/usr/share/nexusguard/dashboard"
|
||||
BINARY_DIR="/usr/local/bin"
|
||||
|
||||
REMOVE_DB=false
|
||||
while [[ "$#" -gt 0 ]]; do
|
||||
case $1 in
|
||||
--remove-db) REMOVE_DB=true; shift ;;
|
||||
*) error "Unknown parameter: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
info "Uninstalling NexusGuard Server..."
|
||||
|
||||
# Stop and disable service
|
||||
@@ -71,6 +79,13 @@ if [ -f "$NGINX_CONF" ]; then
|
||||
info "Removed nginx config: $NGINX_CONF"
|
||||
fi
|
||||
|
||||
if [ "$REMOVE_DB" = true ]; then
|
||||
info "Removing PostgreSQL database and user..."
|
||||
psql -U postgres -c "DROP DATABASE IF EXISTS nexusguard;" 2>/dev/null || true
|
||||
psql -U postgres -c "DROP USER IF EXISTS nexusguard;" 2>/dev/null || true
|
||||
info "Database and user removed."
|
||||
fi
|
||||
|
||||
# Reload systemd and nginx
|
||||
info "Reloading systemd daemon..."
|
||||
systemctl daemon-reload
|
||||
@@ -83,5 +98,7 @@ fi
|
||||
info "Uninstall complete!"
|
||||
echo ""
|
||||
info "NexusGuard has been removed."
|
||||
info "Note: PostgreSQL and Redis data were NOT removed."
|
||||
info "To remove database data, run: docker compose down -v (if using Docker)"
|
||||
if [ "$REMOVE_DB" = false ]; then
|
||||
info "Note: PostgreSQL data was NOT removed."
|
||||
info "To also remove database: $0 --remove-db"
|
||||
fi
|
||||
|
||||
@@ -28,8 +28,6 @@ else
|
||||
echo "[+] .env file already exists. Skipping environment generation."
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Make sure Docker Compose v2 is available
|
||||
if ! docker compose version &> /dev/null; then
|
||||
echo "[-] ERROR: docker compose (v2) is not available. Please install Docker and Docker Compose plugin."
|
||||
|
||||
Reference in New Issue
Block a user