Configuration Reference
Complete reference for the hostess.yml configuration file — services, environments, resources, lifecycle hooks, and more.
The hostess.yml file is the single source of truth for your application. It defines what services run, how they connect, where they deploy, and how they scale. One file describes your entire stack.
Design Principles
Hostess configuration follows four principles:
- Declarative — You describe the desired state of your stack, not the steps to achieve it. Hostess figures out the "how".
- Minimal — Only specify what matters. Smart defaults handle everything else. A simple app needs only a few lines.
- Portable — Your configuration is not tied to any specific cloud provider, orchestrator, or hosting platform.
- Readable — Non-engineers should be able to read your
hostess.ymland understand the basics of your stack.
Top-Level Fields
Every hostess.yml file starts with these top-level fields:
version: "1.0"
name: my-app
description: A description of my application
environments:
production:
domains:
web: [my-app.example.com]
services:
# ... your services
jobs:
# ... one-off, scheduled, or manual jobsField Reference
| Field | Type | Required | Description |
|---|---|---|---|
version | string | Yes | Schema version. Use 1.0. |
name | string | No | Project name, displayed in Studio and used for URL generation. |
description | string | No | Human-readable project description. |
environments | object | No | Per-environment custom domain mappings. |
services | object | Yes | Service definitions. This is the core of your configuration. |
jobs | object | No | Top-level finite workloads that run on deploy, once, manually, or on a schedule. |
Only version and services are required. Everything else has sensible defaults.
Services
Services are the core of your hostess.yml file. Each service defines a component of your application — a web frontend, an API backend, a database, a cache, a worker process, or any containerized application.
services:
frontend:
type: nextjs
build:
source: ./frontend
backend:
type: fastapi
build:
source: ./backend
database:
type: postgres
resources: largeEach service is keyed by a name (the YAML key under services:). Names must be at least 2 and at most 63 characters, use lowercase letters, digits, and hyphens only, start with a letter, and end with a letter or number.
Full ServiceSpec Reference
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | Service type (see Service Types). One of nextjs, fastapi, postgres, redis, or custom. |
build | object | Conditional | Build from a Dockerfile. One of build, image, or source is required for non-database services. |
image | string | Conditional | Public container image URL (pullable without registry credentials). For private images, prefer building from your source instead. |
source | string | Conditional | Zero-config build path — no Dockerfile. Hostess auto-detects your language/framework and builds it. Mutually exclusive with build and image. |
entrypoint | string or array | No | Override the image entrypoint. |
command | string or array | No | Override the image command/CMD. Array form is recommended; each entry is one argv segment. |
env | object | No | Environment variables (literals, magic variables, secret references). |
files | array | No | Read-only file mounts from local files, inline content, or Hostess secrets. |
depends_on | array or object | No | Services or top-level jobs this service depends on. |
domains | array | No | Custom domains (production shorthand). |
visibility | string | No | Who can reach the service: public, team, or private. See Visibility. |
ports | array | No | Ports to expose. Defaults depend on service type. Optional per-port visibility. |
resources | string or object | No | Resource allocation. Defaults to automatic workload-aware sizing (see Resources). |
replicas | number or object | No | Replica count or autoscaling config. Defaults to 1. |
health | object | No | Health check configuration. Defaults depend on service type. |
retention | string | No | Data retention policy: permanent or ephemeral. For postgres, redis, and stateful custom services. |
persistence | bool, object, or array | No | Durable custom-service mounts. Custom services only. |
lifecycle | object | No | Lifecycle hooks (init, migrate, post_deploy, shutdown). |
insights | bool or object | No | Toggle traffic, latency, and trace collection for the service. Defaults to enabled. |
logs | string | No | How Hostess parses the service's logs: structured or plain. |
backups | string or object | No | Backup schedule and configuration. |
databases | string or object | No | Scoped database groups. Postgres and Redis only. |
Service Types
The type field tells Hostess what kind of service you are running. This enables smart defaults for ports, health checks, resource allocation, and more.
type: nextjs | fastapi | postgres | redis | customSupported Types
| Type | Category | Default Port | Default Health Check | Description |
|---|---|---|---|---|
nextjs | Web Framework | 3000 | GET / | Next.js (React) applications |
fastapi | Web Framework | 8000 | GET /health | FastAPI (Python) applications |
postgres | Database | 5432 | pg_isready | Managed PostgreSQL database |
redis | Database | 6379 | redis-cli ping | Managed Redis instance |
custom | Generic | None | None | Any containerized application |
The type field is required. Hostess applies sensible defaults per type so you configure less. For custom, you must explicitly configure ports, health checks, and other settings.
Web framework types (nextjs, fastapi) require one of build, image, or source to be specified. They produce container deployments that receive HTTP traffic.
Database types (postgres, redis) are fully managed by Hostess. You do not need to provide build or image — Hostess provisions the database automatically. Database services support resources, retention, backups, and databases (scoped databases) fields.
Build Configuration
Every non-database service needs to tell Hostess where its code is. You have three options:
source— zero-config. Point at a directory and Hostess builds it for you, no Dockerfile required (the simplest path).build— build from your own Dockerfile, when you need full control.image— use a pre-built, public container image.
Choose exactly one of source, build, or image for each non-database service. Database services (postgres, redis) are fully managed and need no build configuration.
Use source when you just want Hostess to build and run your app without writing a Dockerfile. Point it at your code and Hostess auto-detects the language and framework — Node, Python, Go, Ruby, and more — and produces an optimized image for you (powered by Railpack).
services:
api:
type: fastapi
source: ./backendThat's the whole build config. Hostess inspects the directory, installs dependencies, and builds and starts your app.
When to use source
- You don't have (or don't want to maintain) a Dockerfile.
- Your app uses a mainstream stack that Railpack recognizes.
- You want the shortest path from code to deployment.
source ignores any Dockerfile in the directory — it always builds with auto-detection. If you have a Dockerfile you want Hostess to use, choose build instead. Reach for build whenever you need control auto-detection can't give you (a specific base image, system packages, multi-stage builds, etc.).
Examples:
source: .source: ./services/workerUse build when you want Hostess to build a container image from your own Dockerfile:
services:
backend:
type: fastapi
build:
source: ./backend
dockerfile: Dockerfile.prod
args:
NODE_ENV: production
BUILD_VERSION: "1.2.3"BuildSpec Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
source | string | Yes | - | Build context path, relative to the hostess.yml file. |
dockerfile | string | No | Dockerfile | Dockerfile path, relative to the source directory. |
args | object | No | - | Build arguments passed to Docker during the build. |
The source path determines which files are sent to the build system. It is also the root for the Dockerfile lookup.
Examples:
build:
source: .build:
source: ./services/authbuild:
source: ./backend
dockerfile: Dockerfile.prod
args:
PYTHON_VERSION: "3.12"Use image when you have a pre-built container image that Hostess can pull without registry credentials — for example a public image on Docker Hub or another registry.
services:
backend:
type: custom
image: ghcr.io/myorg/backend:v1.2.3The value must be a fully qualified reference (registry, repository, and tag).
image is for public images only. For private images, use build from source so the platform builds and deploys from your repo instead.
Examples:
image: nginx:1.25image: ghcr.io/myorg/my-service:latestimage: registry.example.com/team/service:v2.0.0Environment Variables
The env field defines environment variables for your service. Hostess supports three types of values:
services:
backend:
type: fastapi
env:
# Literal values
LOG_LEVEL: info
NODE_ENV: production
# Magic variables — automatic service discovery
DATABASE_URL: ${database.url}
CACHE_URL: ${cache.url}
FRONTEND_URL: ${frontend.external_url}
# Secret references — values from the Hostess secret store
JWT_SECRET: ${secret:JWT_SECRET}
STRIPE_KEY: ${secret:STRIPE_API_KEY}Value Types
| Type | Syntax | Description |
|---|---|---|
| Literal | KEY: value | Plain string value, injected as-is. |
| Magic variable | KEY: ${service.field} | Resolved at deploy time to the referenced service's URL, host, port, etc. See Magic Variables. |
| Secret reference | KEY: ${secret:NAME} | Fetched from the Hostess secret store. Missing secrets cause deployment failure. |
Dependencies
The depends_on field declares that your service depends on other services. Hostess uses it for deployment ordering and to wait before starting a dependent service’s runtime instances.
services:
backend:
type: fastapi
depends_on:
- database
- cache
env:
DATABASE_URL: ${database.url}
CACHE_URL: ${cache.url}
database:
type: postgres
cache:
type: redisUse object form when you need to make the dependency condition explicit or depend on a top-level job:
services:
backend:
type: fastapi
depends_on:
database:
condition: healthy
migrate-db:
condition: completed
jobs:
migrate-db:
image: ghcr.io/acme/api:latest
command: ["alembic", "upgrade", "head"]
run: on_deployBehavior
- Startup order — Dependent services are rolled out after their dependencies in the graph.
- Waiting — For HTTP services (for example
nextjs/fastapi/customwith an HTTP health check), Hostess waits until the configured HTTP health path responds. For Postgres and Redis, it waits until the dependency accepts connections on the database port. - Job gates — A service can depend on a top-level job with
condition: completed, so migrations or setup jobs finish before the service starts. - Magic variables — Values like
${database.url}are resolved from the stack configuration; list dependencies independs_onwhen you need strict ordering relative to those services. - Deployment order — Dependencies must form a directed acyclic graph (no cycles).
Validation
- No circular dependencies — If service A depends on B and B depends on A, validation fails.
- References must exist — Every target listed in
depends_onmust be defined inservicesorjobs. - No self-references — A service cannot depend on itself.
- Typed conditions —
healthyis valid for service targets;completedis valid for job targets. - Gating jobs only — Services can depend on jobs that complete automatically as part of a deploy;
manualandcronjobs run outside the deploy flow.
You do not need to add database services to depends_on only because you reference their magic variables. Add them when you want dependent services to wait on database connectivity during rollout.
File Mounts
Use files when a service image expects a read-only config file, certificate, policy, or key at a specific path.
services:
gateway:
type: custom
image: ghcr.io/acme/gateway:1.0.0
files:
- name: gateway-config
mount: /etc/gateway/config.yml
source: ./gateway/config.yml
- name: signing-key
mount: /etc/gateway/signing.key
secret: GATEWAY_SIGNING_KEY
mode: "0400"| Field | Required | Description |
|---|---|---|
name | Yes | Stable file identifier, unique within the service. |
mount | Yes | Absolute file path inside the container. |
source | Conditional | Project-relative source file. |
content | Conditional | Inline non-secret file content. |
secret | Conditional | Hostess secret value mounted as a file. |
mode | No | Quoted octal mode such as "0444" or "0400". Defaults to "0444". |
Exactly one of source, content, or secret must be set. File mounts are single files, not directories, and are read-only at runtime.
Use files for application services and custom services.
Domains
Custom domains give your services memorable, branded URLs instead of the auto-generated *.hostess.run addresses.
services:
frontend:
type: nextjs
domains:
- myapp.com
- www.myapp.com
api:
type: fastapi
domains:
- api.myapp.comService-level domains is shorthand for production only. For per-environment domains (e.g., staging), use the environments section. See Environments below.
Behavior
- Automatic HTTPS — Hostess automatically provisions TLS certificates via Let's Encrypt for all custom domains.
- Auto-generated URLs always exist — Every service gets a
*.hostess.runURL regardless of custom domains. - Web-facing services — Attach custom domains to services that serve HTTP traffic (your apps and APIs).
- DNS setup required — You need to create a CNAME record pointing your domain to the Hostess routing endpoint:
CNAME myapp.com → ingress.hostess.runValidation Rules
- Must be valid RFC 1123 hostnames — exact, lowercase names like
myapp.comorapi.myapp.com - Maximum 253 characters
- Globally unique — a domain cannot appear in multiple services or environments
- No duplicates within a single service
Visibility
The visibility field controls who can open a service’s HTTPS URL:
| Value | HTTPS URL | Access |
|---|---|---|
public | Yes | Anyone |
team | Yes | Organization members after Hostess sign-in |
private | No | Other services via magic variables; local access with hostess connect |
Defaults: nextjs → public; other types → private. Set visibility: team explicitly when you want a sign-in–gated URL.
services:
dashboard:
type: nextjs
build:
source: ./dashboard
visibility: teamFull behavior, Studio Access activity, and custom-domain notes are in Service Visibility.
Ports
The ports field specifies which ports your service exposes. Most of the time you do not need to set this — the service type provides a sensible default.
services:
backend:
type: fastapi
ports: [8000]Default Ports by Type
| Service Type | Default Port |
|---|---|
nextjs | 3000 |
fastapi | 8000 |
custom | None (must be specified) |
When to Override
You need to set ports when:
- Your application listens on a non-default port
- You expose multiple ports (e.g., an application port and a metrics port)
- You are using the
customservice type
Multi-Port Services
Some services expose multiple ports. List them all, and optionally set visibility per port:
services:
minio:
type: custom
image: minio/minio
command: ["server", "/data", "--console-address", ":9001"]
ports:
- port: 9000
visibility: public
- port: 9001
visibility: teamEach public or team port gets its own external URL:
Port 1 (9000): https://my-app-minio-quiet-harbor.hostess.run
Port 2 (9001): https://my-app-minio-quiet-harbor-2.hostess.runYou can reference individual ports using magic variables: ${minio.port_1.url}, ${minio.port_2.url}, ${minio.port_2.external_url}, etc.
Resources
The resources field controls how much CPU, memory, and storage your service gets. Hostess offers convenient presets and also supports explicit values.
The simplest way to set resources is with a preset name:
services:
backend:
type: fastapi
resources: mediumPreset Reference
| Preset | CPU | Memory | Storage (databases only) | Typical Use Case |
|---|---|---|---|---|
small | 0.5 cores | 512Mi | 10Gi | Development, small apps |
medium | 1.0 cores | 1Gi | 20Gi | Production APIs, standard workloads |
large | 2.0 cores | 2Gi | 50Gi | High-traffic services |
xlarge | 4.0 cores | 4Gi | 100Gi | Large databases, ML workloads |
If you omit resources, Hostess selects automatic workload-aware sizing based on service type. This is not a named preset — use small, medium, large, or xlarge when you want a fixed preset.
| Workload | CPU request | Memory request | CPU limit | Memory limit |
|---|---|---|---|---|
| Next.js / FastAPI | 0.1 cores | 256Mi | 1.0 cores | 1Gi |
| Custom | 0.25 cores | 512Mi | 1.0 cores | 1Gi |
| Jobs | 0.1 cores | 256Mi | 1.0 cores | 1Gi |
| Postgres / Redis | 1.0 cores | 1Gi | 1.0 cores | 1Gi |
For Postgres, Redis, and custom services with persistent storage, disk defaults to 20Gi when storage is omitted.
For database services, you can use a preset for CPU and memory but override the storage:
services:
database:
type: postgres
resources:
preset: large
storage: 200GiThis gives you the large preset's CPU (2.0 cores) and memory (2Gi) with 200Gi of storage instead of the default 50Gi.
For full control, specify CPU, memory, and (for databases) storage individually:
services:
ml-inference:
type: custom
resources:
cpu: 4.0
memory: 16Gi
database:
type: postgres
resources:
cpu: 2.0
memory: 4Gi
storage: 100GiThe storage resource field only applies to database services (postgres, redis). Including storage on other service types (including custom) is a validation error.
Replicas and Autoscaling
The replicas field controls how many instances of your service run. You can set a fixed number or configure horizontal autoscaling.
Set a fixed number of replicas:
services:
worker:
type: custom
replicas: 3With fixed replicas, Hostess always runs exactly the specified number of instances. Autoscaling is disabled.
Configure autoscaling with minimum and maximum bounds:
services:
backend:
type: fastapi
replicas:
min: 2
max: 10
target_cpu: 70| Field | Type | Default | Description |
|---|---|---|---|
min | number | - | Minimum number of replicas. Always running. |
max | number | - | Maximum number of replicas. Upper scaling bound. |
target_cpu | number | 70 | Target CPU utilization percentage. When average CPU usage exceeds this, Hostess scales up. |
Hostess manages stabilization windows and cooldown periods internally to prevent thrashing.
If you do not specify replicas, it defaults to 1. Autoscaling in v1.0 is based on CPU utilization only.
Validation
- Fixed replica count and autoscaling
minmust be at least 1. - Autoscaling
maxmust be greater than or equal tomin.
Health Checks
Health checks tell Hostess how to determine if your service is running correctly. Hostess uses them to decide when a replica is ready to receive traffic, to restart replicas that stop responding, and to gate safe rollouts.
The most common health check — Hostess sends an HTTP GET request to the specified path:
services:
backend:
type: fastapi
health:
http: /api/healthz
interval: 10s
timeout: 2s
retries: 5For services without an HTTP endpoint, use a command-based health check:
services:
worker:
type: custom
health:
command: "pgrep -f worker_process"
interval: 30s
timeout: 5s
retries: 3Health Check Fields
When you omit the entire health block, Hostess uses the built‑in defaults for your service type (see below). Those defaults use a 30s check interval.
When you set a health block, you can tune the check with interval, timeout, and retries. If you omit interval in your health block, the check runs on a 10s interval (other fields still default as in the table).
| Field | Type | Default (when health is set) | Description |
|---|---|---|---|
http | string | - | HTTP path for health checks (e.g., /health). |
command | string | - | Shell command to run inside the container. Exit code 0 means healthy. |
interval | string | 10s | How often to run the check (only when you provide a health block). |
timeout | string | 5s | Maximum time to wait for a response or command. |
retries | number | 3 | Consecutive failures before marking unhealthy. |
Default Health Checks by Type
If you do not define health, each service type gets a built‑in check with a 30s interval:
| Service Type | Default Health Check |
|---|---|
nextjs | GET / |
fastapi | GET /health |
postgres | pg_isready command |
redis | redis-cli ping command |
custom | None (configure health yourself) |
You only need to set health if you want to override the default or if you are using the custom type.
Lifecycle Hooks
Lifecycle hooks let you run custom commands at specific points in your service's lifecycle — before startup, during deployment, after deployment, and during shutdown.
services:
backend:
type: fastapi
lifecycle:
init:
command: ["python", "manage.py", "collectstatic", "--noinput"]
migrate:
command: ["alembic", "upgrade", "head"]
timeout: 10m
post_deploy:
command: ["python", "scripts/warmup_cache.py"]
shutdown:
timeout: 30s
command: ["python", "scripts/cleanup.py"]Hook Reference
| Hook | Fields | Behavior |
|---|---|---|
init | command | Runs setup work before the main service starts. |
migrate | command, timeout | Runs a one-off deployment task using the service image and migration command. |
post_deploy | command, timeout | Runs a one-off release task after deploy, useful for cache warmups and similar work. |
shutdown | command, timeout | Adds a pre-stop command and termination grace period for graceful shutdown. |
Commands should be YAML arrays, with each item representing one argv segment. migrate.timeout and post_deploy.timeout default to 5m when omitted.
Retention and Persistence
The retention field controls whether data for postgres, redis, and stateful custom workloads should persist across redeploys or can be discarded with the environment.
services:
database:
type: postgres
retention: permanent| Value | Description |
|---|---|
permanent | Keep data across redeploys and reprovisions where supported. Use when the data must survive new deploys. |
ephemeral | Data can be discarded when the deployment or environment is torn down. |
Set retention explicitly for each service that supports it — the retention field decides whether data persists, regardless of the environment name.
Use retention with postgres, redis, and custom services where storage applies.
For custom services, retention: permanent is shorthand for one durable mount at /data, sized from the service resource preset. Use persistence when the image needs a different mount path, a specific size, ownership initialization, or multiple durable directories.
services:
minio:
type: custom
image: minio/minio:latest
command: ["server", "/data"]
ports: [9000]
retention: permanentservices:
n8n:
type: custom
image: docker.n8n.io/n8nio/n8n:stable
ports: [5678]
persistence:
mount: /home/node/.n8n
size: 10Gi
owner: "1000:1000"services:
cms:
type: custom
image: ghcr.io/acme/cms:latest
ports: [8080]
persistence:
- name: data
mount: /var/lib/cms
size: 20Gi
- name: uploads
mount: /app/uploads
size: 100Gi
owner: "1000:1000"Persistence Fields
| Field | Required | Description |
|---|---|---|
name | List form only | Stable mount identifier. Single-object form defaults to data. |
mount | Yes | Absolute directory path inside the container. |
size | No | Storage size such as 10Gi. Defaults to the resource preset storage size. |
owner | No | Ownership initializer, such as "1000:1000" or "node:node". Numeric values are more portable across images. |
Validation rejects persistence on non-custom services, retention: ephemeral combined with explicit persistence, duplicate mount paths, unsafe paths, and files mounted inside persistent directories.
Insights
The insights field controls whether Hostess collects traffic, latency, error-rate, and trace data for the service. Insights are on by default — this field exists only to turn collection off. You never have to configure anything to get insights.
services:
backend:
type: fastapi
insights: disabled # shorthand: turn off all insights for this serviceUse the object form for finer control:
services:
web:
type: nextjs
insights:
server: disabled # no server-side metrics or traces collected
browser: disabled # no browser analytics collectedFields
| Field | Type | Default | Description |
|---|---|---|---|
server | enum | enabled | enabled or disabled. When disabled, Hostess collects no server-side traffic, latency, or trace data for the workload. |
browser | enum | enabled | enabled or disabled. Gates browser-side analytics collection. |
The scalar shorthand insights: disabled disables both server and browser. insights: enabled and an absent block are equivalent.
See Insights for the full picture: what shows up in Studio out of the box, and how to unlock route-level data with one line of code.
Logs
The logs field tells Hostess how to parse your service's log output.
services:
backend:
type: fastapi
logs: structured # parse stdout/stderr as structured JSON| Value | Description |
|---|---|
structured | Logs are emitted as structured JSON and parsed field-by-field. |
plain | Logs are treated as plain text lines. |
Backups
The backups field configures automatic backups for database and custom services.
For postgres and redis services, use the shorthand form with a schedule preset:
services:
database:
type: postgres
backups: dailyAvailable schedule presets: daily, weekly, biweekly, monthly.
For more control over schedule and retention:
services:
database:
type: postgres
backups:
schedule: daily
retention: 14You can also use a cron expression for custom schedules:
services:
database:
type: postgres
backups:
schedule: "0 3 * * *" # Every day at 3 AM
retention: 30For custom services, you must provide the backup and optionally the restore commands:
services:
my-mongo:
type: custom
image: mongo:7
backups:
schedule: daily
retention: 7
command: ["mongodump", "--archive=/backup/dump.gz", "--gzip"]
restore_command: ["mongorestore", "--drop", "--archive=/backup/dump.gz", "--gzip"]Custom backup commands must write output to the /backup/ directory.
Backup Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
schedule | string | Yes | - | daily, weekly, biweekly, monthly, or a 5-field cron expression. |
retention | number | No | 7 | Number of backups to keep. Must be between 1 and 365. |
command | array | Custom only | - | Backup command for custom services. Must write to /backup/. |
restore_command | array | No | - | Restore command for custom services. If omitted, automated restore is disabled. |
Validation
backupsis allowed onpostgres,redis, andcustomservices onlycommandis required forcustomservices and not allowed forpostgres/redisrestore_commandapplies tocustomservices onlyretentionmust be between 1 and 365- Custom cron expressions must have exactly 5 fields
Scoped Databases
By default, all services that reference a database share the same database instance and keyspace. The databases field lets you scope databases so different groups of services get isolated databases.
This is useful when you have multiple logical domains (e.g., an auth service and an analytics service) that should not share a database.
Define named groups that map to lists of consuming services:
services:
api:
type: fastapi
env:
DATABASE_URL: ${postgres.url}
analytics:
type: custom
env:
DATABASE_URL: ${postgres.url}
postgres:
type: postgres
databases:
main: [api]
analytics: [analytics]In this setup, api gets its own database and analytics gets a separate one, even though both connect to the same Postgres instance.
If you want every consuming service to get its own database, use the shorthand:
services:
postgres:
type: postgres
databases: per_serviceThis automatically creates one database group per service that references ${postgres.url}.
Scoped Databases for Redis
Redis scoping works the same way, but uses numbered Redis databases (0-15):
services:
redis:
type: redis
databases:
cache: [api, frontend]
sessions: [auth-service]
queues: [worker]Redis supports a maximum of 16 database groups (numbered 0 through 15). If you define more than 16 groups, validation will fail.
Validation
databasesis only allowed onpostgresandredisservices- Group names must be DNS-safe
- A service that references
${<database>.url}must belong to exactly one group - A service cannot appear in multiple groups for the same database
- Redis has a maximum of 16 groups
Jobs
Top-level jobs are finite workloads declared outside services. Use them for migrations, setup tasks, asset builds, scheduled reports, maintenance tasks, or manual operations that should not run as long-lived services.
jobs:
setup:
image: ghcr.io/acme/setup:latest
command: ["./setup.sh"]
run: once
daily-report:
build:
source: ./reports
command: ["python", "-m", "reports.daily"]
run: cron
schedule: daily
rebuild-search:
image: ghcr.io/acme/search-tools:latest
command: ["./rebuild.sh"]
run: manualJobSpec Reference
| Field | Required | Description |
|---|---|---|
image or build | Yes | Container image source. Exactly one is required. |
entrypoint | No | Override the image entrypoint. |
command | Yes | Command/CMD arguments to run. |
env | No | Literals, magic variables, and secret references. |
files | No | Read-only file mounts. |
depends_on | No | Services or jobs that must be healthy/completed first. |
resources | No | Same shape as service resources. Defaults to automatic workload-aware sizing (see Resources). |
run | No | on_deploy, once, manual, or cron. Defaults to on_deploy. |
schedule | Required for cron | daily, weekly, monthly, or a 5-field cron expression. |
timeout | No | Defaults to 5m. |
retries | No | Defaults to 1. |
Run Policies
| Policy | Behavior |
|---|---|
on_deploy | Runs every deploy. |
once | Runs the first deploy that includes the spec, then only when the spec changes or the run is reset. |
manual | Runs only when triggered from the CLI or Studio. |
cron | Runs on schedule. |
Operate jobs with hostess jobs.
Environments
Environments represent different deployment targets such as production, staging, preview, or a custom stage. In hostess.yml, per-environment configuration is expressed with environments.<env>.domains.
environments:
production:
domains:
frontend: [myapp.com, www.myapp.com]
api: [api.myapp.com]
staging:
domains:
frontend: [staging.myapp.com]
api: [api-staging.myapp.com]Environment Fields
| Field | Type | Description |
|---|---|---|
domains | object | Custom domains per service for this environment. |
Staging
Staging environments are long-lived environments for pre-production testing:
environments:
staging:
domains:
frontend: [staging.myapp.com]Custom Environments
You can define any custom environment name:
environments:
qa:
domains:
frontend: [qa.myapp.com]
demo:
domains:
frontend: [demo.myapp.com]Per-Environment Domains
Custom domains can be configured at two levels:
- Service-level
domains— Shorthand for production:
services:
frontend:
domains: [myapp.com] # Applies to production only- Environment-level
domains— Explicit per-environment:
environments:
production:
domains:
frontend: [myapp.com, www.myapp.com]
api: [api.myapp.com]
staging:
domains:
frontend: [staging.myapp.com]Domain Rules
- Environment-level domains override service-level domains for that environment
- Service-level
domainsonly applies to the production environment - A domain cannot appear in multiple environments (must be globally unique)
- Service-level and environment-level domains for the same service cannot conflict
Complete Examples
Minimal Example
The simplest possible hostess.yml — a single Next.js app:
version: "1.0"
services:
app:
type: nextjs
build:
source: .
domains:
- myapp.comFull-Stack Application
A complete e-commerce platform with frontend, backend, database, cache, and background workers:
version: "1.0"
name: E-Commerce Platform
description: Next.js frontend with FastAPI backend
environments:
production:
domains:
frontend: [myorg.com, www.myorg.com]
backend: [api.myorg.com]
services:
database:
type: postgres
resources:
preset: large
storage: 20Gi
retention: permanent
cache:
type: redis
resources: medium
retention: permanent
backend:
type: fastapi
build:
source: ./backend
env:
DATABASE_URL: ${database.url}
REDIS_URL: ${cache.url}
JWT_SECRET: ${secret:JWT_SECRET}
STRIPE_KEY: ${secret:STRIPE_KEY}
depends_on:
- database
- cache
replicas:
min: 2
max: 10
target_cpu: 70
resources: medium
lifecycle:
migrate:
command: ["alembic", "upgrade", "head"]
domains:
- api.myorg.com
frontend:
type: nextjs
build:
source: ./frontend
env:
NEXT_PUBLIC_API_URL: ${backend.external_url}
depends_on:
- backend
replicas:
min: 2
max: 20
resources: medium
domains:
- myorg.com
- www.myorg.com
worker:
type: custom
build:
source: ./backend
command: ["celery", "-A", "app.celery", "worker", "--loglevel=info"]
env:
DATABASE_URL: ${database.url}
REDIS_URL: ${cache.url}
depends_on:
- database
- cache
replicas: 3
resources: mediumMicroservices Architecture
Multiple independent services sharing infrastructure:
version: "1.0"
name: Microservices Platform
services:
postgres:
type: postgres
redis:
type: redis
auth-service:
type: fastapi
build:
source: ./services/auth
env:
DATABASE_URL: ${postgres.url}
REDIS_URL: ${redis.url}
JWT_SECRET: ${secret:JWT_SECRET}
domains:
- auth.platform.io
user-service:
type: fastapi
build:
source: ./services/users
env:
DATABASE_URL: ${postgres.url}
AUTH_URL: ${auth-service.url}
depends_on:
- postgres
- auth-service
domains:
- users.platform.io
order-service:
type: fastapi
build:
source: ./services/orders
env:
DATABASE_URL: ${postgres.url}
USER_SERVICE_URL: ${user-service.url}
depends_on:
- postgres
- user-service
domains:
- orders.platform.io
frontend:
type: nextjs
build:
source: ./frontend
env:
NEXT_PUBLIC_AUTH_URL: ${auth-service.external_url}
NEXT_PUBLIC_USER_URL: ${user-service.external_url}
NEXT_PUBLIC_ORDER_URL: ${order-service.external_url}
domains:
- platform.ioAI/ML Application
An AI image generator with a dedicated ML inference service:
version: "1.0"
name: AI Image Generator
services:
database:
type: postgres
redis:
type: redis
api:
type: fastapi
build:
source: ./api
env:
DATABASE_URL: ${database.url}
REDIS_URL: ${redis.url}
MODEL_SERVICE_URL: ${ml-inference.url}
domains:
- api.aiapp.io
ml-inference:
type: custom
build:
source: ./ml
dockerfile: Dockerfile.gpu
env:
MODEL_PATH: /models/stable-diffusion
resources:
cpu: 4.0
memory: 16Gi
replicas:
min: 1
max: 5
worker:
type: custom
build:
source: ./worker
command: ["celery", "-A", "tasks", "worker"]
env:
DATABASE_URL: ${database.url}
REDIS_URL: ${redis.url}
ML_SERVICE_URL: ${ml-inference.url}
replicas: 3
resources: medium
frontend:
type: nextjs
build:
source: ./frontend
env:
NEXT_PUBLIC_API_URL: ${api.external_url}
domains:
- aiapp.ioMulti-Port Service
A MinIO object storage service exposing both the API and console ports:
version: "1.0"
name: Object Storage
services:
minio:
type: custom
image: minio/minio
command: ["server", "/data", "--console-address", ":9001"]
ports: [9000, 9001]
env:
MINIO_CONSOLE_URL: ${minio.port_2.external_url}Port 1 (9000) is the S3-compatible API. Port 2 (9001) is the web console. Each gets its own URL:
Port 1: https://my-app-minio-quiet-harbor.hostess.run
Port 2: https://my-app-minio-quiet-harbor-2.hostess.runAppendix: Validation Rules
Service names
- Length: 2–63 characters (see naming rules under Services).
- Reserved (cannot be used as a service name):
hostess,default,system
Dependencies
| Rule | Detail |
|---|---|
| Circular | Not allowed — validation fails |
| Existence | Referenced services or jobs must be defined |
| Self-reference | A service cannot depend on itself |
| Condition | healthy is for service targets; completed is for job targets |
Appendix: Default Values
A quick reference of defaults when fields are omitted:
| Field | Default Value |
|---|---|
resources | Automatic workload-aware sizing (see Resources) |
replicas | 1 |
Built-in health (no health block) | Type defaults with 30s interval, 5s timeout, 3 retries |
health block without interval | 10s interval (when you define a custom health section) |
lifecycle.migrate.timeout / lifecycle.post_deploy.timeout | 5m |
backups.retention | 7 |
replicas.target_cpu (autoscaling) | 70 |
jobs.*.run | on_deploy |
jobs.*.timeout | 5m |
jobs.*.retries | 1 |
Default Storage by Preset
| Preset | Storage |
|---|---|
small | 10Gi |
medium | 20Gi |
large | 50Gi |
xlarge | 100Gi |