Environment Variables
Configuration options for the QueryGlow container, defined in your .env file. ./queryglow install (deploy.sh) writes NODE_ENV, PORT, SESSION_SECRET, ENCRYPTION_SALT, QUERYGLOW_ALLOW_DESTRUCTIVE and the three AI key lines. Everything else is optional.
Applying a change: recreate the container, a plain restart does not read .env again:
docker compose -f docker-compose.production.yml up -d --force-recreate queryglow./queryglow update lists settings that are new since your version and never changes existing values. Display settings such as time zone, date format or rows per page are not environment variables: they live in Preferences, per browser.
Security
| Variable | Default | Description |
|---|---|---|
| SESSION_SECRET | none, required | Derives the encryption key for database passwords, SSH keys and AI keys entered in the app (AES-256-GCM with scrypt). At least 32 characters; openssl rand -hex 32 gives 64. Without it, no connection with a password or SSH key can be saved or opened.Warning: If you lose or change it, saved passwords, SSH keys and AI keys become unreadable. Never regenerate it on an install with saved connections; back up .env securely. |
| ENCRYPTION_SALT | queryglow-salt-v1 | Salt for the key derivation. The installer writes a random one (openssl rand -hex 16) for each installation. Without it the built-in default salt is used. Never change it once connections are saved. |
| NODE_ENV | production in the image | Set to production for production. .env.example sets development for local work; the Docker image runs production. |
Safe Mode
| Variable | Default | Description |
|---|---|---|
| QUERYGLOW_ALLOW_DESTRUCTIVE | false | Controls what the Query Editor may run: false = Safe Mode (default) Blocks DROP TABLE (and DROP INDEX, VIEW, SEQUENCE, SCHEMA), TRUNCATE, DELETE/UPDATE without WHERE true = Power Mode Also allows DROP, TRUNCATE and DELETE/UPDATE without WHERE. The always blocked list below still applies. Note: Data Browser buttons (edit and delete single rows) always work. The setting also decides whether Agent Access write tokens may run DELETE or UPDATE without WHERE; agents never get DROP, TRUNCATE or DDL. |
Always blocked (cannot be enabled): DROP DATABASE, SHUTDOWN, INTO OUTFILE, INTO DUMPFILE, LOAD_FILE, LOAD DATA, xp_cmdshell, OPENROWSET, COPY TO/FROM PROGRAM, pg_execute_server_program
System
| Variable | Default | Description |
|---|---|---|
| PORT | 3000 | Port the Next.js server listens on (127.0.0.1 only in the image). The installer takes the next free port up to 3100 if 3000 is in use, or asks for one. Also a Docker build argument. |
| DATA_DIR | ./data (/app/data in Docker) | Directory for the JSON data files:
|
| QUERYGLOW_MAX_EXPORT_ROWS | 100000 | Row cap for a CSV export from the Data Browser. A truncated export warns the user. 0 disables the cap (not recommended). Since 1.1.0. |
| DEMO_MODE | unset (false) | Turns the app into a read-only public demo and switches Agent Access off. Do not set it for normal use. |
Agent Access (MCP)
| Variable | Default | Description |
|---|---|---|
| QUERYGLOW_MCP_RATE_MAX | 240 | Requests per minute per IP to the agent endpoint /api/mcp. |
| QUERYGLOW_MCP_GLOBAL_RATE_MAX | 2000 | Requests per minute to the agent endpoint across all callers. Holds even when a proxy sets no trusted client IP. |
| QUERYGLOW_AGENT_STATEMENT_TIMEOUT_MS | 30000 | Timeout per agent statement in milliseconds, on every engine. Since 1.2.1. |
| QUERYGLOW_SQLITE_MAX_WORKERS | 4 | How many SQLite worker processes Agent Access may run at once. Since 1.3.0. |
Ask AI (Optional)
Keys can also be entered in the app (Ask AI, gear icon, AI providers), where they are stored encrypted in ai-settings.json and can be checked with a Test button. A key in .env wins over one entered in the app. With no key in either place, Ask AI is off and everything else works. Requests go through your server, so keys never reach the browser. Ask AI sends your database type, table and column names with their types, and your prompt. Never rows.
| Variable | Default | Description |
|---|---|---|
| OPENAI_API_KEY | empty | OpenAI key. Format: sk-... |
| ANTHROPIC_API_KEY | empty | Anthropic key. Format: sk-ant-... |
| GOOGLE_API_KEY | empty | Google key. Format: AIza... |
| QUERYGLOW_OPENAI_MODEL | gpt-5.1-2025-11-13 | OpenAI model. Changing it needs the same --force-recreate as any .env change. Since 1.2.1. |
| QUERYGLOW_ANTHROPIC_MODEL | claude-haiku-4-5-20251001 | Anthropic model. Since 1.2.1. |
| QUERYGLOW_GOOGLE_MODEL | gemini-3-pro-preview | Google model. Since 1.2.1. |
Ask AI is rate limited to 30 requests per minute per IP at nginx (standalone mode).
Advanced (not in .env.example)
The app reads these two, but .env.example does not list them. You rarely need them.
| Variable | Default | Description |
|---|---|---|
| QUERYGLOW_CONNECTION_IDLE_MS | 1800000 (30 min) | Idle database connection pools close after this many milliseconds. |
| QUERYGLOW_SQLITE_WORKER_PATH | auto | Overrides the path of the SQLite agent worker. Only for unusual setups without Docker. |
Set by the Image, the App or the Host Command
Not part of your .env, listed so the reference is complete.
| Variable | Default | Description |
|---|---|---|
| TZ | UTC | The server process sets UTC at start, so timestamps reach the browser as stored. Set the display time zone in Preferences. |
| NEXT_RUNTIME | set by Next.js | Internal to Next.js. |
| HOSTNAME | 127.0.0.1 | Set in the Docker image. The bind address itself comes from the start command (-H 127.0.0.1). |
| NEXT_TELEMETRY_DISABLED | 1 | Next.js telemetry is off in the build and at runtime. |
| QG_HEALTH_TIMEOUT | 90 | Seconds ./queryglow update waits for the health check, set in the host shell: QG_HEALTH_TIMEOUT=180 ./queryglow update. |
Example .env File
# ==============================================
# QueryGlow Configuration
# ==============================================
# REQUIRED: paste the output of openssl rand -hex 32
SESSION_SECRET=
# Written by the installer (unique per installation).
# Leave commented out unless you generate one: openssl rand -hex 16
# ENCRYPTION_SALT=
# Environment
NODE_ENV=production
# Safe Mode (false = Safe Mode on)
# Set to true only if you need DROP TABLE, TRUNCATE, etc.
QUERYGLOW_ALLOW_DESTRUCTIVE=false
# Data persistence (the Docker image sets /app/data)
# DATA_DIR=/app/data
# Port (default: 3000)
PORT=3000
# Optional: AI keys. A key here wins over a key entered in the app,
# so leave these empty unless you use .env for keys on purpose.
OPENAI_API_KEY=
ANTHROPIC_API_KEY=
GOOGLE_API_KEY=Never copy placeholder values into a real .env: a placeholder AI key overrides the key entered in the app, and a placeholder secret is long enough to pass the length check.
Quick Reference
| Variable | Default | Purpose |
|---|---|---|
| SESSION_SECRET | none (required) | Encryption key derivation, at least 32 characters |
| ENCRYPTION_SALT | queryglow-salt-v1 | Salt for the key derivation (the installer writes a random one) |
| NODE_ENV | production in the image | Runtime mode (development in .env.example) |
| PORT | 3000 | App port |
| DATA_DIR | ./data (/app/data in Docker) | Where the JSON data files live |
| QUERYGLOW_ALLOW_DESTRUCTIVE | false | Safe Mode (false) or Power Mode (true) |
| QUERYGLOW_MAX_EXPORT_ROWS | 100000 | Row cap for a CSV export, 0 disables |
| QUERYGLOW_MCP_RATE_MAX | 240 | Agent endpoint requests per minute per IP |
| QUERYGLOW_MCP_GLOBAL_RATE_MAX | 2000 | Agent endpoint requests per minute overall |
| QUERYGLOW_AGENT_STATEMENT_TIMEOUT_MS | 30000 | Timeout per agent statement in milliseconds |
| QUERYGLOW_SQLITE_MAX_WORKERS | 4 | SQLite worker processes for agents at once |
| DEMO_MODE | unset (false) | Read-only public demo; leave unset |
| OPENAI_API_KEY | empty | OpenAI key for Ask AI |
| ANTHROPIC_API_KEY | empty | Anthropic key for Ask AI |
| GOOGLE_API_KEY | empty | Google key for Ask AI |
| QUERYGLOW_OPENAI_MODEL | gpt-5.1-2025-11-13 | OpenAI model |
| QUERYGLOW_ANTHROPIC_MODEL | claude-haiku-4-5-20251001 | Anthropic model |
| QUERYGLOW_GOOGLE_MODEL | gemini-3-pro-preview | Google model |
| QUERYGLOW_CONNECTION_IDLE_MS | 1800000 (30 min) | Idle database pools close after this (not in .env.example) |
| QUERYGLOW_SQLITE_WORKER_PATH | auto | Path of the SQLite agent worker (not in .env.example) |
| TZ | UTC (set at start) | Server time zone, set by the app |
| NEXT_RUNTIME | set by Next.js | Internal to Next.js |
| HOSTNAME | 127.0.0.1 | Set in the Docker image |
| NEXT_TELEMETRY_DISABLED | 1 | Next.js telemetry off, set in the Docker image |
| QG_HEALTH_TIMEOUT | 90 | Seconds ./queryglow update waits for the health check |