Build

aria.yaml reference: every field

The complete aria.yaml (version 1) reference: services, databases, env, references between services, backups, limits, and two worked examples.

Updated Markdown

In this page
  1. What does a whole file look like?
  2. What are the top-level fields?
  3. What can a service say?
  4. What can a database say?
  5. What can a variable say?
  6. How does one service or database reference another?
  7. What can the backup block say?
  8. What are registries and resources?
  9. What are the limits?
  10. Example 1: three services, Postgres and Redis
  11. Example 2: a web app on self-hosted Supabase
  12. How do I check the file?

aria.yaml is the one file that tells Aria what your app needs to run: its services, its databases, and which variable goes to which service. Put it at the root of your repository (or tell Aria where it is). Aria AI or your coding agent usually writes it, Aria checks it with line numbers, and Aria applies it on the first launch and on every push. Unknown keys are refused, so a typo is caught before anything is deployed.

What does a whole file look like?

YAML
version: 1
name: my-app
services:
  web:
    type: web
    path: apps/web
    port: 3000
    healthcheck: /
    domain: "@"
databases:
  main:
    type: postgres
    migrations: db/migrations
env:
  DATABASE_URL:
    services: [web]
    from: main.url
resources:
  users: 200

Only version and services are required.

What are the top-level fields?

Field Type Default What it does
version 1 required The schema version.
name text, up to 60 characters none A label for people.
services map of name to service required What runs. At least one, at most 12.
databases map of name to database none Up to 6.
env map of NAME to variable none Up to 200 variables.
email { enabled, from } off A test inbox that catches the mail your app sends over SMTP so you can read it in Aria. It delivers to nobody. To send real email, turn on Aria Mail.
registries map of name to login none Logins for private image registries.
backup backup settings none Your own backup schedule, retention and hooks.
resources sizing hints none Traffic, people at once, data region.

Names of services, databases, volumes and registries use lowercase letters, digits and dashes, start with a letter, and have at most 31 characters. A service cannot be called supabase, inbox or email, or end in -supabase. A database cannot share a service’s name. The file is up to 64 KB.

What can a service say?

services.<name> describes one thing that runs.

