# nolay.toml

URL: https://docs.nolay.ru/en/reference/nolay-toml/
Updated: 2026-09-23

> Every field of the project settings file with types and defaults.

`nolay.toml` lives in the root of the project repository. Every field is optional: without the file the agent detects the builder and port itself. The file in the repository takes priority over the panel form, and the panel never does more than this file.

Secrets are not written in `nolay.toml`: the file lives in the repository. Set them in the panel on the [Secrets](/en/guides/secrets/) page.

## Example

```toml
builder = "auto"

[run]
port = 3000

[env]
NODE_ENV = "production"

[health]
path = "/healthz"

[proxy]
domains = ["app.example.com"]
redirect_www = true

[[volumes]]
name = "data"
path = "/app/data"

[backup]
schedule = "0 3 * * *"
targets = ["volumes"]
```

## Fields

The table is built from the protocol schema `nolay-toml.v1.json`. A path with `[]` is an element of a table list, for example `[[cron]]`; `source(git)` and `source(archive)` are the two variants of the `[source]` section.

| Field | Type | Default | Description |
|---|---|---|---|
| `builder` | string | `"auto"` | How the image is built. `auto` picks on its own: your Dockerfile, then a Nolay template, then Railpack. `compose` is not supported yet, `nixpacks` is kept for older projects and is not used by `auto`. Values: `auto`, `nixpacks`, `railpack`, `dockerfile`, `compose`, `static`, `image`, `template:node`, `template:next-standalone`, `template:python-uvicorn`, `template:python-gunicorn`, `template:go`, `template:bun`, `template:ruby`, `template:static`. |
| `backup` | table |  | Backup schedule to your own S3 storage. No section means no backups. S3 keys are never written here: they are project secrets `NOLAY_S3_*`. |
| `backup.db` | table |  | How to dump the database. Required when `targets` contains `db`. |
| `backup.db.container_env` | string |  | Name of the variable that holds the database password, for example `POSTGRES_PASSWORD`. The agent takes the value from project secrets. |
| `backup.db.database` | string |  | Database name for `postgres` and `mysql`. |
| `backup.db.kind` | string | `"postgres"` | Which database runs in the project container. Values: `postgres`, `mysql`, `sqlite`. |
| `backup.db.service` | string |  | Name of a catalog service from `uses` to dump. User, database and password are then taken from the service. |
| `backup.db.sqlite_path` | string |  | Path to the database file inside the container, `sqlite` only. |
| `backup.db.user` | string |  | Database user for `postgres` and `mysql`. Not a secret. |
| `backup.keep_daily` | integer | `7` | How many daily copies to keep. |
| `backup.keep_monthly` | integer | `3` | How many monthly copies to keep. |
| `backup.keep_weekly` | integer | `4` | How many weekly copies to keep. |
| `backup.schedule` | string | `"0 3 * * *"` | Cron schedule, five fields, UTC time. |
| `backup.targets` | array of string | `["volumes"]` | What to back up: project volumes, a database dump, or both. Values: `volumes`, `db`. |
| `build` | table |  | Image build settings. |
| `build.args` | table of string |  | Build arguments (`ARG` in a Dockerfile). Keys use capital Latin letters, digits and `_`. Secrets do not belong here: the file lives in the repository. |
| `build.base_dir` | string |  | Reserved. The agent does not read this field yet; set the repository subdirectory in `source.subdir`. |
| `build.build_cmd` | string |  | Build command for Railpack, nixpacks and templates, for example `npm run build`. |
| `build.dockerfile` | string |  | Path to the Dockerfile inside the project directory. Defaults to `Dockerfile`. |
| `build.image` | string |  | Ready-made image for `builder = "image"`, for example `nginx:alpine`. Other builders ignore it. |
| `build.install_cmd` | string |  | nixpacks only: replaces its whole install step. Without it nixpacks installs dependencies from `package.json` and similar files. |
| `build.static_dir` | string |  | Directory with already built static files for `builder = "static"`, `dist` by default. The agent does not build the frontend. |
| `cron` | array of table |  | Scheduled jobs. Each run starts a one-off container from the project image. Up to 20 jobs per project. |
| `cron[].cmd` | string |  | Command that runs as `sh -c <cmd>` in the job container. |
| `cron[].name` | string |  | Job name, unique within the project: lowercase Latin letters, digits and hyphens, up to 32 characters. |
| `cron[].schedule` | string |  | Cron schedule, five fields, UTC. A run is skipped while the previous one is still going. |
| `cron[].timeout_secs` | integer | `900` | How many seconds one run may take, 1 to 21600. After that the container is stopped. |
| `env` | table of string |  | Non-secret environment variables. Secrets are set in the panel; if a key is in both places, the secret wins. |
| `health` | table |  | Readiness check. No section: the project is ready once the container runs. With `path`: the agent waits for a 2xx or 3xx answer on that path. |
| `health.interval_sec` | integer | `10` | Pause between check attempts, seconds. |
| `health.path` | string |  | HTTP check path, for example `/healthz`. Without it the image `HEALTHCHECK` is used. |
| `health.timeout_sec` | integer | `60` | How long to wait for readiness in total, seconds. If it runs out, the new version is not switched on and the old one keeps running. |
| `protection` | table |  | Domain protection on the entry proxy. No section: the defaults from this table apply. |
| `protection.allow_ips` | array of string | `[]` | Addresses and subnets allowed to reach the domain. Empty: open to everyone. The ACME certificate check is never blocked. |
| `protection.block_bad_bots` | boolean | `true` | Answer 403 to known scanners by `User-Agent`. Search engine crawlers are not on the list. |
| `protection.frame_options` | string | `"SAMEORIGIN"` | Value of the `X-Frame-Options` header: `SAMEORIGIN` or `DENY`. Remove the field and the header is not set. |
| `protection.https_redirect` | boolean | `true` | Redirect HTTP to HTTPS with code 308. Does not apply to `*.localhost`, `*.test` and IP addresses. |
| `protection.max_body_mb` | integer | `32` | Maximum request body size in MiB. Larger requests get 413. |
| `protection.rate_limit` | string | `"300/1m"` | Requests per IP as `<count>/<window>`, for example `300/1m`, or `off`. |
| `protection.waf` | string | `"off"` | Coraza attack filter with OWASP CRS rules. `low` has almost no false positives, `medium` is stricter. Costs about 100 MiB of memory. Values: `off`, `low`, `medium`. |
| `protection.waf_exclude` | array of string | `[]` | Paths where the filter is off, by prefix, for example `/api/upload`. |
| `proxy` | table |  | Project domains. No domains: the project is reachable only inside the Docker network on the server. |
| `proxy.domains` | array of string | `[]` | Lowercase domains, no `*`. The agent on your server issues the certificate. |
| `proxy.redirect_www` | boolean | `false` | Redirect `www.<domain>` to `<domain>` with code 308. |
| `resources` | table |  | Project container limits. |
| `resources.cpu` | float |  | CPU share, for example `0.5` or `2`. |
| `resources.mem_mb` | integer |  | Memory limit in MiB for the container and the build. Not set: the build runs with a 512 MiB limit. |
| `run` | table |  | How the project runs. |
| `run.expose` | array of string | `[]` | Reserved, the agent does not read this field yet. |
| `run.port` | integer |  | Port the application listens on. Templates have their own default, so it is optional. |
| `run.post_deploy` | string |  | Reserved, the agent does not read this field yet. |
| `run.pre_deploy` | string |  | Reserved, the agent does not read this field yet. Run migrations from the application start command. |
| `run.privileged_caps` | array of string | `[]` | Linux capabilities beyond the base set, without the `CAP_` prefix, up to eight. Each one is written to the agent log. |
| `run.start_cmd` | string |  | Start command when the builder does not detect it, for example `npm start`. |
| `source` | table |  | Where the agent takes the code from. Usually the panel writes this section, there is no need to keep it in the repository. |
| `source(git).commit` | string |  | Exact commit. Set by the panel, not written in the repository. |
| `source(git).kind` (required) | string |  | `git` for a repository. Values: `git`. |
| `source(git).ref` | string | `"main"` | Branch, tag or commit hash. |
| `source(git).subdir` | string |  | Repository subdirectory to build from. Not set: the root. |
| `source(git).url` | string |  | Repository address over HTTPS or SSH. Do not put a login or token in the address: private repositories use the `NOLAY_GIT_TOKEN` and `NOLAY_GIT_SSH_KEY` secrets. |
| `source(archive).format` | string | `"tar_gz"` | Archive format. Set by the panel on upload. Values: `tar_gz`, `zip`, `tar`, `tar_zst`, `tar_xz`, `tar_bz2`. |
| `source(archive).kind` (required) | string |  | `archive` for an archive uploaded through the panel. Values: `archive`. |
| `source(archive).sha256` | string |  | Archive checksum. The agent verifies it before unpacking. |
| `source(archive).size` | integer | `0` | Archive size in bytes. |
| `source(archive).upload_id` | string | `"00000000-0000-0000-0000-000000000000"` | Upload ID. Set by the panel. |
| `uses` | array of string | `[]` | Server catalog services the project connects to, for example `["db", "cache"]`. The connection string arrives as the `DATABASE_URL`, `REDIS_URL` or `MONGO_URL` secret. |
| `volumes` | array of table |  | Docker volumes for persistent data. Without volumes the container contents are lost on the next deploy. |
| `volumes[].name` (required) | string |  | Volume name within the project: lowercase Latin letters, digits and hyphens. |
| `volumes[].path` (required) | string |  | Absolute path inside the container where the volume is mounted. |
| `workers` | array of table |  | Background processes: containers from the same image without a port or domain. Up to 10 per project. |
| `workers[].cmd` | string |  | Start command as `sh -c <cmd>`. The key can also be written as `start_cmd`. |
| `workers[].name` | string |  | Process name, unique within the project. |
| `workers[].replicas` | integer | `1` | How many identical containers to run, 1 to 10. |
| `workers[].resources` | table |  | Process limits. Not set: taken from the project `[resources]`. |
| `workers[].resources.cpu` | float |  | CPU share. |
| `workers[].resources.mem_mb` | integer |  | Memory limit in MiB. |
