DeployRuntimes

Runtimes

Static, Node, Python and PHP — how the runtime is chosen, the single entrypoint each one looks for, what it installs dependencies from, and the escape hatch for everything else.

The runtime decides how your source is built and started. There are four, and each looks for one entrypoint. Match it and a deploy just works.

RuntimeInferred fromEntrypoint it looks forInstalls deps fromPort
staticindex.htmlindex.html at the project root80
nodepackage.jsonnpm start (the start script)package.json3000
pythonrequirements.txt, .pyapp imported from app.pyrequirements.txt8000
phpcomposer.json, .phpindex.php at the project rootcomposer.json (optional)80

How the runtime is chosen

Pass it explicitly as runtime"node:22", "python:3.12", "php:8.3", "static" — or omit it on create_app and agenthost infers it from your files. Inference is a convenience for the common case; when in doubt, set it explicitly. If you omit it and nothing can be inferred, create_app fails and asks for one.

The version half is optional: "node" and "node:22" both work, and a supported default is picked when you leave it off. See Choosing a version.

There is no start_command, and no port setting.

How an app starts is fixed per runtime — it is the convention on these pages, not a parameter. A field the tool schema doesn't define is silently ignored rather than rejected, so a wrong guess looks like it worked.

What every runtime shares

  • Your source goes in, dependencies do not. node_modules, vendor, .venv, __pycache__, .git and .env files are excluded from the build. Ship the manifest, not the install.
  • HTTPS and routing are automatic. You never expose a port or configure a proxy.
  • Environment variables are injected at run time, never written into your source. See Environment variables.
  • Builds are asynchronous. A successful call means queued, not live. See Checking a deploy.

The escape hatch

If your project contains a Dockerfile at its root, we use yours and generate nothing. That covers anything the four runtimes don't: a Go binary, an ASGI server, a runtime with system dependencies, a bespoke build.

Two constraints hold:

  • You still pick a runtime (or let one be inferred) — it decides which port traffic is routed to.
  • Your container must listen on that port: 3000 for node, 8000 for python, 80 for php and static.

Pages