---
url: /reference/duploy-toml.md
description: Every key of duploy.toml with its type, default and rules.
---

# duploy.toml

The file lives at the root of the repository (or at the config path set on
the project). Unknown keys are errors. Every error is reported with its key
path and line, and an invalid file is not applied at all.

```toml
version = 1

[services.<name>]
# …

[databases.<name>]
# …
```

| Key | Type | Required | Notes |
|---|---|---|---|
| `version` | integer | yes | Always `1` |
| `services` | table | no | Service name → service |
| `databases` | table | no | Database name → database |

Names of services and databases share one namespace and must match
`^[a-z][a-z0-9-]{0,31}$`.

## Service

| Key | Type | Default | Notes |
|---|---|---|---|
| `type` | `"web"` | `"worker"` | `"cron"` | `"web"` | |
| `source` | table | — | Required. See [source](#source). |
| `port` | integer | — | Required for `web`; not allowed for `worker` and `cron` |
| `replicas` | integer ≥ 1 | `1` | Not for `cron`; `1` when the service has a volume |
| `command` | array of strings | image `CMD` | |
| `domains` | array of tables | `[]` | `web` only. See [domains](#domains). |
| `health` | table | by type | Not for `cron`. See [health](#health). |
| `schedule` | string | — | `cron` only, required there. Five fields, UTC. |
| `timeout` | duration | platform limit | `cron` only |
| `resources` | table | plan defaults | See [resources](#resources). |
| `inherit_env` | string | — | Service whose resolved env this one starts from |
| `node` | string | — | Pin to a named node |
| `env` | table | `{}` | See [env](#env). |
| `volumes` | table | `{}` | See [volumes](#volumes). |
| `files` | table | `{}` | See [files](#files). |
| `network` | table | — | See [network](#network). |

Durations are written `30s`, `5m`, `1h`.

### source

Exactly one of `path`, `repo`, `image`, `image_of`.

| Key | Type | Default | Notes |
|---|---|---|---|
| `path` | string | `"."` | Build context, relative to the repository root |
| `repo` | string | — | `owner/name`; build from another repository |
| `branch` | string | default branch | Only with `repo` |
| `dockerfile` | string | `"Dockerfile"` | Relative path |
| `build_args` | table | `{}` | `path`/`repo` only. `KEY = "value"` or `KEY = { secret = true }`. Names match `^[A-Za-z_][A-Za-z0-9_]*$`. |
| `image` | string | — | Image reference; no build |
| `image_of` | string | — | Another service's image; not itself, no chains |

`path` and `repo` sources need a project with a linked repository.

### domains

| Key | Type | Default | Notes |
|---|---|---|---|
| `host` | string | — | Required |
| `path` | string | `"/"` | Must start with `/` |
| `strip_prefix` | boolean | `false` | |
| `port` | integer | service `port` | Container port for this domain |
| `protocol` | `"http1"` | `"h2c"` | `"http1"` | `h2c` for gRPC backends |

The same `host` + `path` may appear only once across the project.

### health

| Key | Type | Default | Notes |
|---|---|---|---|
| `http` | string | — | Path for an HTTP GET; 2xx and 3xx pass |
| `cmd` | array of strings | — | Command run in the container; exit 0 passes |
| `interval` | duration | `10s` | |
| `timeout` | duration | `5s` | |
| `retries` | integer | `3` | Consecutive failures before unhealthy |

Exactly one of `http` and `cmd`. Without `health`, a `web` service is probed
with a TCP connect to `port` and a `worker` is healthy after 5 seconds up.

### resources

Also used by databases.

| Key | Type | Notes |
|---|---|---|
| `cpu` | number | Cores |
| `memory` | string | `512M`, `2G`, `256Mi`, `1GB` |
| `pids` | integer | Process limit |
| `disk` | string | Root filesystem quota; for databases, the data volume |
| `nofile` | integer | Open file limit |
| `read_only` | boolean | Read-only root filesystem, writable `/tmp` |
| `runtime` | `"runc"` | `"sysbox-runc"` | `"kata-clh"` | |

Missing keys come from the plan defaults. Values above the plan maximum are
errors.

### env

| Value | Meaning |
|---|---|
| `"text"` | Literal |
| `{ secret = true }` | Value set with `duploy secret set` |
| `{ from_database = "db", property = "url" }` | `url` (default), `host`, `port`, `user`, `password`, `database` |
| `{ from_service = "api", key = "TOKEN" }` | Variable of another service; `key` required |

### volumes

| Value | Meaning |
|---|---|
| `"/data"` | Mount path |
| `{ path = "/data", size = "10G", backup = { schedule = "0 4 * * *", retain = 7 } }` | With quota and snapshots |

Paths are absolute, not `/`, and unique per service. `retain` is at least 1.

### files

| Value | Meaning |
|---|---|
| `"content"` | Inline content |
| `{ content = "…", mode = "0640" }` | Inline content with a mode |
| `{ from = "config/app.yml" }` | Repository file at the deployed commit |

Keys are absolute file paths in the container, outside every volume path.
`${VAR}` is resolved from the service env and platform variables; `$${`
escapes. Limits: 64 KiB per file, 16 files, 256 KiB in total.

### network

| Key | Type | Notes |
|---|---|---|
| `egress` | array of strings | Hosts, `*.wildcards`, IPs and CIDRs this service may reach; at most 64. Absent means unrestricted. |

## Database

| Key | Type | Default | Notes |
|---|---|---|---|
| `engine` | `"postgres"` | `"mysql"` | `"redis"` | — | Required |
| `version` | string | — | Required. `"18"` or `"18.2"`. Minimum: Postgres 18, MySQL 8, Redis 7. |
| `extensions` | array of strings | `[]` | Postgres only: `pgvector`, `postgis`, `pg_cron`, `timescaledb` |
| `backup` | table | — | `schedule` (five fields, UTC) and `retain` |
| `resources` | table | plan defaults | See [resources](#resources). |
| `node` | string | — | Pin to a named node |

## A complete example

```toml
version = 1

[services.web]
source = { path = ".", dockerfile = "Dockerfile" }
port = 8080
replicas = 2
domains = [{ host = "shop.example.com" }]
health = { http = "/healthz", interval = "10s", retries = 6 }
resources = { cpu = 1.0, memory = "1G" }

[services.web.env]
DATABASE_URL = { from_database = "db" }
REDIS_URL = { from_database = "cache" }
SESSION_KEY = { secret = true }

[services.worker]
type = "worker"
source = { image_of = "web" }
inherit_env = "web"
command = ["bin/worker"]

[services.nightly]
type = "cron"
source = { image_of = "web" }
inherit_env = "web"
command = ["bin/report"]
schedule = "0 2 * * *"
timeout = "30m"

[databases.db]
engine = "postgres"
version = "18"
extensions = ["pgvector"]
backup = { schedule = "0 3 * * *", retain = 7 }

[databases.cache]
engine = "redis"
version = "7"
```
