Skip to main content
airmux runtime commands read YAML from --config, then AIRMUX_CONFIG. Gateway commands use ./.airmux/airmux.yml, falling back to a shared ./airmux.yml when the standalone file is absent. Control-plane commands use ./airmux.yml. The airmux image uses deploy/docker/airmux.yml.

Docker Compose variables

YAML structure

Both planes must configure the same secret store. A remote data plane uses a management key with bundle-read, usage-ingest, and heartbeat permissions.

References

References must occupy the whole YAML scalar. The loader does not discover .env files or mutate the process environment; CLI startup owns optional .env loading. Relative file references and runtime paths resolve against the containing configuration file. A local bundle resolves its taxonomy and key references against the bundle file.

Bundle sources

Remote defaults are 30 seconds for poll and heartbeat intervals. Local bundle reload defaults to 2 seconds.

Outbound HTTP connections

The data plane creates one outbound HTTP client per worker. Configure its connection limits under data_plane.http:
The default is 100 active connections. The limit must be an integer from 1 through 65,535. Whole-value environment or file references can supply integer strings. Booleans, fractional values, null, and unbounded limits are rejected. Each worker shares one native aiohttp session across providers, remote bundle fetching, heartbeats, and usage export. Connections are reused by destination, with a 15-second idle keepalive timeout. The limit bounds active connections; idle connections to other destinations can remain cached until they expire. Four workers with max_connections: 256 can have up to 1,024 active outbound connections. Outbound requests use HTTP/1.1, including over TLS. Connect and pool acquisition share a 5-second timeout; response reads have a 120-second idle timeout. There is no overall inference deadline. Budget refreshes have a 5-second total timeout. Responses stream with backpressure, and closing a stream releases its connection slot immediately. Provider cookies are never stored, and redirects are not followed. aiohttp honors HTTP_PROXY, HTTPS_PROXY, and NO_PROXY when a proxy is configured at startup. Without a configured proxy, environment and netrc lookups are disabled to avoid thread-pool work on each request. Changing these settings requires restarting the gateway.

Application logs

Both planes write application logs to stderr. Outside dev mode, each log record is JSON. Writes are batched until 100 records or 65,536 characters accumulate, or a 100 ms timer expires, whichever happens first. A single large record is written intact. Timer delivery depends on the event loop being able to run; a blocked output stream can still block that loop. Error and critical records flush the pending batch immediately. Application shutdown and normal process exit flush remaining records. Logging outside an active event loop is immediate. Formatting happens when the event is logged, so timestamps and request IDs retain the original request context. Abrupt termination can lose buffered lines. Failed writes use Python logging’s error handling and discard the failed batch rather than retrying potentially partial output. These diagnostic logs are separate from the usage-event outbox and do not change its accounting or persistence behavior. Dev mode keeps immediate plain-text application logs. Gateway HTTP access logs remain enabled only in dev mode.

Event outboxes

SQLite export defaults to every 5 seconds. Its cache directory defaults to .airmux beside the configuration file, and the outbox writes events.db there. Workers sharing one gateway cache directory coordinate through that outbox. The file sink resolves path relative to the configuration file, creates missing parent directories, and creates new files with mode 0600. It appends one complete usage event per line, and processes sharing a local file serialize their writes. Restarting appends to the existing file. It has no export queue, deduplication, rotation, or fsync guarantee. Use it on a local POSIX filesystem. A file write failure terminates the worker instead of silently discarding usage. SQLite and file requests do not wait for local persistence. If the outbox cannot accept an event, the gateway returns 503 metering_capacity_exhausted before starting that provider attempt. Graceful shutdown writes accepted events to local storage. SIGKILL, machine failure, power loss, or storage failure can lose events not yet written.

Budget backends

Budget configuration is independent of the bundle source and event outbox. The control_plane backend is best effort; missing, mismatched, or expired state allows requests. With budget.kind set to none, budget rules always allow requests.

Secret stores

The environment store checks AIRMUX_SECRET_PROVIDER_<PROVIDER> before <PROVIDER>_API_KEY. Scope and credential name are not part of its lookup, so it cannot isolate tenant-specific values.