Skip to content

Configuration

brookie edited this page Oct 8, 2026 · 9 revisions

Configuration

This page covers the main config file (config.yaml): its keys, every setting, the layout of the config folder, running several configs side by side, and when edits take effect. Remote and database files have their own pages: Routing and Restrictions and SQL Database Support.

# api_dock_config/config.yaml
name: my-api
description: Detections and core services
authors:
  - Your Name

remotes:
  - core                 # remotes/core.yaml, a folder remotes/core/ of versions,
                         #   or an entry in remotes/config.yaml
databases:
  - birdnet              # databases/birdnet.yaml, databases/birdnet/, or a `slugs` entry
  - owl

restricted:
  - route: "*"
    method: delete       # block DELETE on every remote route

settings:
  add_trailing_slash: false
  follow_redirects: false
  timeout: 30
  duckdb:
    memory_limit: 600MB
    threads: 2
    max_concurrent_queries: 2

expose: true             # adds /databases, /remotes and /sources

Keys

Key Meaning
name, description, authors Metadata returned by GET /. authors is a list of strings or mappings (e.g. {name: ..., email: ...}); it is returned as written
remotes Remote APIs to proxy. Each entry is the name of a file in remotes/ (without .yaml), of a version folder remotes/<name>/, or of an entry in remotes/config.yaml
databases Databases to serve. Each entry is the name of a file in databases/, a version folder databases/<name>/, or a database defined in the shared config's slugs; - from: <lookup> stands for every database a lookup generates
endpoints A list returned under endpoints in GET / (default ["/"]). It is informational only and adds no routes. Catalog routes from expose are appended automatically
restricted, routes Global restrictions and allow-list for remote routes. See Routing and Restrictions
cookies, authentication Defaults inherited by database configs (see below). See Authentication and Cookies
settings HTTP and query behavior (see Settings)
expose Optional catalog endpoints (see Catalog endpoints)

GET / returns:

{"name": "my-api", "description": "Detections and core services", "authors": ["Your Name"],
 "endpoints": ["/", "/databases", "/remotes", "/sources"], "remotes": ["core", "birdnet", "owl"]}

The remotes field lists remotes and databases together.

Remote and database names

  • A remote's URL prefix is the name inside its file (the file name is used if the file has no name). For a versioned remote, the folder name remotes/<name>/ is the prefix. For a remote defined in remotes/config.yaml, its key is the prefix.
  • A database's URL prefix is its entry in databases:, which is also its file or folder name. A name key inside a database file is not used for routing.

Inherited cookies and authentication

A database config that has no cookies key gets the main config's cookies, and one with no authentication key gets the main config's authentication. A database's own value replaces the main config's entirely; the two are not merged.

Remote requests don't use the main config's cookies or authentication: they use only what the remote's own file sets. Details, including which headers and cookies reach a remote, are in Authentication and Cookies.

Restrictions

