Architecture
QueryGlow is built so your data stays on your server. It runs as a self-contained Node.js process inside Docker. Its only calls to third-party services are the optional Ask AI requests to the provider you chose; the browser loads the Monaco editor from cdn.jsdelivr.net. The app never checks for updates: ./queryglow update runs git fetch against your own remote, only when you run it.
The Tech Stack
- Next.jsHandles the React frontend (Monaco Editor, Data Grid) and the API backend in one Node.js 22 process. The container starts
nextdirectly and runs as a non-root user. - DriversDirect native connections using
pg(PostgreSQL, CockroachDB, TimescaleDB),mysql2(MySQL, MariaDB), andbetter-sqlite3(SQLite).knexis used only for MySQL, MariaDB and SQLite. - Ask AIStateless requests to OpenAI, Anthropic or Google with your own key. Ask AI sends your database type, table and column names with their types, and your prompt. Never rows. Keys come from
.envor are entered in the app and stored encrypted inai-settings.json; a key in.envwins. Rate limited to 30 requests per minute at nginx (standalone mode). - Host toolingThe
queryglowshell command runs on the host for install, update, status, backup and doctor. It needs bash, git, Docker with the compose plugin and curl; no Node.js on the host. - TimeThe server process runs in UTC, so timestamps reach the browser as stored. The browser formats them with the time zone and format set in Preferences.
Request Lifecycle
- Authentication (nginx Layer)
Request hits nginx first. Basic Auth checks the credentials against the htpasswd file, and nginx applies a general rate limit (standalone mode). If valid, nginx proxies to
127.0.0.1:3000(or the port the installer picked). - CSRF Validation (API Layer)
For state-changing requests (POST, PUT, PATCH, DELETE), the API refuses a request marked cross-site by the browser or whose Origin header does not match the Host. Cross-origin requests are blocked.
- Decryption
The API route reads
connections.jsonand decrypts the stored password with AES-256-GCM authenticated encryption, using a key derived fromSESSION_SECRETandENCRYPTION_SALT. Tampered ciphertext fails to decrypt. - Safe Mode Check (Query Editor and Agents)
If Safe Mode is enabled (default), destructive queries are blocked:
DROP TABLE,TRUNCATE,DELETE/UPDATEwithout WHERE clause. Data Browser buttons do not go through this check. On a connection marked production, the Query Editor also asks for confirmation before any write. - Tunneling (Optional)
If SSH Tunneling is enabled, the app opens a local listener on
127.0.0.1with a random port, connects to your bastion over SSH and forwards the database traffic through it. The bastion's host key is pinned on first use; a changed key is refused with both fingerprints. - Execution
The driver connects (either directly or via the local tunnel port) and executes the SQL. SSL connections can verify the server certificate (Verify server certificate option). Results come back to the UI as JSON.
Agent Access Path
AI agents call /api/mcp, which skips Basic Auth and requires a Bearer token instead (tokens are stored only as SHA-256 hashes). The app rate limits the endpoint per IP and overall, runs the same query guard, then executes one statement per call inside a read-only transaction enforced by the database (for read-only tokens), with a per-statement timeout. Every call, including refused and paused ones, is recorded in the Activity tab. Agent Access guide
Security Layers
QueryGlow uses defense in depth with multiple independent security layers:
- Network Isolation: QueryGlow binds to
127.0.0.1:3000only. Not accessible from external network. - Credential Encryption: AES-256-GCM with scrypt key derivation. Unique salt per installation (written by the installer).
- SQL Injection Prevention: Identifier escaping + parameterized queries for all user input.
- SQLite Sandboxing: File paths restricted to the
/app/datadirectory only. - CSV Export Protection: Formula injection characters are sanitized to prevent Excel/Sheets exploits.
File-System Persistence
QueryGlow does not use an external database for its own state. It keeps JSON files in the Docker volume, written atomically and one writer at a time. ./queryglow backup copies them, together with .env, to backups/<timestamp>/.
Connection profiles. Passwords, SSH private keys and SSH passphrases are AES-256-GCM encrypted.
Rolling log of the last 1,000 executed queries across all connections.
Saved SQL snippets with names for quick reuse.
Agent tokens (SHA-256 hashes only) and the log of agent calls shown in the Activity tab.
AI provider keys (encrypted) and models entered in the app.
SSH host key fingerprints pinned on first connect.
Important: SESSION_SECRET and ENCRYPTION_SALT in your .env file derive the encryption key. Without them, you cannot decrypt saved connection passwords, SSH keys or AI keys. Back up the data and .env together.