51eece14c259c873b3723c9098cd751ef198ba0e
All checks were successful
PostgreSQL Compatibility Matrix / PG14 smoke (push) Successful in 7s
PostgreSQL Compatibility Matrix / PG15 smoke (push) Successful in 7s
PostgreSQL Compatibility Matrix / PG16 smoke (push) Successful in 7s
PostgreSQL Compatibility Matrix / PG17 smoke (push) Successful in 6s
PostgreSQL Compatibility Matrix / PG18 smoke (push) Successful in 6s
Implemented backend and frontend support for managing SMTP settings for email notifications. Includes API endpoints, database migration, and UI integration for configuring and testing email alerts.
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_bgwritervspg_stat_checkpointerfields).
What it includes
- Multi-target PostgreSQL monitoring (remote instances)
- Polling collector for:
pg_stat_databasepg_stat_activitypg_stat_bgwriterpg_lockspg_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
- Authentication and RBAC (
- 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 applicationfrontend/React (Vite) applicationops/helper scripts and env template copydocker-compose.ymlfull stack definition.env.exampleenvironment 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 yourBACKEND_PORT) - core DB:
5433(or yourDB_PORT)
- frontend:
Optional but recommended:
psqlclient for troubleshooting target connectivity
Quick start
- Create local env file:
cp .env.example .env
- Generate an encryption key and set
ENCRYPTION_KEYin.env:
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
- Start services:
make up
- Open:
- Frontend:
http://<SERVER_IP>:5173(orhttps://<your-domain>) - Backend API:
http://<SERVER_IP>:8000/api/v1(orhttps://<your-domain>/api/v1) - OpenAPI docs:
http://<SERVER_IP>:8000/docs(orhttps://<your-domain>/docs)
Default initial admin (from .env):
- Email:
admin@example.com - Password:
ChangeMe123!
Common commands
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:
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):
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/docsENVIRONMENT:dev | staging | prod | testLOG_LEVEL:DEBUG | INFO | WARNING | ERROR
Core database (internal)
DB_NAME: Internal metadata DB nameDB_USER: Internal metadata DB userDB_PASSWORD: Internal metadata DB passwordDB_PORT: Host port mapped to internal PostgreSQL5432
Backend API
BACKEND_PORT: Host port mapped to backend container8000JWT_SECRET_KEY: JWT signing key (must be changed)JWT_ALGORITHM: JWT algorithm (defaultHS256)JWT_ACCESS_TOKEN_MINUTES: access token lifetimeJWT_REFRESH_TOKEN_MINUTES: refresh token lifetimeENCRYPTION_KEY: Fernet key for encrypting target passwords at restCORS_ORIGINS: comma-separated allowed origins or*(dev-only)POLL_INTERVAL_SECONDS: collector polling intervalINIT_ADMIN_EMAIL: bootstrap admin emailINIT_ADMIN_PASSWORD: bootstrap admin password
Frontend
FRONTEND_PORT: Host port mapped to frontend container80VITE_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
- Proxy/SSL setup: use
API overview (minimum)
- Auth:
POST /api/v1/auth/loginPOST /api/v1/auth/refreshPOST /api/v1/auth/logoutGET /api/v1/me
- Targets:
GET/POST /api/v1/targetsGET/PUT/DELETE /api/v1/targets/{id}GET /api/v1/targets/{id}/metrics?from=&to=&metric=GET /api/v1/targets/{id}/locksGET /api/v1/targets/{id}/activityGET /api/v1/targets/{id}/top-queriesGET /api/v1/targets/{id}/overview
- Admin users (admin-only):
GET /api/v1/admin/usersPOST /api/v1/admin/usersPUT /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.
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.
Description
Releases
13
Languages
Python
48.2%
JavaScript
40.1%
CSS
10.4%
Shell
0.5%
Dockerfile
0.5%
Other
0.2%