Docs

Coolify

Deploy a Proa app to Coolify on your own VPS.

Open Markdown

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:

Terminal
proa new site my-site --template marketing --deploy coolify --tailwind --yes
cd my-site

The preset writes:

Dockerfile
.dockerignore
coolify.env.example
COOLIFY.md
README.md
src/main.rs
public/

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

  1. Push the generated project to GitHub.
  2. In Coolify, create an Application from the repository.
  3. Choose the Dockerfile build pack or Dockerfile deployment type.
  4. Set the exposed port to 3000.
  5. While the Proa repository is private, add a GitHub token with read access to Proa-Labs/proa as Docker build secret github_token.
  6. Add runtime variables from coolify.env.example.
  7. Set the health check path to /healthz for liveness. The generated /readyz also probes the database, so use it as the readiness check when one is configured.
  8. 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:

Dockerfile
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:

  1. Build the image in GitHub Actions with the github_token build secret.
  2. Push the image to GHCR or another Docker registry.
  3. 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:

coolify.env.example
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:

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:

  1. Add a wildcard DNS record pointing to the Coolify server, such as *.preview.example.com.
  2. In Coolify, enable Preview Deployments for the application.
  3. Use a URL template such as {{pr_id}}.preview.example.com.
  4. Keep production secrets in production-only variables.
  5. 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:

Terminal
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:

Use Coolify source builds when:

Either way, run the image locally once before you point Coolify at it.

Verifying before you deploy

Before you deploy:

Next steps

Search

Type at least 2 characters