# Configuration

> Every QueryProxy environment variable — query limits, execution, result storage, the application database and the queue.

- Documentation: Reference
- Updated: 2026-09-07
- Source: https://queryproxy.com/docs/configuration/
- Language: en-US
- Author: Muhammet ŞAFAK

---
All configuration is environment variables (`.env` locally, container
environment in Docker). `.env.example` in the repository documents the full
set; this page explains the ones you'll actually change.

## QueryProxy settings

| Variable | Default | Meaning |
| :-- | :-- | :-- |
| `QUERYPROXY_SELECT_DEFAULT_LIMIT` | `1000` | `LIMIT` injected into SELECTs that have none |
| `QUERYPROXY_SELECT_HARD_LIMIT` | `10000` | Larger LIMITs are clamped down to this |
| `QUERYPROXY_EXECUTION_TIMEOUT` | `300` | Max seconds a single request may run on the worker |
| `QUERYPROXY_RESULT_DISK` | `local` | Laravel filesystem disk for result files (`s3` supported) |
| `QUERYPROXY_RESULT_TTL_DAYS` | `30` | Days before `results:prune` deletes stored results |
| `QUERYPROXY_SEED_DEMO` | `false` | Docker only: seed the demo team on first boot (one random password, printed once in the logs; refused under `APP_ENV=production` unless `QUERYPROXY_SEED_DEMO_FORCE=true`) |
| `QUERYPROXY_REQUIRE_2FA` | `none` | Enforce TOTP two-factor auth: `none`, `admins`, `dba` or `all` |
| `QUERYPROXY_CHAT_WEBHOOK_ALLOWED_HOSTS` | — | Extra allowed hosts for outbound chat webhooks (SSRF guard; Slack/Teams hosts are allowed by default) |
| `QUERYPROXY_CHAT_INCLUDE_SQL` | `true` | Embed a SQL preview in chat notifications |
| `QUERYPROXY_CONNECTION_HOST_DENYLIST` | — | Extra hosts blocked as connection targets (comma-separated) |
| `QUERYPROXY_SQLITE_ALLOWED_DIR` | — | Restrict SQLite connection files to this directory |

> Keep the worker's `--timeout` a bit above `QUERYPROXY_EXECUTION_TIMEOUT`
> (the image's worker uses `310` vs `300`) so the job timeout fires first, and
> keep `DB_QUEUE_RETRY_AFTER` (default `330`) above that timeout so a slow query
> is never re-reserved and executed twice.

## Application key and HTTPS

`APP_KEY` encrypts your stored connection credentials and chat secrets. **For
production, set it explicitly and keep it stable** — a regenerated key (e.g. on
container recreation) makes every stored credential unreadable. Generate one
with `php artisan key:generate --show`, and when rotating, move the old key into
`APP_PREVIOUS_KEYS` (comma-separated) so existing ciphertext still decrypts.

When serving over HTTPS behind a reverse proxy, set `SESSION_SECURE_COOKIE=true`.

## Application database

QueryProxy's own data (users, teams, requests, audit log) lives in SQLite by
default — zero configuration. For MySQL or PostgreSQL, set the standard Laravel
variables:

```dotenv
DB_CONNECTION=pgsql        # or mysql
DB_HOST=db
DB_PORT=5432
DB_DATABASE=queryproxy
DB_USERNAME=queryproxy
DB_PASSWORD=change-me
```

This is the *application* database — the databases you proxy are configured in
the UI under **Connections**, per team, with encrypted credentials.

## Queue

The queue is database-backed by default (no Redis required). To move it to
Redis:

```dotenv
QUEUE_CONNECTION=redis
REDIS_HOST=redis
```

The worker command stays the same:
`php artisan queue:work --queue=queries,default`.

## Result storage on S3

Set `QUERYPROXY_RESULT_DISK=s3` and the standard `AWS_*` variables. Result
files are written as NDJSON, streamed — memory use stays flat regardless of
result size.

## SQL Server targets

The default Docker image ships `pdo_pgsql`, `pdo_mysql` and `pdo_sqlite`. To
proxy Microsoft SQL Server databases, extend the Dockerfile with Microsoft's
ODBC driver and the `sqlsrv` / `pdo_sqlsrv` PECL extensions (see the README's
"SQL Server support" section for the exact steps).
