aster.Web Data / Docs Aster UI ↗

Aster Web Data / Reference

Configuration

Every configuration key, its type, default and effect.

Keys

The server reads one YAML file. Unknown keys are an error, so a misspelt key stops the start-up rather than being ignored. Relative paths resolve against the directory of the configuration file. Secrets never go in the file: a database names the environment variable or file that holds its connection URL or password.

Types: string, int, bool, list (YAML list), map, and file (a path, relative to the configuration file). A duration is a whole number with a unit: ms, s, m or h (for example 5s).

Top level

Key Type Default Effect
listen string 127.0.0.1:8080 Address to bind. Port 0 picks a free port, and the server prints the one it bound.
services map required One entry per service. At least one. See Services.
databases map required One entry per database. At least one. See Databases.
startup section see below What start-up does when a database cannot be opened.
limits section see Limits Request limits for every service, unless a service sets the key itself.
auth section see Authentication How a request becomes a caller.
cors section absent Cross-origin access for browser clients. Absent: no CORS headers, so browsers allow same-origin pages only.
request_facts section see below What rules may read about a request besides its caller.
i18n section see below Message files $metadata is translated with.
log section see below Log format and level.
shutdown section see below How a stop drains requests in flight.
updates section see below Whether a preview build looks for a newer build.
scripts section see below Ceilings that a script's own limits: cannot exceed.
http map none Named connections that scripts make HTTP calls on. See HTTP connections.
explain section see below The explain response header. See Explain.
observability section see below Traces, metrics and logs export.
observe section see below Per-plan-shape request metrics.
health section see below The health listener and its endpoints.

Startup

Key Type Default Effect
startup.require_databases bool false Every database must open and pass its check at start-up, or the process stops. Overridden by ASTER_WEBDATA_REQUIRE_DATABASES.
startup.require_tls bool false Every PostgreSQL and MariaDB database refuses a plaintext or unverified connection. Overridden by ASTER_WEBDATA_REQUIRE_TLS. Independent of require_databases.

Services

Each key below sits under services.<name>. The name uses letters, digits, _ and -. It appears in logs and in the aster_webdata.service metric label, and it gives the default root.

Key Type Default Effect
root string /<name> The path the service is mounted at. Roots are unique, and no root is a path prefix of another (/a and /a/b cannot both be roots).
public_url string http://<listen><root> The absolute service root clients see, in context URLs and next links. Set it behind a proxy.
openapi bool true Publishes <root>/openapi.json (OpenAPI 3.1) from the same model as $metadata.
namespace string Aster The CSDL schema namespace.
datasources list required DataSource files (.ds.xml, .ds.yaml, .ds.yml), or directories that hold them.
database string the only database The database the sources are on, unless a DataSource names its own with database:. With several databases, a source with neither is refused at load.
seed file none A JSON object of entity set name to an array of entities, for this service's sets. Loaded once per database: into memory, or into the tables with setup: recreate.
max_page_size int 1000 Server-driven paging: the largest page before a next link. A larger $top arrives in pages of this size, not as a refusal. Clients can ask for less with Prefer: odata.maxpagesize.
select_without_keys bool false When false, a $select adds the key properties to the response. When true, it returns only what was selected.
etag_opt_out list [] Entity sets without an ETag (the same as etag: none in the DataSource). Writes to them are last write wins.
updates_without_read list [] Entity sets that accept an update of a row the caller may write but not read, with If-Match: *. Published as AsterData.UpdatesWithoutRead.
deletes_without_read list [] Entity sets that accept a delete of a row the caller may delete but not read, with If-Match: *. Published as AsterData.DeletesWithoutRead. Separate from the update option.
rules file none A rules file of server rules over claims, request facts and data. A rule that does not compile fails the load, and the error names it.
security.<Set>.read, .insert, .update, .delete map none Access rule for the operation: authenticated (bool), roles (list, any one), never (bool). An absent operation allows anyone.
security.<Set>.owner string none The property holding the owner's user ID. A caller sees and changes only their own rows.
context.values.<name>.type string required String, Int64, Decimal, Boolean, Guid or Date. Name: lower case letters, digits and _.
context.values.<name>.required bool false A request without the value gets 400.
context.values.<name>.authorise.set string none The set a value is checked against.
context.values.<name>.authorise.filter string none A $filter over that set, which may read context.<name>, user.<property> and $user. Fails with 403 when no row matches.
context.user_source.set string none The entity set with one row per user. Its properties are the request facts user.<property>.
context.user_source.subject string none The property holding the token's subject.
context.user_source.required bool false A caller with no row gets 403.
limits.* section the top-level limits Any key of Limits, for this service only. A key left out keeps the top-level value.

