Deploying
Language guides and static sites
What Nixpacks detects for Node.js, Python, Go, PHP, Ruby and Java, how to set start commands and versions, and how to host static sites and SPAs.
With the Nixpacks build type (the default), MarvX runs Nixpacks on your repository root to detect the language, install dependencies, build and pick a start command. A root Dockerfile takes precedence.
Rules for every language
- Listen on
0.0.0.0and thePORTvariable (MarvX setsPORT=3000unless you set it). - Make the start command explicit with a
Procfile(web: <command>) ornixpacks.toml. - Commit your lockfile.
- Project environment variables exist only at runtime, not during the build. Put build settings in
nixpacks.toml(it's committed, so no secrets). - The app must be at the repository root (see Dockerfiles, images and Compose for monorepos).
# nixpacks.toml (repository root)
[variables]
NODE_ENV = "production"
[phases.build]
cmds = ["npm run build"]
[start]
cmd = "node dist/server.js"Node.js
- Detected by
package.json. The package manager follows the lockfile: npm, Yarn, pnpm or Bun. Installs are frozen, so a stale lockfile fails the build. - Runs the
buildscript if present, then thestartscript. - Version:
"engines": { "node": "20" }or.nvmrc. NEXT_PUBLIC_*/VITE_*values must be known at build time: set non-secret ones innixpacks.toml[variables], or build with a Dockerfile.
app.listen(process.env.PORT || 3000, "0.0.0.0");Python
- Detected by
requirements.txt,pyproject.toml(incl. Poetry) orPipfile. Version:.python-version. - Start command in a
Procfile, e.g.web: gunicorn myproject.wsgi --bind 0.0.0.0:$PORTorweb: uvicorn main:app --host 0.0.0.0 --port $PORT. Add the server package to your dependencies.
Go
- Detected by
go.mod(which sets the Go version). Nixpacks builds and runs the binary. - If
mainisn't at the root, set build and start commands innixpacks.toml. Listen on":" + os.Getenv("PORT").
PHP
- Detected by
composer.json(Laravel byartisan). Served by nginx and PHP-FPM onPORT. - Set
APP_KEYand other settings as variables; run migrations from Open Terminal or a cron schedule.
Ruby
- Detected by
Gemfile(Rails automatically). Version:.ruby-versionorGemfile. web: bundle exec rails server -b 0.0.0.0 -p $PORT, and setSECRET_KEY_BASEorRAILS_MASTER_KEY.
Java
- Detected by
pom.xmlorbuild.gradle(.kts); commit the Maven or Gradle wrapper. - Read
PORT(Spring Boot:server.port=${PORT:3000}). Override the start command innixpacks.tomlif needed, e.g.cmd = "java -jar target/app.jar". - Keep the heap under your plan's memory cap, e.g.
JAVA_TOOL_OPTIONS=-Xmx384mon Free.
Static sites
The Static site (nginx) build type serves files with nginx and doesn't run a build command. It serves the first folder that exists: dist, build, public, out, otherwise the repository root. Unknown paths fall back to index.html, so single-page-app routing works.
- Commit the files to serve (e.g. a built
dist/). - Build Type: Static site (nginx), Save, then Deploy.
Don't set PORT on a static site: nginx listens on 3000 and a different PORT breaks routing.
For sites that need building (Vite, Astro, CRA…): commit the build output, or use Nixpacks with a start script that serves the output on $PORT (e.g. npx serve -s dist -l $PORT), or a multi-stage Dockerfile.
When detection fails
The language files aren't at the root or the language isn't supported. Add a Dockerfile and choose Dockerfile. See Troubleshooting builds and deployments.