Configuration

Resql reads a single YAML file at startup. The path is set with --config <path> or the RESQL_CONFIG env var (default /app/resql.yaml inside the container).

All fields have safe defaults except sql_dir. Every unknown YAML field is rejected — typos fail startup instead of silently ignoring config.

Top-level fields

FieldTypeDefaultPurpose
sql_dirpath(required)Directory scanned for .sql files at startup.
serverobjectsee belowHTTP listener settings.
datasourceslist[]Configured database connections.
project_datasource_mapmap{}Override which datasource a URL project routes to.
allow_datasource_headerbooltrueHonour X-Datasource: <name> on requests.
corsobjectsee belowCORS layer settings.
loggingobjectsee belowLog level + format.

server

FieldTypeDefaultPurpose
bindstring0.0.0.0:8080Listener address.
max_body_bytesinteger1048576 (1 MiB)Inbound JSON body cap. Overflow → HTTP 413.
request_timeout_secondsinteger30Reserved. Currently informational.

datasources (list of)

FieldTypeDefaultPurpose
namestring(required)Unique label. Referenced from URL project or X-Datasource header.
urlstring(required)Connection URL. Supported schemes: postgres://, postgresql://, sqlite:.
usernamestring""Username to inject in the URL userinfo. Ignored if the URL already has one.
password_envstring""Env-var name holding the password. Never store passwords in this file.
max_connectionsinteger10Pool size ceiling.
acquire_timeout_secondsinteger5Per-acquire wait.

Startup refuses in any of these cases:

  • Two datasources share a name.
  • A username is set but password_env is empty.
  • password_env names a variable that is not set in the environment.
  • project_datasource_map refers to a name absent from datasources.

project_datasource_map

Maps URL project segment → datasource name. When a request arrives at POST /crm/find-user, the default behaviour is to look up a datasource named crm. Add an entry crm: primary-db to route it elsewhere.

Falls back to the project name if the map has no entry — a bare sql_dir layout of sql/foo/… will look up datasource foo with no config.

allow_datasource_header

When true (default), the X-Datasource: <name> request header overrides both the map and the project name. Set to false in locked-down deployments where operators pick datasources centrally.

cors

FieldTypeDefaultPurpose
allowed_originsstring** = any; otherwise comma-separated exact origins.

logging

FieldTypeDefaultPurpose
levelstringinfo,resql=debugtracing_subscriber EnvFilter directive.
formatstringtexttext or json.

The RESQL_LOG env var overrides level at runtime without touching the config file.

Env-var overrides

Any string in password_env is looked up in the process environment. Nothing else is env-driven — the config file is authoritative. If you need per-environment overrides, use one config file per environment or mount a config file from a secret at runtime.

Complete example

server:
  bind: "0.0.0.0:8080"
  max_body_bytes: 2097152   # 2 MiB

sql_dir: "/app/sql"

allow_datasource_header: true

project_datasource_map:
  legacyapp: primary
  reports: analytics

datasources:
  - name: primary
    url: "postgres://pg-primary.internal:5432/appdb"
    username: "resql"
    password_env: "RESQL_PRIMARY_PASSWORD"
    max_connections: 20
  - name: analytics
    url: "postgres://pg-analytics.internal:5432/warehouse"
    username: "resql_ro"
    password_env: "RESQL_ANALYTICS_PASSWORD"
    max_connections: 5

cors:
  allowed_origins: "https://ops.internal, https://console.internal"

logging:
  level: "info,resql=debug,sqlx=warn"
  format: "json"