nubo.toml at the root of your repo. Nubo reads it on every push.
A minimal file
For a single service, the one key you’re likely to reach for is the build entrypoint:nubo.toml
Declaring infrastructure
To run more than one Frame from a repo, or to add a database, list your Frames explicitly. Each[[frames]] block is one Frame.
nubo.toml
version
Schema version. Defaults to 1. Leave it at 1.
[project]
Project-level settings.
name: a display name for the Project.
[[frames]]
One block per Frame. Nubo matches Frames by name, so keep names stable once you’ve picked them.
name(required): the Frame’s name.kind:"app"(the default) or"database".
path: the subdirectory to build from, for monorepos. Defaults to the repo root (.).stack: override auto-detection. One ofstatic,node,sveltekit,react,vue,go,dockerfile,paketo.stack = "dockerfile"forces the Dockerfile pack;stack = "paketo"sends the Frame to the Paketo builder (see below).builder:"raypacks"(the default) or"paketo". The escape hatch when a Frame needs the classic builder.port: the port your app listens on.replicas: how many copies to run. Defaults to1.
[frames.env]
Environment variables for the Frame above it. Keys are added or updated on each push; removing a key here does not delete it from the Frame (see Reconcile).
nubo.toml
[[frames.volumes]]
Persistent volumes for the Frame above it.
name: a name for the volume.mount_path: where it mounts inside the container.size_gb: size in GB. Defaults to1.read_only: mount read-only. Defaults tofalse.
replicas is forced to 1 for that Frame.
Database Frames
Setkind = "database" (or simply an engine) to declare a managed database as a Frame:
engine:postgres(the default),mysql,mongodb, orredis.version: the engine version, for example"16".storage_gb: the data volume size. It only grows (see below).inject_into: thenameof an app Frame to wire this database into.inject_as: the environment variable the connection string lands under. Defaults toDATABASE_URL.
inject_into = "web", Nubo sets DATABASE_URL on the web Frame to this database’s connection string, so your app connects with no secrets to copy. Set inject_as to use a different variable name.
[build]
entrypoint
The path Raypacks builds from. Defaults to auto-detect.
- For Go: the directory containing your
main.go. Auto-detected from repo-rootmain.go, then the firstcmd/*/main.goalphabetically. - Other packs ignore this field today.
., ./path, or path/to/dir. Absolute paths and .. segments are rejected. The directory must contain a main.go.
nubo.toml
How Nubo applies the file
On every push, Nubo reconciles your Frames to matchnubo.toml. Reconcile is additive-only and deliberately safe:
- It never deletes. Removing a Frame, database, volume, or env var from
nubo.tomldoes not remove it from Nubo. Delete it from your dashboard when you actually want it gone. - Database storage only grows. Raising
storage_gbexpands the volume. Lowering it is ignored, so data is never shrunk out from under you. - A volume pins the Frame to one replica. Declare a volume and
replicasbecomes1for that Frame, whatever number you wrote. - Databases are created for you. A
kind = "database"Frame innubo.tomlis provisioned automatically on the next push. - New app Frames are not. A new app Frame named in
nubo.tomlis not auto-created; create it in your dashboard first, thennubo.tomlkeeps its settings in sync. Until it exists, Nubo notes it and moves on rather than risk a broken deploy.
Precedence
Settings can come from three places. Higher beats lower:nubo.toml(committed to your repo)- Dashboard / API overrides (per-Frame, set in the UI)
- Raypacks auto-detection
nubo.toml checked into the repo is the source of truth. Dashboard tweaks fill in the gaps. Auto-detection is the fallback.
Validation
Raypacks rejects bad config at plan time, before the build runs. You’ll see a clear error in the build logs (“nubo.toml: build.entrypoint './cmd/missing' has no main.go”) rather than a confusing go build failure ten minutes later.
Inspecting the resolved plan
Every build prints a plan table that shows the final values and where each came from:decision line shows (auto) and you wanted something different, set the value in nubo.toml and redeploy.