Panopticum

June 18, 2026 · View on GitHub

A tool for developers and QA — web interface for viewing and managing database connections. Designed for deployment in Kubernetes or Docker.

What it does

  • Connect to PostgreSQL, Greenplum, YugabyteDB, CockroachDB, MySQL, MongoDB, Redis, ClickHouse, Kafka, Elasticsearch, H2, HSQLDB, Derby, Couchbase, Kubernetes API, S3/MinIO, Prometheus/VictoriaMetrics, and many more
  • Browse schemas, tables, keys, topics — with pagination and tree view; Kubernetes: namespaces, pods, Deployments, StatefulSets, Services, Ingresses, ConfigMaps, Secrets (reveal on demand, audited — value never logged), events; S3: buckets and object prefixes; Prometheus: jobs and metrics
  • Query — run SQL, CQL, MQL, PromQL; peek S3 object contents (JSON/CSV/Parquet/hex)
  • Compare — Data Diff for records across Dev / Stage / Prod
  • Integrate — MCP endpoint for AI agents (Cursor, Claude Desktop) — including new describe-entity tool for schema context
  • Offline — all assets bundled, no CDN

Connections are stored in H2. Add, test, and remove them in Settings. Use / in connection names for folders (e.g. Prod/PG, Dev/Mongo).

Quick install

Docker

docker run -d --name panopticum \
  -p 8080:8080 \
  -v panopticum-data:/data \
  -e PANOPTICUM_USER=admin \
  -e PANOPTICUM_PASSWORD=changeme \
  ghcr.io/thesharque/panopticum:latest

Open http://localhost:8080.

Images: GHCR ghcr.io/thesharque/panopticum:latest, Docker Hub sharque/panopticum:latest. For a fixed version use a tag, e.g. :v8.4.0.

Helm

helm repo add panopticum https://thesharque.github.io/panopticum
helm repo update
helm install my-panopticum panopticum/panopticum

Then kubectl port-forward svc/my-panopticum 8080:8080 and open http://localhost:8080.

See panopticum-helm-chart/README.md for configuration (credentials, connections, ingress, persistence).

Configuration

VariableDescriptionDefault
PANOPTICUM_USERBasic Auth loginadmin
PANOPTICUM_PASSWORDBasic Auth passwordadmin
PANOPTICUM_DB_PATHH2 database path./data/panopticum
PANOPTICUM_CONNECTIONS_JSONJSON array of connections to load on first start
ADMIN_LOCKDisable adding/removing connectionsfalse
READ_ONLYDisable data editingfalse
AUDIT_ENABLEDActivity audit lines to stdout (AUDIT user=... action=...) — browse, queries (no SQL text), mutations, connection CRUD, API/MCP; for DevOps / Lokitrue

Activity audit

Structured one-line events on stdout (logger com.panopticum.audit), suitable for Loki/Grafana. No SQL, request bodies, passwords, or row values.

20:12:53.446 AUDIT user=admin conn=419 action=OPEN_DATABASE type=mysql scope=panopticum_dev
20:12:53.814 AUDIT user=admin conn=641 action=RUN_QUERY type=postgresql kind=SELECT
20:12:53.908 AUDIT user=admin action=API_CALL method=POST route=/api/postgres/connections/{id}/query status=200 durationMs=126

Actions: OPEN_DATABASE, OPEN_SCHEMA, OPEN_TABLE, RUN_QUERY, ROW_UPDATE, CONNECTION_CREATE / UPDATE / DELETE, API_CALL, MCP_CALL. Set AUDIT_ENABLED=false to disable.

Bootstrap connections

If db_connections is empty at startup, the app loads connections from PANOPTICUM_CONNECTIONS_JSON (JSON array). Example:

[
  {"name": "prod-pg", "jdbcUrl": "jdbc:postgresql://app:secret@pg.svc:5432/mydb"},
  {"name": "cache", "type": "redis", "host": "redis.svc", "port": 6379},
  {"name": "docs", "type": "mongodb", "host": "mongo.svc", "port": 27017, "database": "mydb"}
]

For Helm: use a Secret with valueFrom.secretKeyRef if the JSON contains passwords.

Supported databases

