Projects and services
Build settings
How Cloud picks a build type and commands for a repository, and how to change them.
Updated
A service built from a GitHub repository has a build type, up to three commands, and a directory in the repository to build in. Cloud reads the repository to fill these in, and every one of them can be changed on the Source card of the service's Overview section.
Builds run on a shared build server, separate from the machines your services run on. The first lines of a build log say so. The only time limit Cloud puts on a build is the two-hour ceiling on a whole deployment, which Deployments explains.
Build types
Build with offers four, named as the builders name themselves:
| Build with | What it does |
|---|---|
| nixpacks | "Reads the repository and builds it without a Dockerfile." The default. |
| Dockerfile | "Builds the Dockerfile at the top of the build path." |
| railpack | "Reads the repository the way railpack does." |
| Static site | "Serves what the build wrote, with no server of its own." See Deploy a static site. |
How Cloud chooses
When you pick a repository and a branch on the create form, Cloud lists the repository's top directory and takes the first match:
| The directory holds | Build with | The line under the field |
|---|---|---|
Dockerfile | Dockerfile | From the repository: a Dockerfile, which the build runs as it is written. |
railpack.json | railpack | From the repository: a railpack.json. |
package.json | nixpacks, with commands filled in | From the repository: package.json, with pnpm. (or Yarn, Bun, npm) |
index.html, and none of the above | Static site | From the repository: an index.html and nothing to build. |
| Anything else | nixpacks | From the repository: nixpacks reads the repository and builds what it finds. |
Reading the repository never blocks you. If Cloud cannot read it, the field stays empty and you choose.
If you choose a different build type yourself, your choice is used, and commands Cloud read for another builder are not sent with it: a repository read as nixpacks with npm commands, switched to Dockerfile, is created with no npm commands.
Node projects
For a package.json, the lock file in the same directory names the package manager, and the scripts in package.json name the commands:
| Lock file | Install command | Scripts run with |
|---|---|---|
pnpm-lock.yaml | pnpm install --frozen-lockfile | pnpm run |
yarn.lock | yarn install --frozen-lockfile | yarn run |
bun.lockb or bun.lock | bun install | bun run |
package-lock.json | npm ci | npm run |
| None of these | npm install | npm run |
A build script becomes the build command, such as pnpm run build, and a start script the start command. A script the file does not have leaves its command empty for nixpacks to work out. Cloud fills these in because nixpacks on its own runs npm against a pnpm lock file, which is the mistake most worth preventing.
The Source card
The card reads "What this service is built from, and what makes it build again. A change here is read at the next deploy." Which fields it shows depends on Build with:
| Field | Shown for | What it is |
|---|---|---|
| Install command | nixpacks | "Run before the build. Empty leaves nixpacks to work it out." |
| Build command | nixpacks | "Run to build. Empty leaves nixpacks to work it out." |
| Publish directory | Static site | "Where the build wrote what is served, under the build path." |
| Start command | every build type | What the container runs. For nixpacks it is also what nixpacks builds in. |
| Build path | every build type | "The directory in the repository the build runs in. Empty is its root." |
Deploy on and Watch paths are on the same card; Source and deploy triggers covers them. Press Save source to keep your changes.
A field that does not belong to the chosen builder is hidden rather than cleared, so switching to Dockerfile and back to nixpacks before you save gives you your nixpacks commands back.
Read the repository again
Changing Repository or Branch on the card makes Cloud read the new one and fill Build with, the commands and Publish directory from it, over what the fields held. The round arrow button in the card's corner, labelled "Read the repository again", does the same for the repository already chosen, using the Build path in the field. Nothing is saved until you press Save source. If Cloud cannot read the repository, the fields keep what they had.
Commands
A command is one line of at most 500 characters. An empty command leaves the choice to the builder or the image.
Set a start command when package.json has none
nixpacks settles the start command while it builds. A Node repository whose package.json has no start script fails the build with "No start command could be found" before any container exists. Set Start command, such as npm run start, save, and deploy again.
The start command is split on spaces and run directly, with no shell, so quotes, pipes, redirections and && reach the program as literal words. A container that needs several steps at boot should run a script from the repository instead.
For a nixpacks build, Cloud passes the three commands to the build through its environment, as NIXPACKS_INSTALL_CMD, NIXPACKS_BUILD_CMD and NIXPACKS_START_CMD, without writing them into the environment you edit. If your own environment already sets one of those names, yours is used. Other build types are sent none of them.
Build path
For a repository that holds more than one application, set Build path to the application's directory, such as apps/web. The build runs there, a Dockerfile is read from there, the publish directory is counted from there, and Cloud looks for an environment template there first. A path is written from the repository's root: apps/web, /apps/web and /apps/web/ are the same path. A path is at most 255 characters, and one holding .. is refused with "A build path names a directory in the repository, such as /apps/web."
apps
web
- package.json
- pnpm-lock.yaml
api
- Dockerfile
In this repository, one service with the build path apps/web builds with nixpacks and pnpm, and a second with apps/api builds from its Dockerfile. Give each watch paths so that a push to one does not rebuild the other.
When changes apply
Build settings are read at the next deploy, so saving one does not touch what is running. Start command is the exception: it is what the container runs rather than how it was built, so saving a new one restarts a running service with it at once, whatever the card's own line says.