Databases

Each key below sits under databases.<name>. The name is for operators (logs, metrics, and the readiness listener). Clients never see it.

Key Type Default Effect
kind string required postgres, mariadb, sqlite, duckdb, mssql (SQL Server), oracle, db2, tigerbeetle or memory. postgres, mariadb and memory are in the default build, and the others where the build includes them. An unknown kind is a start-up error that lists the kinds the build has.
url_env string none Environment variable that holds the connection URL. Read again on every attempt to open the database.
url_file file none File that holds the connection URL. Read again on every attempt.
host, port, user, database string, int, string, string none The parts form, used instead of a URL. database is the connection's database (MariaDB: also its default schema).
password_env, password_file string, file none The password for the parts form.
schema string the kind's default The default schema of the database's sources. A source's own schema wins. PostgreSQL: public. DuckDB: main. MariaDB: the connection's database.
tls disable, prefer, require, verify-ca or verify-full prefer prefer uses TLS when offered, without verification. A plaintext or unverified connection logs a warning. SQL Server, Oracle and Db2 accept fewer modes (see their pages); SQLite, DuckDB and TigerBeetle take none.
ca_file file Mozilla roots PEM certificates that verify-ca and verify-full trust.
tls_strict bool false A plaintext or unverified connection is a start-up error. Independent of required. Also set for every database by startup.require_tls.
collation string none The collation published as AsterData.Collation for text fields that declare none. Checked against each column at start-up.
setup existing or recreate existing existing uses the tables as they are. recreate creates a missing schema (it never drops one), drops and creates each source's table, then loads the seeds. For scratch and test databases only.
read_only bool false No source on the database may write. The server refuses at load any set, binding or action that writes, and any setup: recreate or seed.
required bool false A database that cannot be opened, or fails its start-up check, stops the process. By default the server starts, the sets stored on the database answer 503, and the server keeps retrying.
retry.initial duration 1s First reconnection delay. Backoff is exponential with jitter and no attempt limit.
retry.max duration 60s Longest reconnection delay.
pool.max int 10 Most connections the pool opens.
pool.min_idle int 0 Connections kept open while the pool is in use.
pool.connect_timeout duration 5s How long a connection attempt may take.
pool.checkout_timeout duration 5s How long a request waits for a free connection. An exhausted pool answers 503 PoolExhausted.
options map none Settings of the database kind's own. PostgreSQL: single_statement (bool, default true): $expand and deep inserts run as one statement. Set false for the multi-statement form. TigerBeetle: cluster_id, addresses, timeout_ms.

Limits

Limits sit under limits at the top level, and under services.<name>.limits for one service. Each key is optional. A key a service leaves out keeps the top-level value, and a top-level key left out keeps the built-in default.

Key Type Default Effect
residual_rows int 50000 Most rows the in-engine executor holds at once. A read that needs more fails with 400 QueryTooExpensive.
max_insert_rows int 10000 Most rows one insert may take.
max_batch_size int 1000 Most operations in one $batch.
max_expand_depth int 8 Deepest $expand nesting.
max_in_set int 10000 Most items in one in list or array.
request_deadline_ms int 60000 Time a request may run before it is cut.
statement_timeout_ms int 30000 Time one database statement may run. A timeout answers 503 Timeout.
max_traverse_depth int 64 Deepest walk of a hierarchy (ancestors, descendants, traverse).
max_body_bytes int 16777216 (16 MiB) Largest request body accepted.
unbounded_residual warn or refuse warn What a $skip or $count does when it would run in memory over every row of an unbounded backend fetch. warn runs it, logs it, and counts it. refuse answers 501.
key_batch int 8192 Most keys one statement of a key batch carries ($expand and navigation across databases). Larger levels are read in chunks. Must be at least 1.
max_orderby_items int 128 Most items in one $orderby. More answers 400 QueryTooExpensive. Must be at least 1.
max_lambda_depth int 4 Deepest nesting of any and all in one expression. Deeper answers 400 QueryTooExpensive.

Authentication

