diff --git a/.sisyphus/plans/nxg-phase6-desktop-client.md b/.sisyphus/plans/archived/nxg-phase6-desktop-client.md similarity index 100% rename from .sisyphus/plans/nxg-phase6-desktop-client.md rename to .sisyphus/plans/archived/nxg-phase6-desktop-client.md diff --git a/.sisyphus/plans/nexusguard-config-architecture.md b/.sisyphus/plans/nexusguard-config-architecture.md index f930eb3..160e8c7 100644 --- a/.sisyphus/plans/nexusguard-config-architecture.md +++ b/.sisyphus/plans/nexusguard-config-architecture.md @@ -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) diff --git a/.sisyphus/plans/realtime-traffic-monitoring.md b/.sisyphus/plans/realtime-traffic-monitoring.md index 4842300..70db771 100644 --- a/.sisyphus/plans/realtime-traffic-monitoring.md +++ b/.sisyphus/plans/realtime-traffic-monitoring.md @@ -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 diff --git a/AGENTS.md b/AGENTS.md index 5d47c63..c1a8c33 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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 diff --git a/README.md b/README.md index 7e9706d..6b3321c 100644 --- a/README.md +++ b/README.md @@ -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 "" ``` 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 +``` diff --git a/apps/dashboard-ui b/apps/dashboard-ui index 9f7985a..bbd4f48 160000 --- a/apps/dashboard-ui +++ b/apps/dashboard-ui @@ -1 +1 @@ -Subproject commit 9f7985a9d45725385670fea74ca264434ae69062 +Subproject commit bbd4f483f4fca4c8f011ac992fb2b07520618c36 diff --git a/apps/server-core b/apps/server-core index 70b81b8..f7eaecc 160000 --- a/apps/server-core +++ b/apps/server-core @@ -1 +1 @@ -Subproject commit 70b81b8aab9ef63e6c7a390f913bdbe738825b6f +Subproject commit f7eaecc00b2114655ff91ba37f2d11d9adf5f68b diff --git a/nexusguard-install.sh b/nexusguard-install.sh index ad88c9e..e81ae1d 100644 --- a/nexusguard-install.sh +++ b/nexusguard-install.sh @@ -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 '' ''; + # Inject runtime config into HTML responses + sub_filter '' ''; 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!'" diff --git a/nexusguard-uninstall.sh b/nexusguard-uninstall.sh index 6686f77..cebc46e 100644 --- a/nexusguard-uninstall.sh +++ b/nexusguard-uninstall.sh @@ -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 diff --git a/setup.sh b/setup.sh index e80afde..94092c1 100755 --- a/setup.sh +++ b/setup.sh @@ -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."