Runtimes

Zenifra does not perform automatic runtime detection. In projects created from a Git repository, the user explicitly chooses the runtime during project creation.

Supported runtimes

RuntimeHow it works
Node.jsThe user chooses the version in the console, and the platform installs dependencies with npm ci
PythonThe user chooses the version in the console, and the platform installs dependencies with pip install --no-cache-dir -r requirements.txt when the file exists
BunThe user chooses the version in the console, and the platform installs dependencies with bun install --frozen-lockfile

Note: Today, Node.js, Python, and Bun are officially supported for Git repository builds. Java, Go, PHP, .NET, Nginx, Apache, and other stacks should be published via OCI Image.

Available versions

RuntimeVersionsSuggested default port
Node.js20, 22, 24, and 263000
Python3.11, 3.12, 3.13, and 3.148000
Bun1.2, 1.3, and 1.43000

Pick the same major version you use in development. The suggested port is just a starting point: the project Port field must match the port your app listens on.

Build and runtime environment

  • Project environment variables are available during dependency install, pre-build, and build, as well as at runtime. This lets build steps use variables such as NEXT_PUBLIC_* or VITE_*.
  • Changing a variable restarts the instances but does not rebuild. Values embedded during the build only change on a new deployment.
  • The app runs as an unprivileged user inside the application directory. It can write to that directory, but files are ephemeral unless stored in persistent storage.
  • On Node.js and Bun, the app runs with NODE_ENV=production.
  • The build uses the folder set in Root directory (the repository root by default; in monorepos, a subfolder such as backend) and an environment generated by Zenifra for the selected runtime: an existing Dockerfile in the repository is not used. To build with your own Dockerfile, publish an OCI Image.
  • The repository .git folder is not included in the published application. If your application read Git information at runtime (for example, the current commit), use an environment variable.
  • On Python, print() and logging output reaches the logs unbuffered, and the build environment includes a C compiler and the PostgreSQL client libraries for packages with native extensions.

Important rule

In GitHub projects created in the console, runtime, version, and branch cannot be changed in the console; through the API (PUT /v1/project/:id/source) or the CLI (zenifra project source) you can reconfigure the source. In Forgejo projects, the project page's Git repository section lets you change the runtime (Node.js or Python), version, and commands; the API also accepts Bun.

Node.js

Required files

{
  "name": "my-app",
  "scripts": {
    "start": "node index.js"
  }
}

For Node.js projects based on Git, these files are required:

  • package.json
  • package-lock.json

Default dependency install

Zenifra installs dependencies with:

npm ci

By default, npm ci installs the dependencies declared in the lockfile. Keep TypeScript, bundlers, and other build tools in devDependencies. If the project configuration sets NODE_ENV=production for the build, that install omits those dependencies; in that case, set pre-build to npm install --include=dev. It runs after the default install and before npm run build, making the tools available to the build. The current runtime does not prune devDependencies after that step.

No build command: when the build field is empty, devDependencies are pruned after install. Everything the start command uses must be in dependencies.

Git projects using Yarn or pnpm are compatible with the current Node.js runtime only when they also provide a compatible npm package-lock.json. Zenifra does not automatically convert Yarn or pnpm lockfiles or workspaces; without a compatible npm lockfile, publish an OCI Image prepared by your own build process.

Project commands

After the default install step, these commands are user-defined during project creation:

  • pre-build (optional)
  • build (optional)
  • start (required)

A common use of pre-build in Node.js is generating code before the build, such as ORM clients. pre-build runs during the build, not on every application start; for database migrations, prefer running them at the beginning of start, as shown in the framework guides.

Python

Dependency files

Keep a requirements.txt in the project's Root directory (the repository root by default) with the runtime dependencies. The install below runs only when that file exists. If the repository also has pyproject.toml or setup.py, the package is installed with pip install -e . after the build.

Default dependency install

pip install --no-cache-dir -r requirements.txt

Project commands

These commands are user-defined during project creation:

  • pre-build (optional)
  • build (optional)
  • start (required)

Bun

Files

{
  "name": "my-app",
  "scripts": {
    "start": "bun index.ts"
  }
}
  • package.json (required)
  • bun.lock (recommended): commit the lockfile so the build installs exactly the versions used in development. Generate it with the same Bun version selected for the project: a lockfile created by a newer version can be rejected by an older one.

Default dependency install

bun install --frozen-lockfile

devDependencies stay installed after the build, so tools such as TypeScript and bundlers are available to pre-build and build. Bun runs TypeScript directly, with no required compile step.

Project commands

The default start command is bun run start, which runs the start script from package.json. As with the other runtimes, you can also set:

  • pre-build (optional)
  • build (optional)
  • start (required)

What can be edited later

In GitHub projects, after creation, the pre-build, build, and start commands and the update mode remain editable; runtime, runtime version, and branch are set during creation. See GitHub Deployment.

In Forgejo projects, you can also change the repository, branch, runtime, version, and deployment mode after creation; see Deploy from Forgejo.

Last updated on

On this page