Guides / Deploy
Compose apps
Add workers, databases, and persistent data to an app.
A Compose file runs multiple services as one app. Deploy it through the same local or GitHub workflow.
The public service
One service gets the app URL. Mark its container port with x-hub: { port: 3000 }, or give only that service a ports mapping. A worker-only project needs neither and gets no URL.
A database
For an existing app, add a database with a named volume. Set its password before deploying this change; environment variables require an app that already exists.
This web + database example defaults to always-on and needs two always-on container slots. Free includes one, so this example needs a higher allowance. Check your organization's capacity with hub usage before adding the database; contact Hub to increase it.
services:
web:
build: .
x-hub: { port: 3000 }
environment:
DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/app
depends_on: [db]
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: ${DB_PASSWORD:?Set DB_PASSWORD in Hub}
POSTGRES_DB: app
volumes:
- dbdata:/var/lib/postgresql/data
volumes:
dbdata:hub app my-app env set DB_PASSWORD
hub deployThe password command prompts without echoing it. The required-variable guard prevents database startup without it.
Named volumes survive deployments and rollback of the same instance. Hub does not back them up automatically. Keep your own backups; deleting volumes removes their data. Recreating a deleted app or instance name does not restore retained volumes; see storage and deletion.
Variables
${NAME} uses Hub's environment variables, not a local .env. Services Hub builds receive those variables; ready-image services receive only what Compose explicitly passes.
Deploy safely
Named volumes hold writable data. Project bind mounts are read-only; host privileges, external networks or volumes, and files outside the project are rejected.
Multi-service apps stay running by default. Only enable sleep when every service can pause between requests. See runtime and sleep for that workflow and the runtime command for options.
Runtime policy
Set x-hub-runtime at the top level of your Compose file to choose whether the instance can sleep:
x-hub-runtime:
policy: auto_sleep
activity: http
idleSeconds: 300
services:
web:
build: .
x-hub: { port: 3000 }| Field | Values |
|---|---|
policy | Required: auto_sleep or always_on. |
activity | Required: http, background, or stateful. |
idleSeconds | Integer from 5 to 86400; defaults to 300. |
auto_sleep requires activity: http and a public service selected by Compose's port rules. Only use it when every service can pause between requests. Jobs, timers, and queue consumers need always_on; use activity: background for background work or stateful for stateful services. Unknown fields are rejected.
Without this block, a single HTTP service defaults to sleep after five idle minutes; other projects default to always on. On the VM runtime, sleep pauses every service in the instance and preserves its disks. Explicit x-hub-runtime settings override runtime policy on redeploy. Inspect or change policy with hub app runtime; start a sleeping instance before changing it.