All checks were successful
PostgreSQL Compatibility Matrix / PG14 smoke (push) Successful in 8s
PostgreSQL Compatibility Matrix / PG15 smoke (push) Successful in 7s
PostgreSQL Compatibility Matrix / PG16 smoke (push) Successful in 17s
PostgreSQL Compatibility Matrix / PG17 smoke (push) Successful in 19s
PostgreSQL Compatibility Matrix / PG18 smoke (push) Successful in 18s
This update introduces `PG_DSN_CANDIDATES` for specifying multiple DSN options, improving compatibility and CI portability. The script now attempts connections sequentially using the provided candidates before falling back to single DSN or raising an error. Relevant updates to documentation and workflow configuration have also been made.
206 lines
5.8 KiB
Markdown
206 lines
5.8 KiB
Markdown
# NexaPG - PostgreSQL Monitoring Stack
|
|
|
|
NexaPG is a Docker-based PostgreSQL monitoring platform for multiple remote targets, built with FastAPI + React.
|
|
|
|
## PostgreSQL Version Support
|
|
|
|
NexaPG targets PostgreSQL versions **14, 15, 16, 17, and 18**.
|
|
|
|
- Compatibility is verified with an automated CI matrix.
|
|
- Collector and overview queries include fallbacks for stats view differences between versions (for example `pg_stat_bgwriter` vs `pg_stat_checkpointer` fields).
|
|
|
|
## 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://<SERVER_IP>:5173` (or `https://<your-domain>`)
|
|
- Backend API: `http://<SERVER_IP>:8000/api/v1` (or `https://<your-domain>/api/v1`)
|
|
- OpenAPI docs: `http://<SERVER_IP>:8000/docs` (or `https://<your-domain>/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
|
|
```
|
|
|
|
PostgreSQL compatibility smoke check script:
|
|
|
|
```bash
|
|
PG_DSN='postgresql://postgres:postgres@127.0.0.1:5432/compatdb?sslmode=disable' \
|
|
python backend/scripts/pg_compat_smoke.py
|
|
```
|
|
|
|
CI/runner-safe variant (tries multiple hosts):
|
|
|
|
```bash
|
|
PG_DSN_CANDIDATES='postgresql://postgres:postgres@postgres:5432/compatdb?sslmode=disable,postgresql://postgres:postgres@127.0.0.1:5432/compatdb?sslmode=disable' \
|
|
python backend/scripts/pg_compat_smoke.py
|
|
```
|
|
|
|
## 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 server setup: use `http://<SERVER_IP>:<BACKEND_PORT>/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
|
|
|
|
## CI Compatibility Matrix
|
|
|
|
GitHub Actions workflow:
|
|
|
|
- `.github/workflows/pg-compat-matrix.yml`
|
|
|
|
It runs smoke checks against PostgreSQL `14`, `15`, `16`, `17`, and `18`.
|