Deployment guides

Deploy a NestJS API

Detected automaticallyNode.js 22APIs and services

Lannzo detects NestJS from the @nestjs/core dependency, runs your build, and starts the compiled application with node dist/main.js.

Two things decide whether it works: the build has to produce dist/main.js, and the application has to listen on the port the runtime injects.

What Lannzo expects

The build installs dependencies, runs your build script, and packages dist, package.json and the installed node_modules. The checks below run during the build, so a mismatch fails with a named error.

In your projectWhat Lannzo expects
package.json → scripts.buildA build script. NestJS projects must define one; the build fails with `NEST_BUILD_SCRIPT_MISSING` otherwise.
dist/main.jsThe compiled entrypoint. It must exist exactly at this path, which is the Nest CLI default.
process.env.PORTThe runtime injects `PORT`. An application listening on a fixed port never receives traffic.
0.0.0.0Listen on all interfaces. Binding to `localhost` makes the application unreachable from outside its own container.

Prepare the project

Read the port from the environment and bind to every interface:

// src/main.ts
import { NestFactory } from "@nestjs/core";

import { AppModule } from "./app.module";

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(process.env.PORT ?? 3000, "0.0.0.0");
}

void bootstrap();

Keep the build script the Nest CLI generates. It compiles to dist, with dist/main.js as its entrypoint:

{
  "scripts": {
    "build": "nest build"
  }
}

Deploy it

Link the directory once, and deploy. Preview gets its own URL, so an API can be checked before it reaches production.

lannzo link --project my-api
lannzo deploy
lannzo deploy --prod

To deploy from GitHub instead of your machine, connect the repository once. With --auto-deploy, every push to the production branch deploys on its own; without it, lannzo deploy --git deploys the head commit when you decide to.

lannzo repo connect --repository acme/my-api --branch main --auto-deploy
lannzo deploy --git

Environment variables

Give an API its configuration as runtime variables, and mark anything sensitive as a secret: connection strings, tokens, signing keys. Secrets are written but never read back, and never appear in a listing or a log.

lannzo env set DATABASE_URL --environment production --secret --target runtime
lannzo env list --environment production

Operate the runtime

A release keeps serving until you replace it. Restarting creates a new revision from the same artifact, picking up the current variables without redeploying; stopping withdraws traffic until you start it again.

lannzo runtime restart --environment production
lannzo logs --follow --source runtime

Monorepos

In a monorepo, point Lannzo at the API's directory. Its dist/main.js is resolved inside that directory, not at the repository root.

lannzo project set-root-directory apps/api

Override the configuration

Lannzo detects the framework on every deployment. Setting it explicitly marks the selection as manual, so detection stops overriding it, and it is what makes a custom build or start command take effect — commands saved without a manual framework are ignored by the build.

Use --auto-framework, --auto-build-command and --auto-start-command to clear a manual value and go back to detection and the framework defaults.

lannzo project config --framework nestjs
lannzo project config --framework nestjs --build-command "pnpm build"

When a build fails

`NEST_ENTRYPOINT_MISSING`

The build succeeded but produced no dist/main.js. A changed outDir in tsconfig.json, or a build that emits somewhere else, are the usual causes.

The deployment never becomes healthy

The process starts but nothing answers on the injected port. Check that main.ts listens on process.env.PORT and on 0.0.0.0, then read lannzo logs --source runtime for what the process printed before it went quiet.

Several frameworks detected

If the same package.json declares more than one supported framework, the build stops with FRAMEWORK_DETECTION_AMBIGUOUS instead of guessing. Pick one with lannzo project config --framework <framework>.