aster.Web Data / Docs Aster UI ↗

Aster Web Data / Operate

Configure and deploy

How to write the configuration file for a production deployment, keep secrets out of it, and stop the server cleanly behind a load balancer.

One YAML file describes a whole deployment: the services, the databases they read, authentication, limits and telemetry. The file holds no secrets, so it can live in version control beside your model, and an unknown key stops start-up, so a misspelt key fails the deploy instead of being silently ignored.

The configuration file

The server reads the file named by --config. Relative paths in it resolve against the directory that holds the file. This file runs one service on PostgreSQL behind a load balancer:

listen: 0.0.0.0:8080

services:
  crm:
    root: /crm
    public_url: https://api.example.com/crm
    namespace: Crm
    datasources: [model/crm]
    max_page_size: 100

databases:
  main:
    kind: postgres
    url_env: CRM_DATABASE_URL
    tls: verify-full
    ca_file: certs/db-ca.pem
    required: true
    pool:
      max: 20

auth:
  kind: jwt
  jwt:
    jwks_file: keys/jwks.json
    audience: [crm-api]
    issuer: [https://login.example.com/]

limits:
  residual_rows: 50000
  request_deadline_ms: 60000

observability:
  service_name: crm-api
  traces_exporter: otlp
  metrics_exporter: prometheus
  logs_exporter: none
  otlp_endpoint: http://otel-collector.example.com:4317

health:
  port: 9090
  host: 127.0.0.1

shutdown:
  grace_seconds: 30
  ready_delay_seconds: 5

The Configuration reference lists every key with its default.

Secrets

Secrets stay out of the configuration file. A database connection is named by an environment variable or a file, never written inline:

Aster reads the URL again on every attempt to open the database, so a changed value is used from the next attempt.

A few settings can also come from the server's own environment variables, such as ASTER_LOG for the log filter and the OTEL_* variables for telemetry. Environment variables lists them and which way each one overrides the file.

TLS

PostgreSQL and MariaDB connections take a tls mode:

Mode Behaviour
disable no TLS
prefer TLS when the server offers it, without checking the certificate. This is the default.
require TLS, without checking the certificate
verify-ca TLS, and the certificate must chain to a trusted authority
verify-full verify-ca, and the host name must match the certificate

With verify-ca or verify-full, ca_file names a PEM file of the authority. Without it, the Mozilla root certificates are used.

A plaintext or unverified connection logs a warning. To make it an error, set tls_strict: true on a database. To apply that to every PostgreSQL and MariaDB database, set startup.require_tls: true, or ASTER_WEBDATA_REQUIRE_TLS=1.

Use verify-full for connections that cross a network you do not control, because the prefer default accepts a server that presents any certificate. SQL Server, Oracle and Db2 accept fewer modes; their pages (SQL Server, Oracle, Db2) list them.

Several services

One process serves one or more services. Each service has a root path, such as /crm, and its own data sources, security, rules and limits. Roots are unique, and no root is a path prefix of another, so /a and /a/b cannot both be served. A lone service can use /.

Services can share the databases. Each database is declared once under databases. A service's data sources are on its database unless a data source names its own. The same set name may map different tables in two services, and two services may map one table. Two things are refused at start-up: one table that two services describe differently (its columns, types or keys), and one table that two services both seed.

For how a request reads data that lives in more than one database, see Several databases and Reads across databases.

What a reload applies

Change the model describes how a SIGHUP reload runs and what happens when it fails. A reload applies the services, their models, rules, scripts, operations, views, virtual sources and limits, the databases and their connections, authentication, CORS and the explain header.

These keys need a restart, because the process holds them for its whole life:

Key Why
listen (and --listen) the listening socket is bound once
health (enabled, host, port) the health listener is bound once
log logging is set up once
observability the telemetry pipeline is set up once
shutdown.grace_seconds the drain period is fixed at start
databases.<name>.setup, services.<name>.seed setup and seeding run once, when the database is first opened

If you change one of these and send SIGHUP, the reload applies everything else and logs a warning naming the key.

Shutdown behind a load balancer

On the first SIGTERM or SIGINT, the server:

  1. Sets readiness to false at once. /readyz answers 503 from this point.
  2. Keeps serving for shutdown.ready_delay_seconds (default 0), so the load balancer can take the instance out of rotation.
  3. Stops accepting connections. Requests in flight run until they finish or shutdown.grace_seconds (default 30) ends. After that they are cut.
  4. Flushes the telemetry pipeline, for up to 5 seconds.
  5. Exits.

A second signal exits at once. Set ready_delay_seconds to 5 behind a load balancer, which gives it time to see the failing readiness check. Keep grace_seconds below the time your orchestrator waits before it kills the process, so the server exits cleanly rather than being killed mid-drain.

The server logs one drain summary line when the grace ends. It reports how many requests were in flight when the grace began, how many completed and how many were cut.

Health and outages covers the readiness checks and what happens when a database goes down, and Observability the telemetry the observability section turns on.

Preview builds

A preview build expires one month after it is built. The expiry is part of the build: aster-webdata-server --version prints it, and so does the first line the server logs when it starts.

This is a preview build and will expire on 2026-11-28 13:53 UTC. Run 'aster-webdata-server update' to get the latest build.

A build past its expiry prints the expiry and the update command, exits with status 1 and does not bind its port. A running server stops at the expiry the way it stops on SIGTERM: it stops accepting, lets requests in flight finish up to shutdown.grace_seconds, and exits, after a log line that says why. In the last seven days the server logs a warning each day. Container images are preview builds too; pull a newer image rather than updating inside the container.

To get the latest build:

aster-webdata-server update --check    # installed version and expiry, latest version and expiry
aster-webdata-server update

update downloads the build for your platform from downloads.getaster.now, checks its signature against the public key built into the server, runs the new binary's --version, and replaces the binary in one step. The old binary stays beside it as aster-webdata-server.previous, so you can put it back. Nothing is changed if the download, the signature or the checks fail. update never restarts the service: restart it when you are ready. See the command line for what it refuses.

A preview build also looks at the update feed once when it starts and then daily. It is one GET of a small JSON file, sent with a User-Agent that names the version and nothing else, and it logs a line when a newer build exists. It installs nothing. To turn it off, set the key or the variable:

disable_update_check: true
ASTER_WEBDATA_UPDATE_CHECK=0 aster-webdata-server --config server.yaml