restricted and routes in the main config apply to remote requests only (combined with each remote file's own lists). Database routes are not filtered by them; a database serves exactly the routes its config defines. See Routing and Restrictions.

Settings

All settings are optional.

Setting Default Meaning
add_trailing_slash true Append / to the path forwarded to a remote (/core/projects → <url>/projects/). Avoids redirects from APIs that require the slash; set false for APIs that reject it
follow_redirects true true: API Dock follows a remote's redirects and returns the final response. false: the 3xx response and its Location header go back to the client, which is what you want for redirects to presigned S3 URLs
timeout 10 Timeout in seconds for requests to remotes. null or false disables it (a stalled remote can then hold a connection open indefinitely). Raise it for slow upstreams that would otherwise return 502
base_path none An extra URL prefix the API also answers under, e.g. /dock. /dock/birdnet/latest/detections/ is handled as /birdnet/latest/detections/; paths without the prefix keep working. Use it when a proxy or CDN forwards a path prefix without stripping it. dock, /dock and /dock/ are equivalent
duckdb none Options for DuckDB queries (see below)
lookups none The manual lookup refresh endpoint: {refresh_route: /admin/lookups, token: env:NAME}. See Lookups

duckdb

Each database query that DuckDB runs gets a new in-memory DuckDB connection, in a worker thread so a slow query doesn't hold up other requests. Every key under duckdb except max_concurrent_queries is applied to that connection as SET <key> = <value>, so any DuckDB setting works.

settings:
  duckdb:
    memory_limit: 600MB         # SET memory_limit = '600MB'
    threads: 2                  # SET threads = 2
    temp_directory: /tmp/duckdb # where DuckDB spills when over memory_limit
    max_concurrent_queries: 2   # at most 2 DuckDB queries at once; others wait
  • max_concurrent_queries caps how many DuckDB queries run at once in the process; further queries wait for a free slot. It must be a positive integer. With no value there is no cap.
  • memory_limit applies to each query. Over the limit, DuckDB spills to disk or fails that query instead of the process running out of memory.
  • Sizing: keep memory_limit × max_concurrent_queries below the memory of the machine, leaving room for Python. For example, on a 2 GB instance with one vCPU, memory_limit: 600MB, threads: 2 and max_concurrent_queries: 2.
  • Option names must be plain identifiers. An invalid duckdb section stops startup.

Routes that run natively on PostgreSQL don't use DuckDB; see PostgreSQL.

Catalog endpoints

expose adds read-only endpoints that list the configured databases, remotes, or both, with their versions. It is off unless you set it:

expose: true    # GET /databases, /remotes and /sources

Custom routes, string output and include filters are covered in Catalog Endpoints.

Config folder layout

api_dock_config/
├── config.yaml              # main config (the default one)
├── config_staging.yaml      # another main config (optional)
├── remotes/
│   ├── config.yaml          # optional shared remote config (inline remotes)
│   ├── core.yaml            # unversioned remote
│   └── weather/             # versioned remote
│       ├── 0.1.yaml
│       └── 0.2.yaml
└── databases/
    ├── config.yaml          # optional shared database config
    ├── places.yaml          # unversioned database
    └── birdnet/             # versioned database
        ├── 2.4.yaml
        └── 3.0.yaml
  • Remote and database files are read from remotes/ and databases/ next to the main config file, whichever folder that is.
  • databases/config.yaml is the shared database config: global tables, schemas, PostgreSQL connections, inline databases (slugs) and routes shared by every database. It is not a database itself; don't list config under databases:. See Shared Database Config.
  • Versioned remotes and databases are covered in Versioning.

Multiple configs

Any .yaml file at the top of api_dock_config/ is a main config. Start one by name (with or without .yaml):

api-dock start                  # api_dock_config/config.yaml
api-dock start config_staging   # api_dock_config/config_staging.yaml
api-dock describe config_staging

All main configs in the folder share the same remotes/ and databases/ files; each chooses which of them to serve. Running api-dock with no command lists the available configs.

If api_dock_config/<name>.yaml doesn't exist, the CLI falls back to the example config of that name bundled with the package (so api-dock start with no local folder serves the bundled example). If neither exists it exits with an error. A main config that exists but isn't valid YAML, or isn't a mapping, stops startup with its path (since 0.10.0; before, RouteMapper silently served an empty API).

When edits take effect

  • Read once at startup: the main config file, so the list of remotes and databases, settings, expose, the global restricted/routes, and the main config's inherited cookies/authentication. PostgreSQL connections (database.connections in the shared config) are also fixed at startup. Restart to change any of these.
  • Read on every request: remote files, database files and the shared remotes/config.yaml and databases/config.yaml. Edits to them, including new version files, apply to the next request without a restart.
  • Read at startup and on refresh: lookup rows. Lookups run at startup, then every refresh interval or on demand; databases and versions they generate change only then.

Database configs are only checked at startup. A database file edited while the server runs is used as-is; an error in it surfaces as an error response rather than a refused start. Restart after editing database configs to have them checked.

Clone this wiki locally