Documentation

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

VariableDefaultDescription
SESSION_SECRETnone, requiredDerives 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_SALTqueryglow-salt-v1Salt 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_ENVproduction in the imageSet to production for production. .env.example sets development for local work; the Docker image runs production.

Safe Mode

VariableDefaultDescription
QUERYGLOW_ALLOW_DESTRUCTIVEfalseControls 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

VariableDefaultDescription
PORT3000Port 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:
  • • connections.json: encrypted connection profiles
  • • query-history.json: execution history (last 1,000 queries)
  • • saved-queries.json: saved SQL snippets
  • • agent-tokens.json, agent-activity.json: agent tokens (hashed) and their calls
  • • ai-settings.json: AI keys (encrypted) and models entered in the app
  • • ssh-known-hosts.json: pinned SSH host keys
QUERYGLOW_MAX_EXPORT_ROWS100000Row 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_MODEunset (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)

VariableDefaultDescription
QUERYGLOW_MCP_RATE_MAX240Requests per minute per IP to the agent endpoint /api/mcp.
QUERYGLOW_MCP_GLOBAL_RATE_MAX2000Requests per minute to the agent endpoint across all callers. Holds even when a proxy sets no trusted client IP.
QUERYGLOW_AGENT_STATEMENT_TIMEOUT_MS30000Timeout per agent statement in milliseconds, on every engine. Since 1.2.1.
QUERYGLOW_SQLITE_MAX_WORKERS4How 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.

VariableDefaultDescription
OPENAI_API_KEYemptyOpenAI key. Format: sk-...
ANTHROPIC_API_KEYemptyAnthropic key. Format: sk-ant-...
GOOGLE_API_KEYemptyGoogle key. Format: AIza...
QUERYGLOW_OPENAI_MODELgpt-5.1-2025-11-13OpenAI model. Changing it needs the same --force-recreate as any .env change. Since 1.2.1.
QUERYGLOW_ANTHROPIC_MODELclaude-haiku-4-5-20251001Anthropic model. Since 1.2.1.
QUERYGLOW_GOOGLE_MODELgemini-3-pro-previewGoogle 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.

VariableDefaultDescription
QUERYGLOW_CONNECTION_IDLE_MS1800000 (30 min)Idle database connection pools close after this many milliseconds.
QUERYGLOW_SQLITE_WORKER_PATHautoOverrides 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.

VariableDefaultDescription
TZUTCThe server process sets UTC at start, so timestamps reach the browser as stored. Set the display time zone in Preferences.
NEXT_RUNTIMEset by Next.jsInternal to Next.js.
HOSTNAME127.0.0.1Set in the Docker image. The bind address itself comes from the start command (-H 127.0.0.1).
NEXT_TELEMETRY_DISABLED1Next.js telemetry is off in the build and at runtime.
QG_HEALTH_TIMEOUT90Seconds ./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

VariableDefaultPurpose
SESSION_SECRETnone (required)Encryption key derivation, at least 32 characters
ENCRYPTION_SALTqueryglow-salt-v1Salt for the key derivation (the installer writes a random one)
NODE_ENVproduction in the imageRuntime mode (development in .env.example)
PORT3000App port
DATA_DIR./data (/app/data in Docker)Where the JSON data files live
QUERYGLOW_ALLOW_DESTRUCTIVEfalseSafe Mode (false) or Power Mode (true)
QUERYGLOW_MAX_EXPORT_ROWS100000Row cap for a CSV export, 0 disables
QUERYGLOW_MCP_RATE_MAX240Agent endpoint requests per minute per IP
QUERYGLOW_MCP_GLOBAL_RATE_MAX2000Agent endpoint requests per minute overall
QUERYGLOW_AGENT_STATEMENT_TIMEOUT_MS30000Timeout per agent statement in milliseconds
QUERYGLOW_SQLITE_MAX_WORKERS4SQLite worker processes for agents at once
DEMO_MODEunset (false)Read-only public demo; leave unset
OPENAI_API_KEYemptyOpenAI key for Ask AI
ANTHROPIC_API_KEYemptyAnthropic key for Ask AI
GOOGLE_API_KEYemptyGoogle key for Ask AI
QUERYGLOW_OPENAI_MODELgpt-5.1-2025-11-13OpenAI model
QUERYGLOW_ANTHROPIC_MODELclaude-haiku-4-5-20251001Anthropic model
QUERYGLOW_GOOGLE_MODELgemini-3-pro-previewGoogle model
QUERYGLOW_CONNECTION_IDLE_MS1800000 (30 min)Idle database pools close after this (not in .env.example)
QUERYGLOW_SQLITE_WORKER_PATHautoPath of the SQLite agent worker (not in .env.example)
TZUTC (set at start)Server time zone, set by the app
NEXT_RUNTIMEset by Next.jsInternal to Next.js
HOSTNAME127.0.0.1Set in the Docker image
NEXT_TELEMETRY_DISABLED1Next.js telemetry off, set in the Docker image
QG_HEALTH_TIMEOUT90Seconds ./queryglow update waits for the health check