SQL Database server information dashboard
  • Go 61.6%
  • Vue 30.8%
  • TypeScript 5.2%
  • Makefile 1.5%
  • Dockerfile 0.4%
  • Other 0.4%
Find a file
Johannes Bülow e978db819e
All checks were successful
release / docker (push) Successful in 12m42s
Fix duplicate DB entries and add last-seen clients tracking
- refreshServerData: cleanup volatile tables after successful ping
  (not before like the old cleanupServerData), preventing duplicate
  entries on each collection cycle
- DuckDB: new connection_detail_history table stores per-client
  connection details (user, host, app, state, timestamps)
- API: GET /api/servers/{id}/clients returns the most recent
  connection per unique (user@host, database) pair
- Frontend: Last Seen Clients table on server detail page showing
  when each client was last connected
2026-06-24 09:30:07 +02:00
.forgejo/workflows removed main.yml workflow 2026-06-20 20:30:46 +02:00
api Fix duplicate DB entries and add last-seen clients tracking 2026-06-24 09:30:07 +02:00
cmd/seed Add seed data command and fix collector cleanup ordering 2026-06-20 17:33:47 +02:00
frontend Fix duplicate DB entries and add last-seen clients tracking 2026-06-24 09:30:07 +02:00
internal Fix duplicate DB entries and add last-seen clients tracking 2026-06-24 09:30:07 +02:00
web Initial commit: SQL Panel project scaffold 2026-06-20 14:22:10 +02:00
.air.toml Remove vendoring 2026-06-20 15:35:10 +02:00
.dockerignore Initial commit: SQL Panel project scaffold 2026-06-20 14:22:10 +02:00
.gitignore Track go.sum in git (remove *.sum from gitignore) 2026-06-20 18:16:57 +02:00
AGENTS.md v0.0.1 2026-06-20 19:55:48 +02:00
Design.md Initial commit: SQL Panel project scaffold 2026-06-20 14:22:10 +02:00
Dockerfile Fix Docker user creation for Debian trixie-slim 2026-06-20 18:31:18 +02:00
go.mod Switch historical DB to DuckDB 2026-06-20 15:33:06 +02:00
go.sum Track go.sum in git (remove *.sum from gitignore) 2026-06-20 18:16:57 +02:00
LICENSE Initial commit: SQL Panel project scaffold 2026-06-20 14:22:10 +02:00
main.go Write historical data from collectors to DuckDB 2026-06-22 08:26:03 +02:00
Makefile Update build-all with cross-compiler CC/CXX and darwin note 2026-06-20 19:48:14 +02:00
README.md Update README and swagger docs 2026-06-22 12:22:38 +02:00

SQL Panel

A web dashboard for monitoring PostgreSQL and MSSQL database servers. Collects server metrics, database inventory, active connections, and historical trends — all accessible via a Vue 3 SPA.

Features

  • Server inventory — add, edit, manage monitored database servers with autogenerated passwords and permission SQL snippets
  • Live snapshots — OS, version, RAM, CPU, disk, uptime, connection counts for both PG and MSSQL
  • Database discovery — sizes, owners, collation, encoding, data vs WAL/log sizes across all servers
  • Database objects — tables, indexes, views, procedures, triggers, sequences, foreign keys
  • Active connections — detailed connection table (user, host, app, state, duration, last seen) with full parity across PG and MSSQL
  • Historical data — size, connections, CPU/memory/disk trends stored in DuckDB with configurable retention and automatic downsampling
  • Time-series charts — auto-scaled line charts (bytes in MB/GB, percentages) with timeframe selector (7d/30d/90d/All)
  • Databases page — sortable, filterable table of all databases across all servers with JSON/CSV export
  • Role-based access — admin (full CRUD) and viewer (read-only) roles; local user management page
  • API token authentication — Bearer token auth with read/write scopes, managed at /admin/tokens
  • LDAP authentication — bind auth with recursive group membership resolution, auto-provisioning
  • Password self-service — users can change their own password
  • PostgreSQL collection — extensions, tablespaces, config parameters, replication slots, running queries, pending restart settings, indexes, views, procedures, triggers, sequences, foreign keys
  • MSSQL collection — edition, version, availability groups, agent jobs, running queries, config parameters, tables, indexes, views, procedures, triggers, sequences, foreign keys
  • On-demand collection — manual collect button per server, auto-collect on server creation
  • Embedded frontend — single binary with no separate static file server (Vue 3 + Tailwind v4)
  • Swagger API docs — interactive OpenAPI documentation at /api/swagger/ (17 documented endpoints)
  • Docker support — multi-stage build with Debian base (glibc) for DuckDB compatibility
  • Cross-platform buildsmake build-all for Linux, macOS, Windows on amd64 and arm64
  • Dark mode — default-on dark theme with toggle, persisted to localStorage
  • Seed datamake seed populates fictional data for development

