Docs
Coolify
Deploy a Proa app to Coolify on your own VPS.
A Proa app runs on Coolify as an ordinary Dockerized Rust HTTP server, and Coolify handles TLS, routing, rollbacks, and preview URLs. This page covers scaffolding the project, passing build secrets, setting runtime variables, and previewing pull requests.
Scaffolding for Coolify
Generate a site with the Coolify deployment preset:
proa new site my-site --template marketing --deploy coolify --tailwind --yes
cd my-site
The preset writes:
Dockerfile.dockerignorecoolify.env.exampleCOOLIFY.mdREADME.mdsrc/main.rspublic/The generated server reads PROA_HOST, PORT, and RUST_LOG, and serves public/ relative to its working directory. The Dockerfile installs a pinned, checksum-verified Proa CLI, builds with proa build --locked --artifact-out, sets PROA_HOST=0.0.0.0, exposes port 3000, copies public/ beside the binary, and keeps the GitHub token that fetches Proa's git dependencies in the build stage only.
Coolify needs matching application settings before it can build that image.
Setting up the application
- Push the generated project to GitHub.
- In Coolify, create an Application from the repository.
- Choose the Dockerfile build pack or Dockerfile deployment type.
- Set the exposed port to
3000. - While the Proa repository is private, add a GitHub token with read access to
Proa-Labs/proaas Docker build secretgithub_token. - Add runtime variables from
coolify.env.example. - Set the health check path to
/healthzfor liveness. The generated/readyzalso probes the database, so use it as the readiness check when one is configured. - Deploy.
Proa dependencies are fetched from the Proa git repository at build time, so keep the token scoped to the build. The runtime container does not need GITHUB_TOKEN, and once the repository is public the build needs no credentials at all.
Docker BuildKit secrets keep that token out of the final image.
Passing build secrets
The generated Dockerfile expects a Docker BuildKit secret named github_token, which it exposes to git through a credential helper for the duration of the build step only:
ENV CARGO_NET_GIT_FETCH_WITH_CLI=true
RUN --mount=type=secret,id=github_token \
set -eu; \
export GIT_CONFIG_COUNT=1; \
export GIT_CONFIG_KEY_0=credential.https://github.com.helper; \
export GIT_CONFIG_VALUE_0='!f() { if [ "$1" = get ] && [ -s /run/secrets/github_token ]; then printf "username=x-access-token\npassword=%s\n" "$(cat /run/secrets/github_token)"; fi; }; f'; \
proa build --locked --artifact-out /tmp/proa-app
The token never lands in Git configuration or an image layer. proa build runs the asset build and the linked RSJS pipeline; a plain cargo build --release would skip the assets and fail at link time on any crate with islands.
If your Coolify setup cannot pass Docker build secrets directly, use a GitHub Actions image pipeline instead:
- Build the image in GitHub Actions with the
github_tokenbuild secret. - Push the image to GHCR or another Docker registry.
- Point Coolify at the prebuilt image.
This is the cleanest production shape because the VPS only needs permission to pull the final image.
Either path produces the same container, and that container reads its configuration from runtime variables.
Setting runtime variables
Use these runtime variables in Coolify:
PORT=3000
PROA_HOST=0.0.0.0
Add RUST_LOG=info if you want the log filter set from the environment; the generated file lists only the two the server needs.
Do not set GITHUB_TOKEN as a runtime variable. Set it only when you build from source inside Coolify and cannot use build secrets.
Preview deployments read their own copy of these variables, so scope the sensitive ones before you turn previews on.
Previewing pull requests
Coolify supports pull request preview deployments for GitHub repositories. Previews can:
- deploy automatically for new pull requests
- use a unique preview URL template
- post deployment status comments
- keep preview secrets separate from production secrets
- clean up after you merge or close the pull request
Use the GitHub App setup when possible. Automated comments require the GitHub App, and Coolify offers automated preview deployments only for GitHub App based repositories.
For preview domains:
- Add a wildcard DNS record pointing to the Coolify server, such as
*.preview.example.com. - In Coolify, enable Preview Deployments for the application.
- Use a URL template such as
{{pr_id}}.preview.example.com. - Keep production secrets in production-only variables.
- Use preview-scoped variables for disposable databases, API sandboxes, and limited tokens.
Coolify's docs describe the full setup in GitHub Preview Deploy and the general Applications settings page.
Every environment, preview or production, needs a route Coolify can poll for liveness.
Checking health
Generated Axum sites include a cheap liveness route:
curl -fsS https://example.com/healthz
Use /healthz for Coolify's container health check. If the app needs database readiness, add a separate /readyz route and keep /healthz cheap.
Where that container gets built, on the VPS or in a pipeline, is the remaining decision.
When to use prebuilt images?
Use a prebuilt image pipeline when:
- You do not want the GitHub token on the VPS.
- Builds are too heavy for the production server.
- You need reproducible image promotion from staging to production.
- You want the same image digest in production and preview environments.
Use Coolify source builds when:
- The VPS has enough CPU and memory for Rust release builds.
- You can pass the GitHub token safely as a build secret.
- You prefer the simplest single-system workflow.
Either way, run the image locally once before you point Coolify at it.
Verifying before you deploy
Before you deploy:
proa builddocker build --secret id=github_token,env=GITHUB_TOKEN -t my-site .docker run --rm -p 3000:3000 -e PORT=3000 my-sitecurl -fsS http://127.0.0.1:3000/healthz- Verify
/static/styles.cssloads. - Verify the running container environment holds no
GITHUB_TOKEN.
Next steps
- Deploy
- Pick a deployment target, then follow the guide for it.
- Environment variables
- Load runtime configuration, secrets, bind addresses, and static paths.
- Docker
- Run the Proa image yourself, and own everything a platform would have done.
- CI / GitHub Actions
- Gate pull requests with
proa check, then deploy from the same pipeline.
- Gate pull requests with