Deploy Coolify from a Quake.yaml manifest
Deploy Coolify from a Quake.yaml manifest
Stand up a containerized app on a self-hosted Coolify instance from a single quake.yaml manifest using the validated OpenTofu template coolify-host. One manifest declares the app, its Postgres and Redis datastores, its secret names, and its domain. You validate the manifest, turn it into a launch handoff packet, and run the Coolify consumer, which creates the application, provisions the managed datastores, injects the secrets by name, and triggers the deploy.
This is the automated counterpart to the click-through deploy in Deploy Coolify with the coolify-host template, where you wire the app, database, and domain by hand in the dashboard. Here the manifest is the source of truth and the consumer does the wiring. You run Coolify yourself; this is not a managed service.
Monthly cost estimate
Pricing calculator ↗Sized as a custom package on shared vCPU.
Monthly total for the required template above. Use the configurator below to add optional pieces and see the total update.
What each resource is for
Coolify host
s1a.medium · 4 shared vCPU, 4 GiB RAM, 0.5 Gbps
Runs Coolify in Docker, along with the Postgres and Redis add-ons it provisions for the apps you deploy.
Coolify's baseline is 2 vCPU and 2 GiB RAM. The default size doubles that to leave headroom for image builds and the add-on containers.
Compute shown per role at custom-package rates ($29/dedicated vCPU, $7.25/shared vCPU, $1/GiB RAM). The headline above is the billed total: the cheaper of a named plan and the custom package, plus add-ons.
Included in baseline
s1a.medium
4 shared vCPU, 4 GiB RAM, 0.5 Gbps
Compute + RAM rate basis
4 vCPU + 4 GiB RAM at $29/dedicated vCPU, $7.25/shared vCPU, $1/GiB RAM (regular). Totals apply the flat −$5/mo package promotion.
Block storage (80 GiB)
80 GiB at $0.08/GiB/mo
Public IP (included)
1 included with the custom package
Package promotional discount
Flat −$5.00/mo on the custom package (same promotion as named plans).
Included at no charge
These line items are zero on Quake AI. Many other providers meter them separately.
Data transfer (inbound and outbound)
Unlimited data transfer on every plan; Quake AI does not meter per-GB egress.
AWS, GCP, and Azure meter outbound transfer per GB. DigitalOcean and Hetzner include an allowance on compute plans, then charge overage.
Learn morePrivate networking
Private networks, subnets, Neutron routers, and security groups are included with the plan.
VPC objects are usually free to create elsewhere, but NAT gateways bill hourly plus per-GB processed. Quake AI uses router SNAT with no separate NAT line item.
Control-plane API requests
OpenStack API calls for provisioning and management are included.
Some managed services on other clouds meter API calls or charge for premium control-plane features.
Pricing data last validated: . For current rates, check quake.ai/pricing.
Prerequisites#
You need:
- A self-hosted Coolify instance you operate. Stand one up with Deploy Coolify with the coolify-host template if you do not have one.
- A Coolify API token (Coolify dashboard: Keys & Tokens > API tokens), and the project UUID and server UUID to create resources in.
- A git repository holding a containerized app with a
Dockerfile. This walkthrough uses a Next.js app; any repo Coolify can build from a Dockerfile works. - Python 3.9 or later to run the consumer (standard library only, no third-party packages).
- The reference Coolify consumer from
consumers/coolify/in the platform repository.
Step 1: Write the manifest#
At the root of your app repository, create quake.yaml. It declares the runtime, the build source, a production and a preview environment, the two backing datastores, and the application secret names:
version: 1
name: notes-app
runtime: container
source:
build: dockerfile
dockerfile: ./Dockerfile
environments:
production:
branch: main
resources: cpu-standard
domain: notes.example.com
preview:
branch: "*"
resources: cpu-small
ttl_hours: 72
services:
- type: postgres
name: db
- type: redis
name: cache
secrets:
- NEXTAUTH_SECRET
evidence: trueThe services entries name the datastores Coolify provisions: a Postgres named db and a Redis named cache. The secrets array lists names only; values stay out of the manifest and out of version control. For the full field set and validation rules, see the quake.yaml reference.
Step 2: Validate the manifest#
Convert the manifest to JSON and validate it through the validate_launch_manifest MCP tool before you prepare a packet. The tool checks the schema and reports any resolution problems:
yq -o=json '.' quake.yaml > manifest.json
jq -n --slurpfile m manifest.json \
'{jsonrpc:"2.0",id:1,method:"tools/call",
params:{name:"validate_launch_manifest",arguments:{manifest:$m[0]}}}' \
> validate.json
curl -sS https://docs.quake.ai/api/mcp \
-H 'Content-Type: application/json' \
-d @validate.json | jq '.result.structuredContent.content'A valid manifest returns "valid": true. Fix any reported errors before continuing.
Step 3: Prepare the handoff packet#
Call prepare_launch with the manifest and a deploy action. The tool resolves the manifest into a handoff packet: the build plan, the resolved environment, the declared services, and the secret names the consumer reads from your environment:
jq -n --slurpfile m manifest.json \
'{jsonrpc:"2.0",id:2,method:"tools/call",
params:{name:"prepare_launch",
arguments:{manifest:$m[0],action:"deploy"}}}' \
> prepare.json
curl -sS https://docs.quake.ai/api/mcp \
-H 'Content-Type: application/json' \
-d @prepare.json | jq '.result.structuredContent.content' > handoff.jsonhandoff.json is the portable packet. The same packet runs against any consumer; Coolify is the one you use here. For the packet's structure, see Launch handoff.
Step 4: Export the credentials#
The consumer reads secret values and the Coolify settings from the environment, not from the manifest, the packet, or any file under version control. Export the Coolify connection settings:
export COOLIFY_BASE_URL=https://coolify.example.com
export COOLIFY_API_TOKEN=... # do not commit this
export COOLIFY_PROJECT_UUID=...
export COOLIFY_SERVER_UUID=...Then export one value per application secret, plus a password for each managed datastore. The datastore passwords follow a per-service convention keyed by the service name in UPPER_SNAKE form:
export NEXTAUTH_SECRET=... # the secrets[] entry
export DB_DB_PASSWORD=... # postgres service "db"
export CACHE_REDIS_PASSWORD=... # redis service "cache"Step 5: Run the consumer#
Run the consumer against the packet. The manifest does not carry a git remote, so you pass the repository URL Coolify deploys from at invocation time:
python3 consumers/coolify/coolify_launch_consumer.py \
--packet handoff.json \
--git-repository https://github.com/me/notes-app \
--out handoff.applied.jsonThe consumer maps the packet to Coolify's REST API: it creates the application from your git source with the Dockerfile build pack, provisions the Postgres and Redis as Coolify-managed databases, wires their connection strings into the app as DB_DATABASE_URL and CACHE_REDIS_URL, injects NEXTAUTH_SECRET, and triggers a deployment. It writes the updated packet to handoff.applied.json with the deploy id and preview URL it learned, and prints a summary.
Add --no-deploy to configure the application and datastores without triggering a deploy, which is useful for a dry run.
Step 6: Verify the deploy#
Open the Coolify dashboard and confirm the application shows as deploying, then running, with the Postgres and Redis resources alongside it. Watch the build and deploy logs stream in the dashboard.
Once the production deploy is healthy and the notes.example.com domain resolves to the host, Coolify's proxy serves the app over HTTPS. Confirm it responds:
curl -fsS https://notes.example.com/healthzFor domain and certificate setup, see step 6 of the Coolify host walkthrough.
Preview branches#
The preview environment in the manifest sets branch: "*", which the consumer maps to Coolify's per-pull-request preview deployments: open a pull request and Coolify builds and deploys a preview of that branch automatically. The manifest's ttl_hours: 72 is advisory; Coolify has no API field for a preview lifetime, so prune stale previews in the dashboard or with your own cleanup job.
What you built#
- Wrote one
quake.yamldeclaring a containerized app, a Postgres and a Redis datastore, a secret, and a production domain - Validated the manifest through the
validate_launch_manifestMCP tool - Prepared a handoff packet with
prepare_launch - Ran the Coolify consumer, which created the app, provisioned the datastores, injected the secret by name, and deployed
- Confirmed the deploy and saw how preview branches map to Coolify previews
Scope of this deployment#
This targets a self-hosted Coolify instance you operate, not a managed control plane. It is CPU-only and runs in one region, with no native CDN. The consumer triggers a deployment and reports the deploy id and preview URL; it does not wait for health checks or enforce the preview TTL. A service type Coolify has no managed equivalent for (for example object-storage) is reported and skipped rather than provisioned. You operate the Coolify host, the app, and the datastores: back them up, patch them, and watch resource use as you add apps.
Next steps#
- Deploy Coolify with the coolify-host template: the click-through deploy this page automates, and the host you run the consumer against
- How to execute a launch handoff packet from CI: run the same packet from GitHub Actions or GitLab CI instead of locally
quake.yamlreference: the full manifest field set and validation rules- Launch handoff: the packet structure and the validate-prepare-execute flow
Clean up#
Remove the application and its datastores from the Coolify dashboard (delete the app, the Postgres resource, and the Redis resource in your project). To tear down the Coolify host itself, run tofu destroy in the coolify-host template directory as shown in the Coolify host walkthrough. Export anything you want to keep before you delete.
See Also
How to execute a launch handoff packet from CI
Shares: Mcp, Quake Yaml
How to deploy from a Quake.yaml manifest with Forgejo Actions
Shares: Mcp, Quake Yaml
Launch handoff
Shares: Mcp, Quake Yaml
How to deploy on git push with a webhook listener
Shares: Quake Yaml, Launch
quake.yaml reference
Shares: Quake Yaml, Launch