Key Type Default Effect
auth.kind anonymous, fixed, dev-headers or jwt anonymous Which authenticator turns a request into a caller.
auth.user string none fixed only: the user ID every request runs as. Absent: anonymous with the roles below.
auth.roles list [] fixed only: the roles every request has.
auth.user_header string X-Aster-User dev-headers only: the header naming the user.
auth.roles_header string X-Aster-Roles dev-headers only: the header listing roles, comma-separated.
auth.jwt.secret_env string none Environment variable that holds an HMAC secret of at least 32 bytes.
auth.jwt.public_key_file file none PEM public key (RSA, EC or Ed25519).
auth.jwt.jwks_file file none JWKS file. The token's kid picks the key. Read from a local file only.
auth.jwt.algorithms list the one the key implies Accepted algorithms, for example HS256, RS256, ES256 or EdDSA. Required with a JWKS.
auth.jwt.audience list required A token must name one of these audiences.
auth.jwt.issuer list none A token must name one of these issuers. Absent: not checked.
auth.jwt.user_claim string sub Claim that holds the user ID.
auth.jwt.roles_claim string roles Claim that holds the roles: an array, or one space- or comma-separated string.
auth.jwt.leeway_seconds int 60 Clock skew allowed on exp and nbf.

dev-headers lets any client choose its own user and roles. Use it for development only. The server writes a warning at start-up when it is set.

Request facts and CORS

Key Type Default Effect
request_facts.headers list [] Request headers that rules may read, in any case. A header not listed reads as null. Listed headers are added to Vary.
request_facts.client_address_header string none Header a trusted reverse proxy sets to the client's address (for example X-Real-IP). Absent: the address the connection came from. Set it only behind a proxy that overwrites the header.
cors.allowed_origins list required Allowed origins, for example https://ui.example.com. * allows any origin.
cors.allow_credentials bool false Sends Access-Control-Allow-Credentials: true. Cannot be combined with *.
cors.max_age_seconds int 600 How long a browser may cache a preflight answer.
cors.extra_allowed_headers list [] Request headers a page may send, beyond the OData headers the server always allows.

Internationalisation

Key Type Default Effect
i18n.default string none Language of the default document. Absent: message references are published unresolved.
i18n.messages map {} Per language tag, a JSON file of message key to text. $metadata resolves references in the Accept-Language language.

Logging and shutdown

Key Type Default Effect
log.format json or text json One JSON object per line, or text, on stderr.
log.level error, warn, info, debug or trace unset One level for every target. Unset: the default directives, which are warn, with Aster's targets at info. ASTER_LOG and RUST_LOG override it.
shutdown.grace_seconds int 30 After the first stop signal, how long requests in flight may run before they are cut. A second signal stops the process at once.
shutdown.ready_delay_seconds int 0 After the first signal, readiness goes false at once, and the server keeps serving this long before it stops accepting. Set 5 behind a load balancer.

Updates

Key Type Default Effect
disable_update_check bool false In a preview build, look at the update feed once at start-up and then daily, and log one line when a newer build exists. It installs nothing. true turns it off, as does ASTER_WEBDATA_UPDATE_CHECK=0. Other builds never look. See Preview builds.

Scripts

Key Type Default Effect
scripts.ceilings map built-in ceilings The most any script may use, whatever its own limits: say. Keys: memoryMiB, runMs, turnMs, hostCalls, decimalCalls, recursion, stackKiB, printBytes. An omitted key keeps its built-in ceiling.

HTTP connections

Each key below sits under http.<name>. The name is what a script's call names (connection= in Python's http.get(...), connection: in TypeScript's fetch(...)), and it is the aster_webdata.http.connection label on the outbound metrics. Connections belong to the server, so every service can use them. Virtual data sources shows one in use.

Key Type Default Effect
base_url string required An http or https URL with a host, no query and no credentials. A call's relative path is joined to it.
auth.bearer_env, auth.bearer_file string, file none Sends Authorization: Bearer with the token.
auth.basic map none Sends Authorization: Basic. Takes user, and password_env or password_file.
auth.header string none The name of an API-key header. Takes value_env or value_file for its value.
timeout_ms int 30000 The most a call may take, retries and waits included. A call may set its own. The request's deadline is the outer bound.
retries int 2 Attempts after the first. The engine retries on a connection error, 429, 502, 503 or 504, for GET, HEAD, PUT, DELETE and OPTIONS. A POST or PATCH is retried only when the call asks. Waits are exponential with jitter, from 100 ms doubling to at most 10 s, or the Retry-After the server sent.
rate_limit.per_second number none Calls per second, as a token bucket shared by every call on the connection in the process. A call waits for its token.
rate_limit.burst int per_second, at least 1 The size of the bucket: the calls that may go at once after a quiet spell.
headers map none Headers sent on every call. A call's own headers win. The credential's header cannot be set here.
ca_file file Mozilla roots PEM certificates to verify the server with instead of the Mozilla roots.
max_response_bytes int 10485760 (10 MiB) A larger response ends the call with HttpResponseTooLarge.

