The manifest
apphaven.yaml, in the root of your repository, describes your application to
AppHaven. It declares three things:
- Services: the containers and managed databases your app runs.
- Volumes: the storage those services keep.
- Environment variables: the configuration they run with.
AppHaven validates the manifest and uses it to run your app. To change your
app's shape, edit apphaven.yaml and push; the next deploy picks it up.
A complete example
A web service built from the repository's Dockerfile, a managed database, and a persistent volume for uploads:
version: 1
services:
web:
type: container
build:
dockerfile: Dockerfile # built from your repository on every deploy
ports:
- 3000 # served on your app's URL
env:
NODE_ENV: production
DATABASE_URL: ${service.db.url} # a ready-to-use connection URL
volumes:
- name: uploads
mount_path: /app/uploads
depends_on:
- service: db
condition: healthy # wait until the database accepts connections
db:
type: postgres # managed database, provisioned by AppHaven
version: "17"
volumes:
uploads:
type: persistent # kept across deploys
With this manifest, AppHaven builds web from the Dockerfile in your
repository, provisions the db database with generated credentials, creates
the uploads volume, starts web once the database is ready (with
DATABASE_URL set to a real connection URL), and serves port 3000 on your
app's URL over HTTPS.
Top-level fields
| Field | Type | Required | Description |
|---|---|---|---|
version | int | no | The manifest schema version. Currently 1, which is also the default. |
services | map of name → service spec | yes | Your app's services. At least one is required. |
volumes | map of name → volume spec | no | Volumes your services mount. Required only if a service references a volume. |
Naming rule
Every name you choose in the manifest (each service name and each volume name) must match:
^[a-zA-Z0-9][a-zA-Z0-9_\-]{0,63}$
- Starts with a letter or digit.
- 1–64 characters long.
- Contains only letters, digits, underscores (
_), and dashes (-).
Use lowercase service and volume names so they're accepted as written.
Validation
AppHaven validates the manifest before anything is deployed. Validation is strict: an unknown field anywhere in the manifest is rejected with a clear error, so a typo fails fast instead of being silently ignored.
When a manifest is rejected, the message describes the problem. Common causes:
| Cause | Example message |
|---|---|
| An unknown field (often a typo) | service web: unknown field "prots" |
| A name doesn't match the naming rule | service name "my app!" is invalid |
Unknown service type | service web: type "vm" not supported |
Container with neither image nor build | service web: image or build is required |
| A field that isn't valid for the service type | service db: "ports" is not allowed on a postgres service |
| Port out of range | service web: port 99999 out of range |
depends_on cycle | depends_on cycle: web -> db -> web |
condition: healthy on a target with no healthcheck | service web depends_on db (healthy) but db has no healthcheck |
| Reference to an unknown service or field | service web: ${service.cache.url} references unknown service "cache" |
| Reference to an undeclared volume | service web: references undeclared volume "missing" |
| Non-canonical mount path | service web: mount_path "/a/../b" must be canonical |
| Unknown volume type | volume cache: type "weird" not supported |
Where to go next
- Services: containers and managed databases.
- Volumes: durable and scratch storage.
- Environment variables: configuration and secrets.
- Manifest reference: every valid field, on one page.
- Getting started: deploy an app built from this manifest.