# Stack file

URL: https://briq.cloud/docs/stack-file

> briq.yaml declares a stack in the repo it serves, shaped like GitHub Actions services. briq_up and POST /v1/stacks/up bring it up.

`briq.yaml` sits at the root of a repo and declares its stack. A service is a recipe and the
fields it changes, or an image with its settings, as in GitHub Actions `services:`.

```yaml
stack: shop
services:
  db:
    recipe: postgres
    image: pgvector/pgvector:pg16
    volume: { gb: 10 }
  cache: { recipe: redis }
  mail: { recipe: mailpit, expose: private }
  web:
    image: ghcr.io/acme/shop:latest
    ports: [3000]
    env:
      DATABASE_URL: postgres://postgres:{{secret:POSTGRES_PASSWORD}}@{{briq:db}}:5432/app
      REDIS_URL: redis://default:{{secret:REDIS_PASSWORD}}@{{briq:cache}}:6379
      SMTP_HOST: "{{briq:mail}}"
      SMTP_PORT: 1025
      STRIPE_KEY: { secret: STRIPE_KEY }
    expose: private
    sleep: 3h
```

Bring it up:

| Surface | Call                                                                                                                  |
| ------- | --------------------------------------------------------------------------------------------------------------------- |
| MCP     | `briq_up({ file: "<content of briq.yaml>", secrets: { STRIPE_KEY: "…" } })`. See [MCP tools](https://briq.cloud/docs/mcp/tools#briq_up) |
| REST    | `POST /v1/stacks/up` with `{ file, secrets? }`. See [REST reference](https://briq.cloud/docs/api/reference#stacks)                      |
| CLI     | `briq up --secret STRIPE_KEY`, in the repo. See [CLI](https://briq.cloud/docs/cli#briq-up)                                              |

## What up does

1. Makes each service the stack does not have yet, as `briq_run` makes it and under the same
   checks (key policy, quotas, plan, credits). Every new service is made, or none.
2. Leaves each service the stack has as it is. It never changes or deletes one.
3. Answers with every briq, the services `created` and `existing`, and the `outputs`: each recipe's
   connection strings, the secrets briq generated, and `<briq>:URL` for each published service.

Calling it again is safe: it makes nothing new. To change an existing service, destroy it, then
`up` again. `stack` in the call brings the file up as another stack: a branch's.

## Fields

| Field      | Notes                                                                                                          |
| ---------- | -------------------------------------------------------------------------------------------------------------- |
| `stack`    | Required. The stack's name: lowercase letters, digits, dashes                                                  |
| `services` | Required. Service name → a recipe service or an image service. 32 at most                                      |
| `sleep`    | When every service goes to sleep without use: `"30m"`, `"3h"`, `"7d"`, `"never"`. A service's own `sleep` wins |

The service name is the briq's name, so `{{briq:db}}` reaches the service `db`. A recipe that makes
several briqs (`wiki`, `plane`) keeps its own names.

### Recipe service

`recipe` and the fields of the service it makes. Each recipe's [cookbook](https://briq.cloud/cookbook) page lists
the ones it takes and their defaults.

| Field                        | Notes                                                                                                                                     |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `recipe`                     | `postgres`, `redis`, `node`…                                                                                                              |
| `image`                      | Another tag (`postgres:17`) or a compatible image (`pgvector/pgvector:pg16`)                                                              |
| `env`                        | Added to the recipe's env, or replacing one of its values                                                                                 |
| `cmd`, `size`, `files`       | As for an image                                                                                                                           |
| `volume`                     | `{ gb }`: the recipe mounts its own                                                                                                       |
| `checkout`, `steps`, `ports` | A language recipe: the code from a repo, the commands before it starts, its port. See [Run a GitHub repo](https://briq.cloud/docs/guides/run-a-github-repo) |
| `sleep`, `expose`            | As below                                                                                                                                  |

### Image service

Every field of a [briq spec](https://briq.cloud/docs/concepts/briq#a-briq-spec) except `name`: `image` (required),
`cmd` (a string run with `sh -c`, or the argv), `entrypoint`, `env`, `ports`, `size`, `volume`,
`files`, `healthcheck`, `sleep`, and `expose` as below.

### expose

| Value                          | Publishes                                                                                        |
| ------------------------------ | ------------------------------------------------------------------------------------------------ |
| `private` or `public`          | The recipe's front door, or the image's only port, as a URL                                      |
| `{ port: 3000, mode: public }` | Port 3000, as a URL                                                                              |
| `{ protocol: postgres }`       | The recipe's database port, as a [TCP endpoint](https://briq.cloud/docs/guides/connect-to-a-database-from-outside) |

`private` is a URL only whoever has it can open. See [Expose](https://briq.cloud/docs/guides/expose-a-preview-url).

## env

| Value                            | What the service gets                                                                |
| -------------------------------- | ------------------------------------------------------------------------------------ |
| `"text"`                         | The text. A YAML number or boolean is the text it was written as: `1025` is `"1025"` |
| `"{{briq:db}}"`                  | The address of the service `db`                                                      |
| `"{{secret:POSTGRES_PASSWORD}}"` | The value of that secret, held by a service of the stack                             |
| `{ secret: STRIPE_KEY }`         | A secret: the value passed at `up` in `secrets`, or one briq generates               |

`{{secret:…}}` and `{{briq:…}}` are put in when the service starts, inside a larger value too.
Status shows the placeholder, never the secret. The file never holds a secret's value: `up`
refuses `{ secret, value }`.

## Good to know

* Services are made after the ones they read with `{{briq:…}}` or `{{secret:…}}`, whatever their
  order in the file.
* Two services of the file that hold the same secret name cannot be read with `{{secret:…}}`:
  `up` refuses it. Name one of them differently in its `env`.
* A private repo: `checkout: { repo, token: { secret: GITHUB_TOKEN } }`, and the token's value
  passed at `up` in `secrets`.
* An endpoint that cannot be opened yet comes back in `warnings`; `briq_expose` it once it runs.
* JSON is valid too: `up` reads YAML and JSON.
* A mistake is reported by path: `services.db: Unrecognized key(s) in object: 'version'`.
* A value in `secrets` that the file never names is refused: a typo would go unnoticed.
* `up` counts as use of the stack: its running services go to sleep later.