Field Type Default What it does
type web, api, worker, static required web, api and static are public and have a port. A worker has neither. A static site is built once, then served. See Deploy a website.
path folder in the repository . The service’s own folder. A push rebuilds the service when files under it change.
context folder same as path The build context, for a monorepo that builds from its root (.). Install, build and start commands then run from it.
dockerfile path from the repository root none Build with this Dockerfile. Aria does not look for one, so set it whenever the service has one. It must sit inside the build context. install, build and start are then ignored.
image registry/name:tag none Run a prebuilt image instead of building. The tag can hold ${commit}, the full commit SHA Aria deploys. Not with path, context, dockerfile, install, build or start, and not on static.
command list of arguments none Replaces the image’s own command. Needs an image or a dockerfile. Not with start.
runtime text, up to 40 none A hint for sizing.
framework text, up to 40 none A hint for sizing. A Next.js build needs more memory than a Go one.
install, build, start one-line command Aria’s detection Used when there is no Dockerfile. One line, up to 1,000 characters, with no backticks, single quotes or $( ).
port 1 to 65535 3000 for web, api, static; none for a worker The port the service listens on. Aria sets PORT and HOST=0.0.0.0 for every service.
healthcheck path / Where Aria asks whether the service is up. A plain path with no query string, answered quickly without a login, with no 4xx or 5xx. Set it when / redirects or needs a login.
public true or false true, false for a worker Whether the service has an address on the internet. A worker cannot be public.
domain @, a name, or a full host none Its address on your own domain. @ is the domain itself, api is api.yourdomain.com. Public services only, and two services cannot share one. See Domains.
realtime true or false false The service holds long connections such as WebSockets or live audio. Sizing counts connections, not page views. Not on static.
migrate one-line command none Your app’s own migration command, such as prisma migrate deploy. It runs once per deploy in the newly built image, with the service’s variables, before the new version takes traffic. If it fails, the old version keeps serving. It also runs before restarts, so it must be safe to run again. Put it on one service.
volumes map of name to absolute folder none Folders that keep their files across every deploy and restart, up to 8 per service. A new volume starts with what the image has at that folder. Not on static.
depends_on list of service names none Services that must start first. Aria already orders services by what they read, so you rarely need it. Circular dependencies are refused.
stop_grace_period 1 to 900 seconds the platform’s How long the service gets to finish when it is stopped or replaced.
memory MB (1536) or text ("1.5G", "768M") from 128M to 64G twice Aria’s estimate The service’s memory limit. It replaces Aria’s estimate when sizing the server, so the plan must have room for it.
shm_size MB or text from 64M to 32G none Shared memory for Chromium or desktop containers. It cannot exceed memory.
gpu true, or { memory, count } none The service needs an NVIDIA GPU. memory is GPU memory with a unit such as "24G" (1G to 192G), count is 1 to 8. A stack that asks for a GPU only fits a GPU plan, and GPU servers may be available on request rather than straight away. Leave it out for code that only calls a hosted AI API.
pids_limit 32 to 65536 none The most processes and threads at once.
access public, owner public With owner, Aria’s sign-in sits in front of the service and only the workspace’s Owners and Admins get through.
access_exceptions up to 20 paths none With access: owner, paths that skip the sign-in because your app checks them itself. /hooks/* matches everything under it. Other paths match exactly. /.aria/* is reserved.

A static site cannot use image, volumes, gpu, stop_grace_period, shm_size, realtime or migrate. A worker cannot be public or have a domain.

What can a database say?

databases.<name> adds one database. Aria runs Postgres, Redis and Supabase.

Field Type Default What it does
type postgres, redis, supabase required Which database.
version text latest Aria offers Postgres 16 or 17, Redis 7. Leave it out unless you need to pin. Not for Supabase.
path folder supabase Supabase only. The folder laid out like the Supabase CLI’s: migrations/, seed.sql, functions/, config.toml. Two Supabase databases each need their own.
migrations folder none Postgres only. A folder of .sql files applied in the order of their leading number, each once. Only names that start with digits and an underscore count, like 0001_init.sql.
seed .sql file, or false none Postgres: a file that runs once, on a new database. Supabase: only false, which stops seed.sql from running.
auth { smtp } none Supabase only. Real sign-up and password-reset email through your SMTP provider. See Self-hosted Supabase.
domain @, a name, or a full host api, or supabase if a service is named api Supabase only. The Supabase gateway’s address on your domain.
extensions list none Postgres only. Any of vector, pg_trgm, btree_gin, btree_gist, fuzzystrmatch, citext, pgcrypto, uuid-ossp, hstore, unaccent. vector gives you pgvector.
names list of names none Postgres only. More databases on the same server, each owned by a login of the same name.

More on each kind is on Databases and Self-hosted Supabase.

What can a variable say?

env.<NAME> decides which services get a variable and where its value comes from. A variable reaches only the services it lists. With no services it reaches every service, so always give a secret a services list.

Field Type Default What it does
services list of service names every service Who gets it. A Supabase database’s name delivers it to that Supabase’s edge functions.
from name.attribute none A value Aria knows, such as a database or service address. See the table below.
template text with ${name.attribute} none A value built from references and kept current when addresses change, like wss://${api.public_host}/live.
generate secret, password, uuid none Aria makes the value once and keeps it.
value text none A fixed setting that is not secret, like production. Put numbers and true in quotes.
required true or false false The services that get it wait until it has a value.
secret true or false true for a value only a person has, and for a generated one Masks the value everywhere. Not allowed together with value.
build true or false true for NEXT_PUBLIC_, VITE_, PUBLIC_, REACT_APP_, NUXT_PUBLIC_, EXPO_PUBLIC_, GATSBY_ The value is needed while building, not only at runtime.
description text, up to 300 none Shown to the person who has to enter it.
database a name from a Postgres names list none With from: <postgres>.url, points at one of its databases, with that database’s own login.

Use only one of from, template, generate and value per variable. Everything built into a browser bundle is public: never wire a credential into a variable with a browser prefix. The full story is on Environment variables.

How does one service or database reference another?

from: name.attribute and ${name.attribute} read a value Aria knows. name is a key under databases or services, or the word email. Aria works out every address before it builds anything.

Kind Attributes you can read
Postgres url, host, port, user, password, database
Redis url, host, port, password
Supabase url, public_host, internal_url, anon_key, service_role_key, db_url, jwt_secret
A service url, public_host, internal_url, host, port
email smtp_url, host, port, from (needs the email block on)
backup status_url (needs a backup block)

public_host is the public address without https://, handy for building a wss:// URL in a template. url and public_host need a public service. From another service, read internal_url. Aria orders services by what they read, so a frontend that reads an API’s address waits for the API.

What can the backup block say?

Without a backup block, Aria already backs up your databases and volumes every night. Add one to choose the schedule and what is kept. See Backups.

Field Default What it does
schedule once a night A five-field cron in UTC, at most once an hour, like "0 3 * * *".
retention 14 daily, 8 weekly, 6 monthly The newest set of each of the last N days (1 to 90), weeks (0 to 52) and months (0 to 36).
volumes every volume Volume names to include. Write service/name when two services use the same name.
exclude none Paths inside volumes to leave out. ** matches any folders, * matches within a name.
hooks none Commands to run in a running service before (pre) and after (post) the copy, with a timeout of 1 to 600 seconds. A failing pre hook fails the backup.
encryption Aria’s workspace key recipient_secret names a variable holding your own age public key. Aria then cannot read your backups, and a restore asks for your key file.

What are registries and resources?

registries.<name> logs in to a private registry so Aria can pull an image. It takes host (like ghcr.io), username, and password_secret, the name of a secret you enter in Aria. That secret is used only to pull images, never given to a service, and cannot also appear under env.

resources gives Aria hints:

Field What it does
traffic low, medium or high.
users People using the app at the same time at its busiest, 1 to 1,000,000. Sizes memory and checks the processor.
users_next_year The same, a year from now. Aria places the app where it can grow.
data_region europe, north-america or asia-pacific: where your data must stay. Aria marks server locations outside it.
notes Text for people. Nothing reads it.

What are the limits?

  • Up to 12 services, 6 databases and 200 variables per project, and up to 5 projects on one server by default. Every limit is on Limits.
  • Databases are Postgres (16 or 17), Redis (7) and Supabase. There is no MySQL or MongoDB.
  • Up to 8 volumes per service.
  • Commands are one line, with no backticks, single quotes or $( ).
  • Supabase needs about 4 GB of memory on its own.

Example 1: three services, Postgres and Redis

This stack has a web front end built from a Dockerfile at the repository root, an API built from its folder that runs its own migrations, and a worker that waits for a key only you can give.

YAML
version: 1
name: stack-demo
services:
  web:
    type: web
    path: apps/web
    context: .
    dockerfile: apps/web/Dockerfile
    port: 3000
    healthcheck: /
  api:
    type: api
    path: apps/api
    start: node server.js
    migrate: node migrate.js
    port: 8080
    healthcheck: /health
  worker:
    type: worker
    path: apps/worker
    context: .
    dockerfile: apps/worker/Dockerfile
databases:
  main:
    type: postgres
    migrations: db/migrations
    seed: db/seed.sql
  cache:
    type: redis
email:
  enabled: true
  from: hello@example.com
env:
  PUBLIC_SITE_NAME:
    services: [web]
    value: Stack demo
    build: true
  API_URL:
    services: [web]
    from: api.internal_url
  DATABASE_URL:
    services: [api]
    from: main.url
  REDIS_URL:
    services: [api, worker]
    from: cache.url
  SESSION_SECRET:
    services: [api]
    generate: secret
  SMTP_URL:
    services: [api]
    from: email.smtp_url
  MAIL_FROM:
    services: [api]
    from: email.from
  EXTERNAL_API_KEY:
    services: [worker]
    required: true
    secret: true
    description: Any value. The worker refuses to start without it.

What to notice:

  • web reads the API through api.internal_url, so it starts after the API.
  • api runs node migrate.js before each new version takes traffic.
  • The database schema comes from db/migrations, applied in order, each once, and db/seed.sql runs once on a new database.
  • EXTERNAL_API_KEY is required and secret, so the worker waits until you enter it with aria env add EXTERNAL_API_KEY.
  • PUBLIC_SITE_NAME is build: true because the web build reads it.

Example 2: a web app on self-hosted Supabase

One web service on Supabase. The app receives Supabase’s address and keys through variables, and one extra variable reaches an edge function.

YAML
version: 1
name: supabase-demo
services:
  web:
    type: web
    path: .
    dockerfile: Dockerfile
    port: 3000
    healthcheck: /
databases:
  main:
    type: supabase
env:
  NEXT_PUBLIC_SUPABASE_URL:
    services: [web]
    from: main.url
    build: true
  NEXT_PUBLIC_SUPABASE_ANON_KEY:
    services: [web]
    from: main.anon_key
    build: true
  SUPABASE_INTERNAL_URL:
    services: [web]
    from: main.internal_url
  SUPABASE_SERVICE_ROLE_KEY:
    services: [web]
    from: main.service_role_key
  DATABASE_URL:
    services: [web]
    from: main.db_url
  DEMO_FUNCTION_SECRET:
    services: [main]
    generate: secret
  GITHUB_SECRET:
    services: [main]
    required: true
    secret: true
    description: The GitHub OAuth app's client secret, for signing in with GitHub.

What to notice:

  • The two NEXT_PUBLIC_ variables are public by design, so they are marked build: true and are safe in a browser bundle. The service-role key is not, and goes only to server code.
  • services: [main] names the Supabase database, not a service. That delivers the variable to the database’s edge functions and to the config.toml that Supabase reads. GITHUB_SECRET turns on GitHub sign-in once it has a value.
  • Supabase’s own folder (supabase/ with migrations/, seed.sql, functions/ and config.toml) lives in the repository. Aria applies it on every launch and push.

How do I check the file?

Your coding agent can call the validate_stack_file tool, which returns problems with line numbers and warnings about things that are allowed but probably not what you meant. In the browser, Aria checks the file as you paste it. Problems stop a file from being saved. Warnings never block anything. Aria AI runs the same check as it writes the file. See Aria AI and Connect a coding agent.

Account · Terms

We’ve updated our terms.

Please read and accept the current terms of service and privacy policy to keep using Aria.