---
url: /guide/environment.md
description: >-
  Environment variables, secrets, database and service references, inherit_env,
  platform variables and config files.
---

# Environment and secrets

Variables go under `[services.<name>.env]`. A value is one of four kinds:

```toml
[services.web.env]
LOG_LEVEL = "info"                                         # literal
STRIPE_KEY = { secret = true }                             # secret
DATABASE_URL = { from_database = "db" }                    # database property
S3_KEY = { from_service = "storage", key = "ACCESS_KEY" }  # another service's variable
```

## Secrets

`{ secret = true }` declares the key; the value is written separately and is
stored encrypted. It is never shown again, in the panel or the CLI.

```bash
duploy secret set web STRIPE_KEY=sk_live_… OTHER=…
duploy secret set web - < .env.production    # read a .env file from stdin
duploy secret rm web STRIPE_KEY
duploy env web                               # names and kinds, never values
```

`K=` writes an empty value. Removing a value with `secret rm` keeps the key in
the config, so the next deploy fails with `missing_secret` until a value is set
again.

## Database references

`from_database` reads a property of a managed database in the same project:

| `property` | Postgres | MySQL | Redis |
|---|---|---|---|
| `url` (default) | `postgres://app:…@db.shop.internal:5432/db` | `mysql://app:…@…:3306/db` | `redis://:…@…:6379/0` |
| `host` | `db.shop.internal` | same form | same form |
| `port` | `5432` | `3306` | `6379` |
| `user` | `app` | `app` | empty |
| `password` | generated | generated | generated |
| `database` | the database name | the database name | `0` |

```toml
PGHOST = { from_database = "db", property = "host" }
```

## Service references

`from_service` copies a variable from another service's resolved environment,
secrets included. The usual use is sharing one credential between the service
that owns it and the services that call it:

```toml
[services.storage.env]
ACCESS_KEY = { secret = true }

[services.web.env]
S3_ACCESS_KEY = { from_service = "storage", key = "ACCESS_KEY" }
```

The key has to exist in the target's `env` (or be one of the platform
variables below, such as `PORT`).

## Inheriting a whole environment

`inherit_env` starts a service from another service's resolved environment.
Its own `env` then adds to it and overrides it:

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

Order of precedence, lowest first: platform variables, the inherited
environment, the service's own `env`. Cycles are rejected.

## Platform variables

Every container gets these. Your own `env` may override them.

| Variable | Value |
|---|---|
| `PORT` | The service's `port` |
| `DUPLOY_SERVICE` | Service name |
| `DUPLOY_PROJECT` | Project name |
| `DUPLOY_DEPLOYMENT` | Deploy id (services) |
| `DUPLOY_RUN` | Run id (cron jobs) |
| `DUPLOY_CPU` | CPU limit in cores |
| `DUPLOY_MEMORY_BYTES`, `DUPLOY_MEMORY_MB` | Memory limit |
| `GOMAXPROCS` | CPU limit rounded up |

## Config files

Small config files can be mounted into the container, read-only, without
baking them into the image:

```toml
[services.web.files]
"/etc/app/config.yml" = """
listen: 0.0.0.0:${PORT}
log_level: ${LOG_LEVEL}
"""
"/etc/app/ca.pem" = { from = "deploy/ca.pem", mode = "0600" }
```

* The key is an absolute path in the container.
* The value is the content, or `{ content = "…" }`, or `{ from = "<repo path>" }`
  to read a file from the repository at the deployed commit.
* `mode` is an octal string, default `"0644"`.
* `${VAR}` is replaced from the service's environment when the container is
  created; an unknown name is a config error. Write `$${` for a literal `${`.
* Limits: 64 KiB per file, 16 files and 256 KiB per service. Files may not sit
  inside a volume path.

Changing a file, including the repository file behind `from`, starts a new
container; nothing is edited in place.