Quick start

Docker

docker build -t sqlpanel .
docker run -d -p 8080:8080 --name sqlpanel sqlpanel

Default login: admin / admin (override via SP_DEFAULT_ADMIN_PASSWORD).

Local development

Requirements: Go 1.26+, Node 24+, Make.

# Install frontend deps
cd frontend && npm install && cd ..

# Build (Vue → Go)
make build

# Run
make run

Or with live frontend reload:

make dev

This starts Vite on port 3000 (proxying /api to Go on 8080) and the Go server concurrently.

For network-accessible dev (e.g. testing on another device):

make dev-host

Disables authentication and makes the Vite dev server accessible on 0.0.0.0:3000.

Test collectors against real servers

make test-collectors

Starts PostgreSQL and MSSQL Docker containers, runs the collector, and prints the collected data.

Configuration

Configuration is loaded from TOML files (config.toml in the current directory, ~/.config/sqlpanel/, or /etc/sqlpanel/) and environment variables with the SP_ prefix.

Config key Env var Default Description
server.host SP_SERVER_HOST 0.0.0.0 HTTP listen address
server.port SP_SERVER_PORT 8080 HTTP listen port
auth.disable SP_AUTH_DISABLE false Disable authentication (dev only)
auth.ldap.enabled SP_AUTH_LDAP_ENABLED false Enable LDAP authentication
auth.ldap.url SP_AUTH_LDAP_URL "" LDAP server URL (ldap:// or ldaps://)
auth.ldap.bind_dn SP_AUTH_LDAP_BIND_DN "" LDAP bind DN for user search
auth.ldap.bind_password SP_AUTH_LDAP_BIND_PASSWORD "" LDAP bind password
auth.ldap.search_base SP_AUTH_LDAP_SEARCH_BASE "" LDAP search base DN
auth.ldap.user_filter SP_AUTH_LDAP_USER_FILTER (uid=%s) LDAP user search filter (%s = username)
auth.ldap.admin_group_dn SP_AUTH_LDAP_ADMIN_GROUP_DN "" LDAP group DN that maps to admin role
auth.ldap.viewer_group_dn SP_AUTH_LDAP_VIEWER_GROUP_DN "" LDAP group DN that maps to viewer role
SP_DEFAULT_ADMIN_PASSWORD admin Default admin password (first run only)
SP_COLLECT_INTERVAL 5m Collector run interval
log.format SP_LOG_FORMAT text Log output format (text or json)
log.level SP_LOG_LEVEL info Log level (debug, info, warn, error)
debug SP_DEBUG false Overrides log level to debug
database.path SP_DATABASE_PATH data/sqlpanel.db SQLite database path
database.historical_path SP_DATABASE_HISTORICAL_PATH data/historical.duckdb Historical data path
retention.detail SP_RETENTION_DETAIL 168h Keep all records for this duration
retention.hourly SP_RETENTION_HOURLY 720h Keep 1/hour until this
retention.daily SP_RETENTION_DAILY 8760h Keep 1/day until this

Retention

Historical data is cleaned automatically every hour:

Period Behavior
< detail All records kept as-is
detailhourly 1 row per hour per entity, rest deleted
hourlydaily 1 row per day per entity, rest deleted
> daily All rows deleted

API

LDAP authentication

When auth.ldap.enabled is set, users not found in the local database are authenticated against the LDAP server. On first successful login the user is provisioned automatically with a role determined by group membership.

Group resolution is recursive — all nested group memberships are resolved to determine the user's final role.

Example config.toml:

[auth.ldap]
enabled = true
url = "ldaps://dc.example.com:636"
bind_dn = "cn=admin,dc=example,dc=com"
bind_password = "secret"
search_base = "dc=example,dc=com"
user_filter = "(sAMAccountName=%s)"
admin_group_dn = "cn=sqlpanel-admins,ou=Groups,dc=example,dc=com"
viewer_group_dn = "cn=sqlpanel-viewers,ou=Groups,dc=example,dc=com"

Full interactive Swagger documentation is available at /api/swagger/ when the server is running. The spec is generated from Go annotations via swag init and embedded in the binary.

All endpoints except /api/health and /api/auth/login require authentication.

Method Endpoint Auth Description
GET /api/swagger/ Swagger UI (interactive docs)
GET /api/health Database health check
POST /api/auth/login Login with username/password
POST /api/auth/logout Clear session
GET /api/auth/me user Current user info
PUT /api/auth/password user Change own password
GET /api/servers user List all servers
POST /api/servers admin Create server
GET /api/servers/{id} user Get server details
PUT /api/servers/{id} admin Update server
DELETE /api/servers/{id} admin Delete server
GET /api/servers/{id}/databases user List databases for server
GET /api/servers/{id}/overview user Server dashboard (snapshot + databases + connections)
POST /api/servers/{id}/collect admin Trigger data collection now
GET /api/servers/{id}/history/{metric} user Time-series data (database_size, connections, cpu_memory, disk_usage)
GET /api/databases/{id} user Database detail (tables, indexes, views, etc.)
GET /api/admin/users admin List local users
POST /api/admin/users admin Create local user
PUT /api/admin/users/{id} admin Update user password/role
DELETE /api/admin/users/{id} admin Delete user
GET /api/admin/tokens admin List API tokens
POST /api/admin/tokens admin Create API token
DELETE /api/admin/tokens/{id} admin Revoke API token

Architecture

┌─────────────┐     ┌──────────────┐     ┌──────────────┐
│  Vue 3 SPA  │────▶│  Go HTTP API │────▶│  SQLite (DB) │
│  (embedded)  │     │  net/http    │     │  config +    │
│  Tailwind v4 │     │  + custom    │     │  collected   │
└─────────────┘     │  router      │     │  data        │
                    │              │     └──────────────┘
                    │  Collector   │     ┌──────────────┐
                    │  (bg worker) │────▶│  DuckDB      │
                    │  PG + MSSQL  │     │  historical  │
                    └──────────────┘     │  + retention │
                                         └──────────────┘
  • Collector — background goroutine that connects to each configured server on an interval, runs discovery queries, and writes results to the SQLite database.
  • Retention manager — runs hourly, downsamples DuckDB historical data according to configurable retention periods using date_trunc time bucketing.
  • Auth — passwords hashed with bcrypt, sessions stored in SQLite with HttpOnly cookies. API token auth via Authorization: Bearer sp_.... Admin and viewer roles enforced via middleware. LDAP bind auth with recursive group resolution.

Project structure

main.go                       # Entry point (swagger annotations)
api/                          # HTTP handlers + swagger.json/ui
internal/
  auth/                       # Login/logout, LDAP auth, token auth, middleware
  collector/                  # PG + MSSQL data collection + DuckDB history writer
  config/                     # Viper config loader
  database/                   # DB connections, embedded migrations (golang-migrate)
    migrations/               # Versioned SQL migration files
  retention/                  # DuckDB historical data downsampling
  server/                     # HTTP server, custom router, routes
  middlewares/                # Request logging middleware
  session/                    # SQLite-backed session store
cmd/seed/                     # Fictional data generator for dev/testing
web/                          # Embedded Vue dist (//go:embed)
  vue-dist/                   # Built frontend (generated)
frontend/                     # Vue 3 + TypeScript + Vite + Tailwind v4
  src/
    api/                      # API client + export utilities
    components/               # Layout, TimeSeriesChart, TimeframeSelector
    composables/              # Theme composable (dark mode)
    stores/                   # Auth state store
    views/                    # All page components
    router/                   # Vue Router config

License

GNU General Public License v2.0. See LICENSE.