Replaced German text with English across the frontend UI for consistency and accessibility. Enhanced clarity in `.env.example` and `README.md`, adding detailed comments for environment variables and prerequisites. Improved documentation for setup, security, and troubleshooting.
177 lines
4.7 KiB
Markdown
177 lines
4.7 KiB
Markdown
# NexaPG - PostgreSQL Monitoring Stack
|
|
|
|
NexaPG is a Docker-based PostgreSQL monitoring platform for multiple remote targets, built with FastAPI + React.
|
|
|
|
## What it includes
|
|
|
|
- Multi-target PostgreSQL monitoring (remote instances)
|
|
- Polling collector for:
|
|
- `pg_stat_database`
|
|
- `pg_stat_activity`
|
|
- `pg_stat_bgwriter`
|
|
- `pg_locks`
|
|
- `pg_stat_statements` (if enabled on target)
|
|
- Core metadata database for:
|
|
- Authentication and RBAC (`admin`, `operator`, `viewer`)
|
|
- Monitored target configuration (encrypted credentials)
|
|
- Metrics and query stats
|
|
- Audit logs
|
|
- JWT auth (access + refresh)
|
|
- FastAPI + SQLAlchemy async + Alembic migrations
|
|
- React (Vite) frontend with:
|
|
- Login/logout
|
|
- Dashboard overview
|
|
- Target detail with charts and database overview
|
|
- Query insights
|
|
- Admin user management
|
|
- Health endpoints:
|
|
- `/api/v1/healthz`
|
|
- `/api/v1/readyz`
|
|
|
|
## Repository structure
|
|
|
|
- `backend/` FastAPI application
|
|
- `frontend/` React (Vite) application
|
|
- `ops/` helper scripts and env template copy
|
|
- `docker-compose.yml` full stack definition
|
|
- `.env.example` environment template
|
|
|
|
## Prerequisites
|
|
|
|
Install these before starting:
|
|
|
|
- Docker Engine 24+
|
|
- Docker Compose v2+
|
|
- GNU Make (optional, for `make up/down/logs/migrate`)
|
|
- Open ports on your host:
|
|
- frontend: `5173` (default)
|
|
- backend: `8000` (or your `BACKEND_PORT`)
|
|
- core DB: `5433` (or your `DB_PORT`)
|
|
|
|
Optional but recommended:
|
|
|
|
- `psql` client for troubleshooting target connectivity
|
|
|
|
## Quick start
|
|
|
|
1. Create local env file:
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
2. Generate an encryption key and set `ENCRYPTION_KEY` in `.env`:
|
|
|
|
```bash
|
|
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
|
|
```
|
|
|
|
3. Start services:
|
|
|
|
```bash
|
|
make up
|
|
```
|
|
|
|
4. Open:
|
|
|
|
- Frontend: `http://localhost:5173`
|
|
- Backend API: `http://localhost:8000/api/v1`
|
|
- OpenAPI docs: `http://localhost:8000/docs`
|
|
|
|
Default initial admin (from `.env`):
|
|
|
|
- Email: `admin@example.com`
|
|
- Password: `ChangeMe123!`
|
|
|
|
## Common commands
|
|
|
|
```bash
|
|
make up # build + start all services
|
|
make down # stop all services
|
|
make logs # follow logs
|
|
make migrate # run Alembic migrations in backend container
|
|
```
|
|
|
|
## Environment variables reference
|
|
|
|
All variables are defined in `.env.example`.
|
|
|
|
### Application
|
|
|
|
- `APP_NAME`: Display name used by backend/docs
|
|
- `ENVIRONMENT`: `dev | staging | prod | test`
|
|
- `LOG_LEVEL`: `DEBUG | INFO | WARNING | ERROR`
|
|
|
|
### Core database (internal)
|
|
|
|
- `DB_NAME`: Internal metadata DB name
|
|
- `DB_USER`: Internal metadata DB user
|
|
- `DB_PASSWORD`: Internal metadata DB password
|
|
- `DB_PORT`: Host port mapped to internal PostgreSQL `5432`
|
|
|
|
### Backend API
|
|
|
|
- `BACKEND_PORT`: Host port mapped to backend container `8000`
|
|
- `JWT_SECRET_KEY`: JWT signing key (must be changed)
|
|
- `JWT_ALGORITHM`: JWT algorithm (default `HS256`)
|
|
- `JWT_ACCESS_TOKEN_MINUTES`: access token lifetime
|
|
- `JWT_REFRESH_TOKEN_MINUTES`: refresh token lifetime
|
|
- `ENCRYPTION_KEY`: Fernet key for encrypting target passwords at rest
|
|
- `CORS_ORIGINS`: comma-separated allowed origins or `*` (dev-only)
|
|
- `POLL_INTERVAL_SECONDS`: collector polling interval
|
|
- `INIT_ADMIN_EMAIL`: bootstrap admin email
|
|
- `INIT_ADMIN_PASSWORD`: bootstrap admin password
|
|
|
|
### Frontend
|
|
|
|
- `FRONTEND_PORT`: Host port mapped to frontend container `80`
|
|
- `VITE_API_URL`: API base URL baked into frontend build
|
|
- Proxy/SSL setup: use `/api/v1`
|
|
- Direct local setup: use `http://localhost:8000/api/v1`
|
|
|
|
## API overview (minimum)
|
|
|
|
- Auth:
|
|
- `POST /api/v1/auth/login`
|
|
- `POST /api/v1/auth/refresh`
|
|
- `POST /api/v1/auth/logout`
|
|
- `GET /api/v1/me`
|
|
- Targets:
|
|
- `GET/POST /api/v1/targets`
|
|
- `GET/PUT/DELETE /api/v1/targets/{id}`
|
|
- `GET /api/v1/targets/{id}/metrics?from=&to=&metric=`
|
|
- `GET /api/v1/targets/{id}/locks`
|
|
- `GET /api/v1/targets/{id}/activity`
|
|
- `GET /api/v1/targets/{id}/top-queries`
|
|
- `GET /api/v1/targets/{id}/overview`
|
|
- Admin users (admin-only):
|
|
- `GET /api/v1/admin/users`
|
|
- `POST /api/v1/admin/users`
|
|
- `PUT /api/v1/admin/users/{user_id}`
|
|
- `DELETE /api/v1/admin/users/{user_id}`
|
|
|
|
## Security notes
|
|
|
|
- No secrets are hardcoded in source
|
|
- Passwords are hashed with Argon2
|
|
- Target credentials are encrypted with Fernet
|
|
- CORS is environment-configurable
|
|
- Audit logs include auth, target, and user management events
|
|
- Rate limiting is currently a placeholder for future middleware integration
|
|
|
|
## Important: `pg_stat_statements`
|
|
|
|
Query Insights requires `pg_stat_statements` on each monitored target.
|
|
|
|
```sql
|
|
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
|
|
```
|
|
|
|
## Reverse proxy and SSL
|
|
|
|
For production-like deployments behind HTTPS:
|
|
|
|
- Set frontend API to relative path: `VITE_API_URL=/api/v1`
|
|
- Route `/api/` from proxy to backend service
|
|
- Keep frontend and API on the same public origin to avoid CORS/mixed-content problems
|