An auth block takes exactly one form, and the credential is never written inline. A variable named by *_env is read at start-up, and an unset one stops the start-up. A file named by *_file is read at start-up and again on every call, so a rotated secret takes effect without a restart. Scripts never see the value. An unknown key under http.<name> is a start-up error, as everywhere in the file.

http:
  tracker:
    base_url: http://127.0.0.1:8090/api/v1
    auth:
      bearer_env: TRACKER_TOKEN
    timeout_ms: 10000
    retries: 3
    rate_limit:
      per_second: 10
      burst: 20
    headers: {Accept: application/json}

Explain

Key Type Default Effect
explain.enabled bool false Serves the x-aster-explain header. Off, the x-aster-explain-request header and the aster.explain query option are ignored.
explain.role string none Only a caller whose roles include this one gets the header. Unset, any caller does, which suits local development.

See The explain header.

Observability and health

The observability values come from the file, and the environment overrides them.

Key Type Default Effect
observability.service_name string aster-webdata Service name on exported telemetry. Environment: OTEL_SERVICE_NAME.
observability.disabled bool unset Turns the telemetry pipeline off. Environment: OTEL_SDK_DISABLED.
observability.traces_exporter otlp, prometheus or none unset (no export) Environment: OTEL_TRACES_EXPORTER.
observability.metrics_exporter otlp, prometheus or none unset (no export) Environment: OTEL_METRICS_EXPORTER.
observability.logs_exporter otlp or none unset (no export) Environment: OTEL_LOGS_EXPORTER.
observability.otlp_endpoint string none Environment: OTEL_EXPORTER_OTLP_ENDPOINT. Put credentials in OTEL_EXPORTER_OTLP_HEADERS, from a secret store, never in this file.
observe.plan_shapes on or off on Counts and times each read by its plan shape. off makes the request path skip this work. See Metrics and logs.
observe.max_plan_shapes int, 1 to 100000 1000 Most shapes tracked separately per service. Others are counted together as _other.
health.port int none Separate listener for /healthz, /readyz and /metrics, and for /shapes, which only this listener serves. Absent: the first three share the OData port.
health.host string 127.0.0.1 Address of the separate listener. Environment: ASTER_HEALTH_HOST.
health.enabled bool true false turns /healthz, /readyz and /metrics off.
health.ping_interval_seconds int 5 Seconds between background pings of each database that is up.

The health port also reads ASTER_HEALTH_PORT, which overrides health.port.

Environment variables

The server reads these names directly. The file's keys can name others: url_env, password_env and auth.jwt.secret_env each name the variable they read.

Variable Effect
ASTER_LOG Log filter directives. Overrides RUST_LOG and log.level.
RUST_LOG Log filter directives, used when ASTER_LOG is unset.
ASTER_HEALTH_PORT, ASTER_HEALTH_HOST Override health.port and health.host.
ASTER_WEBDATA_REQUIRE_DATABASES 1 or true, or 0 or false. Overrides startup.require_databases.
ASTER_WEBDATA_RESIDUAL_ROWS A positive integer. Sets limits.residual_rows when the configuration file does not.
ASTER_WEBDATA_MAX_INSERT_ROWS A positive integer. Sets limits.max_insert_rows when the configuration file does not.
ASTER_WEBDATA_MAX_QUEUE_OPS A positive integer. Sets limits.max_batch_size when the configuration file does not.
ASTER_WEBDATA_UPDATE_CHECK 0 turns off the preview build's look at the update feed, whatever disable_update_check says.
ASTER_WEBDATA_REQUIRE_TLS 1 or true, or 0 or false. Overrides startup.require_tls.
OTEL_SDK_DISABLED, OTEL_SERVICE_NAME, OTEL_TRACES_EXPORTER, OTEL_METRICS_EXPORTER, OTEL_LOGS_EXPORTER, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_HEADERS Telemetry export. Each has an observability key, and the environment wins over the file.