TypeFeatures
PostgreSQLBrowse; SQL; row edit via CTID where supported
GreenplumSame UI as PostgreSQL (/postgres/{id}); SQL; CTID edit when available
YugabyteDBSame UI as PostgreSQL; SQL; metadata fallbacks for compatibility
CockroachDBSame UI as PostgreSQL; SQL; metadata fallbacks for compatibility
MySQL / MariaDBBrowse; SQL; edit (with PK/unique)
MS SQL ServerBrowse; SQL; edit (with PK/unique)
Oracle DatabaseBrowse; SQL; edit by ROWID
MongoDBBrowse collections; queries
Redis / Dragonfly / Valkey / KeyDBBrowse keys; view/edit values
ClickHouseBrowse; SQL
Cassandra / ScyllaDBBrowse; CQL; edit (with PK)
RabbitMQBrowse queues; peek messages; publish to queue
KafkaBrowse topics; peek records
Elasticsearch / OpenSearchBrowse indices; Query DSL; edit by _id
KubernetesAPI server URL + bearer token; namespaces (comma-separated); browse pods, Deployments, StatefulSets, Services, Ingresses, ConfigMaps, Secrets; tail logs; describe pod (containers, images, resources, probes, conditions, events); namespace events; secret reveal on demand with audit log (payload not logged). Graceful "no access" — 401/403/404 as soft alert
S3 / MinIOEndpoint + access/secret key; browse buckets and prefixes; peek objects (JSON, CSV, Parquet head, hex). Region optional
H2 (TCP)Browse schemas/tables; SQL (/lightjdbc/{id}/...)
HSQLDBSame as H2
Apache Derby (network)Same as H2
CouchbaseBuckets → scopes → collections; documents; N1QL (/couchbase/{id}/...). TLS: couchbases:// via settings

MCP-compatible endpoint at POST /mcp for Cursor, Claude Desktop, etc. Same HTTP Basic Auth as the UI.

Cursor (.cursor/mcp.json):

{
  "mcpServers": {
    "panopticum": {
      "url": "http://localhost:8080/mcp",
      "headers": { "Authorization": "Basic YWRtaW46YWRtaW4=" }
    }
  }
}

Replace YWRtaW46YWRtaW4= with Base64 of username:password (echo -n "admin:changeme" | base64).

MCP Tools

ToolDescription
resolve-panopticum-linkTurn a UI URL/path into connectionId and MCP scope; on error returns availablePaths from saved connections only
list-data-sourcesList all configured connections
list-catalogsList databases / buckets / jobs / namespaces
list-namespacesList schemas (where applicable)
list-entitiesList tables / collections / objects / metrics / pods
query-dataExecute SQL, CQL, N1QL, MQL, PromQL or peek S3 objects
get-record-detailFetch a single record by PK or document ID
describe-entityFull schema: columns, types, PK/FK/indexes, row count — eliminates SELECT *. Supports all data sources

For Kubernetes: list-catalogs → namespaces; list-entities → pods; query-data → tail logs. For S3: list-catalogs → buckets; list-entities → objects; query-data → peek content. For Couchbase: list-catalogs → buckets; list-namespaces → scopes (catalog = bucket); list-entities → collections (namespace = scope); query-data → N1QL; get-record-detail → KV get by documentId. For RabbitMQ: list-catalogs → vhosts; list-entities → queues (catalog = vhost); query-data → peek (20 or {"count":20}) or publish ({"publish":["hello",{"id":1}]}); REST POST /api/rabbitmq/connections/{id}/queues/{vhost}/{queue}/publish with JSON array body.

Docker smoke (optional)

Use official images locally for Greenplum / Yugabyte / CockroachDB, H2 TCP / HSQLDB / Derby network server, and Couchbase Server, add connections in Settings, run Test, then browse and run queries from the UI or MCP.

Stack

  • Micronaut 4.x, Thymeleaf, HTMX
  • REST API + Swagger UI (/swagger-ui)
  • H2 + Flyway
  • EN/RU i18n

Build

./gradlew build

JAR: build/libs/panopticum-all.jar

CI/CD

Push a version tag (e.g. v8.4.0) to trigger a GitHub Actions workflow that builds and pushes Docker images to GHCR and Docker Hub.