# Applications and environments

What an application and an environment are, and how to create them.


## Applications

An application is the thing you deploy: one codebase, with an environment for each place it runs. You create one in the console under **Applications**, or let `brewless init` create it from your project.

An application has a name, a framework and the Scaleway project it runs in. With several projects connected you choose it when you create the application, and it holds for all its environments; see [Connecting providers](/applications/providers#several-scaleway-projects). The framework decides how the application is built, which release commands run and where its schedule is read from. See [Frameworks](/reference/frameworks).

## Environments

An environment is one running copy of an application. Production is what your visitors use; staging is a copy where you try a release first.

When you create an environment you choose:

- **A kind**: production, staging or development.
- **A region**: the Scaleway region everything of this environment lands in. See [Regions](/reference/regions).

Each environment has its own container, variables, domains, scaling bounds and releases. Nothing is shared between two environments unless you point them at the same resource yourself.

> [!NOTE]
> Every plan has as many environments as you like, production included. Your plan decides how many applications you can have: one without a subscription; see [Billing](/organisation/billing).

## Setting an environment up

A new environment has nothing at your providers yet. On its **Resources** page, **Set up** has Brewless make what it needs, in your own accounts. From your project, `brewless init` does it for the environments it adds, and for one environment later:

```bash
brewless provision production
```

The command asks what the environment should have; the options of [provision](/cli/commands#provision) say the same without questions. **Set up** in the console asks the same three things: which database (a new one, one that exists already, or none), where jobs wait (in the database, at Scaleway Queues, or nowhere) and whether to make a bucket for files.

This makes, at Scaleway:

- a private registry for your images, when the project has none from Brewless yet;
- a web, a release and a worker container. They are made but not started: they start with your first deploy. Until then they name Brewless's public base image, by digest, which Scaleway pulls without a key, so nothing has to be in your registry first;
- a Serverless SQL Database, unless you choose otherwise. It sleeps when nobody asks it anything;
- a queue at Scaleway Queues, when you ask for one;
- a private bucket at Object Storage for the files of your application, when you ask for one;
- the first variables in your own Secret Manager, among them a new application key.

With bunny.net connected it also puts a pull zone in front of the web container, routed through the EU only, accepting TLS 1.2 and newer only, that asks the container once more when it does not answer (see [When the origin does not answer](/deployments/deployments#when-the-origin-does-not-answer)).

> [!NOTE]
> Scaleway does not offer every product in every region. Serverless SQL Database is only in Paris, and Scaleway Queues only in Paris and Amsterdam. Elsewhere, setting up offers a database that exists already or none, and lets jobs wait in the database or nowhere; a choice that cannot be made in the region is refused before anything is made.

Setting up only makes things. What it finds under the same name is used as it is; nothing is changed or removed. If it stops halfway, trying again carries on from what was made.

> [!NOTE]
> Your application signs in to its database as an identity of its own, which may use the databases of this project and nothing else. Brewless makes that identity when its key may manage identities (the permission set `IAMManager`). When it may not, the result names the two variables, `DB_USERNAME` and `DB_PASSWORD`. Give the key that right and set the environment up again, or add them yourself before your first deploy. Until your variables name them, a deploy is refused before anything is built. See [Variables](/running/variables).

### Setting it up again

An environment Brewless set up can be set up again, with the same command or button. That run uses the choices of the first one, whatever you answer now, and makes only what is missing: the database identity a key without the right could not make, for instance. Your variables keep every value they have. Only a name the first run left for you to set, and that is still missing or empty, gets the value Brewless could now make. That is a new revision of your variables, which reaches the containers with your next deploy.

An environment whose containers were taken over instead of made is not set up again.

### A database that exists already

Instead of a new database you can name one that stands in your Scaleway project, in the region of the environment. It is read and used as it is: nothing about it is changed, and it is listed among the resources of the environment.

- For a Serverless SQL Database the variables point at it, and your application signs in with an identity of its own, as with a new one.
- For a Managed Database the environment gets a login of its own, as when you [link](/running/databases#environments-and-sharing) one: a logical database and a user named after the application and the environment, such as `shop_production`, with every right on that database and none on the others. The password is made once and kept in your Secret Manager as `<application>-<environment>-db-password`; setting the environment up again gives the user that same password. The variables hold its address, what it speaks (PostgreSQL or MySQL), that database and that user. When the instance has a public endpoint, that one is used, unless the environment is on a [Private Network](#a-private-network).

Two environments can use the same database.

### A queue

| Choice | What happens |
| --- | --- |
| Scaleway Queues | Queues is switched on for the project when it was off, and a queue named after the application and the environment is made. The variables set `QUEUE_CONNECTION=sqs` and where the queue is. This is what you get when you say nothing, where Scaleway offers Queues |
| In the database | Nothing is made. The variables set `QUEUE_CONNECTION=database`. The worker is then called every minute to look for jobs and never sleeps, so Scaleway bills it around the clock: choose it only when you are sure. See [How the worker is called](/running/queues-and-schedule#how-the-worker-is-called) |
| None | The variables set `QUEUE_CONNECTION=sync`: a job runs where it is dispatched |

A queue at Scaleway takes a key of its own. Brewless makes one that may send and receive and may not make or remove queues, and keeps it in your Secret Manager. The key that makes the queue exists for that moment only and is removed again. Because Laravel's `sqs` connection reads the same `AWS_*` names as its `s3` disk, the queue's key is in `SQS_ACCESS_KEY_ID` and `SQS_SECRET_ACCESS_KEY`; the `brewless/laravel` package hands them to the `sqs` connection.

> [!NOTE]
> Scaleway Queues does not answer everything SQS does. Sending and receiving jobs work; asking a queue how many jobs it holds, as Laravel's `Queue::size()` does, is refused.

### A bucket for files

A container keeps no files of its own between requests. Asked for a bucket, Brewless makes a private one in the project of the environment (also when the key you connected prefers another project), named after the application, the environment and your project, and an identity that may read the buckets of this project and read, write and remove the objects in them, and may not make, change or remove a bucket. Scaleway grants this per project, not per bucket. The variables set `FILESYSTEM_DISK=s3` and the `AWS_*` names Laravel's `s3` disk reads.

When the key Brewless has may not manage identities, the bucket is still made and the result names `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` for you to add.

`storage` in `brewless.yml` names the bucket. To keep a file that is overwritten or removed for a while, give it as a map with `keep_versions_days`:

```yaml brewless.yml
environments:
  production:
    storage:
      name: shop-production-files
      keep_versions_days: 7
```

Brewless then switches on versioning for the bucket: putting a file under a name that is there already, or removing one, keeps what was there as an older version. Then it gives the bucket three lifecycle rules: Object Storage removes an older version `keep_versions_days` after it became one, clears a delete marker that has no versions left behind it, and aborts an upload in parts that did not complete a day after it began. A file itself is never removed by them: what your application put stays until it removes it. The bucket gets no bucket policy, and the identity of the application keeps the rights it had on objects.

With only a name, or without `keep_versions_days`, the bucket gets no versioning and no lifecycle. Another number of days sets the bucket up again on the next deploy, an environment that runs included; the same number starts nothing. Leaving `keep_versions_days` out again switches nothing off: versioning and its lifecycle stay as they are at Scaleway, and `brewless plan` says so.

Object Storage keeps what you put in a bucket in Paris, Amsterdam and Warsaw across three zones of the region (Standard Multi-AZ, the class an object gets when your application names none). In Milan it has only Standard One Zone: three racks in one zone. `brewless plan` says so next to a bucket or a bucket for backups there.

### A bucket for backups

`backup` in `brewless.yml` asks for a second, private bucket for backups, in a region of its own. It is only made from the file; the console does not offer it.

```yaml brewless.yml
environments:
  production:
    storage: shop-production-files
    backup:
      name: shop-production-backups
      region: nl-ams
      expire_days: 28
      keep_versions_days: 7
```

`region` and `expire_days` are required, `name` and `keep_versions_days` are optional; without `name` the bucket is named after the application, the environment and your project, with `-backups`. Brewless makes the bucket in the project of the environment and switches on versioning first: putting an object under a name that is there already keeps the object that was there as an older version, so a backup cannot be overwritten. Then it gives the bucket three lifecycle rules: Object Storage removes every object in it `expire_days` after it was put, removes an older version `keep_versions_days` after it became one (`expire_days` when you leave it out), and clears a delete marker that has no versions left behind it; and it aborts an upload in parts that did not complete a day after it began. With versioning, an object that expires first becomes an older version, so a backup is kept at most `expire_days` plus `keep_versions_days` before it is gone: 35 days in the example, and twice `expire_days` without `keep_versions_days`. When you have promised to keep backups no longer than a number of days, make the two add up to at most that. Then it makes two identities, each with a key of its own in your Secret Manager, in the region of the environment under the path `/brewless`:

- `brewless-<application>-<environment>-backup-write`, whose key the application gets. It may put a backup, also in parts, and nothing more. Its key is kept as the secret `<application>-<environment>-backup-write-key`.
- `brewless-<application>-<environment>-backup-read`, for a restore. Its key is kept as the secret `<application>-<environment>-backup-read-key` and never goes into the variables.

Last, Brewless puts a bucket policy on the bucket. Once a bucket has a policy, Object Storage lets in only the principals the policy names, and only as far as their IAM policy allows too: the write identity may put objects and abort an upload in parts (nothing else: it cannot read, list or remove an object or a version of one, nor change the versioning or the lifecycle of the bucket), the read identity may read and list them and their older versions, and Brewless's own key keeps every right on the bucket. Every other key of the project, also the one of the bucket for files, can neither read nor remove a backup. Together this means the key the application gets can add backups, but cannot remove or overwrite one it put before. Each of these steps is set again when the environment is set up again, which changes nothing. Another `expire_days` or `keep_versions_days` in the file sets the bucket up again on the next deploy, versioning and lifecycle included; a bucket for backups made before Brewless switched on versioning gets it then too.

The variables get `BACKUP_BUCKET`, `BACKUP_REGION`, `BACKUP_ENDPOINT`, `BACKUP_ACCESS_KEY_ID` and `BACKUP_SECRET_ACCESS_KEY`, the last two being the key that may only put. Your files disk is left as it is.

> [!WARNING]
> The bucket policy needs identities. When the key Brewless has may not manage them (IAMManager), or Brewless cannot read whom its own key belongs to, no bucket policy is set, nothing is given to the application, and setting the environment up stops with what to do.

To restore, read the latest version of the secret `<application>-<environment>-backup-read-key` in Secret Manager, in the Scaleway console of the project and the region of the environment. It holds `{"access_key": "…", "secret_key": "…"}` for `https://s3.<region>.scw.cloud`. Use it on your own machine for the restore only, and never put it in the application's variables. When an object was put again under the same name, the earlier one is an older version of it: list the versions and read the one you need by its version ID.

### Databases per tenant

`databases` in `brewless.yml`, with a `prefix`, lets the running application ask Brewless for a Serverless SQL Database per tenant of its own. Setting the environment up then makes a key the application signs those requests with, kept as the secret `<application>-<environment>-databases-key`, and the variables get `BREWLESS_API_URL`, `BREWLESS_ENVIRONMENT` and `BREWLESS_DATABASES_KEY`. The environment's own database has to be a Serverless SQL Database. See [Databases per tenant](/running/tenant-databases).

Until your environment has a domain of its own it answers on the address of the pull zone, or of the web container when there is no pull zone.

### A Private Network

A Serverless SQL Database, Scaleway Queues and Object Storage are reached over the internet, with a key. A Managed Database, and a cache (see [A cache](#a-cache)), can be reached over a Private Network instead, which nothing outside your Scaleway project can reach. `network: private` in `brewless.yml` puts the environment on one:

```yaml brewless.yml
environments:
  production:
    network: private
```

- Each Scaleway project gets one Private Network per region, called `brewless`, made the first time an environment asks for it. Every environment of the project that says `network: private` joins it. A Private Network costs nothing at Scaleway.
- The web, release and worker containers go on it. A new environment's containers are made on it; the containers of an environment that runs are put on it, and Scaleway deploys them again for that.
- A Managed Database the environment uses gets a private endpoint on the network, and `DB_HOST` and `DB_PORT` move to it, unless you set them yourself. Its public endpoint stays: Brewless never takes one away. Remove it in your Scaleway console once nothing uses it.
- A Serverless SQL Database cannot join a network and stays as it is.

A container or a Managed Database that is on another Private Network already is not moved; the set-up stops and says which. A database has one private endpoint at most. An environment does not leave the network from `brewless.yml`: `network: public` for an environment on it is refused.

### A cache

A cache keeps what your application would otherwise work out again, such as rendered fragments or the answers of slow services, and Laravel can keep its sessions and locks there too. `cache` in `brewless.yml` gives the environment a Scaleway Managed Database for Redis:

```yaml brewless.yml
environments:
  production:
    cache: shop-cache
  staging:
    cache:
      name: shop-staging-cache
      size: RED1-XS
```

- A cache of that name that stands in the region is used as it is; otherwise one is made, with the size given (Scaleway's node types, `RED1-micro` to `RED1-XL`; without a size `RED1-micro`) and the newest version of Redis Scaleway offers. Scaleway bills a cache by its size, for every hour it exists: a cache does not sleep.
- It is reached over the project's Private Network only, so a cache brings `network: private` along (see [A Private Network](#a-private-network)), and over TLS.
- `nodes: 3` (up to 6) makes a new cache a cluster: Redis spreads the keys over the nodes and keeps answering when one fails, which a cache of one node does not; Scaleway gives an availability promise only from three nodes. Every node is billed, all the time, and the number of nodes is chosen when the cache is made: a deploy never changes it for one that stands. The nodes live in one zone of the region. The application gets every node in `BREWLESS_REDIS_NODES`, and `brewless/laravel` 0.14 or later makes its `default` and `cache` redis connections a cluster of them, over TLS. It is off unless you ask: without `nodes` a cache has one.
- A cache Brewless makes has a user, `brewless`, whose password goes into your Secret Manager, as `<application>-<environment>-cache-key`, before the cache is made; Brewless never keeps it. A cache that stood there already has users of your own making, so `REDIS_USERNAME` and `REDIS_PASSWORD` are left for you to set.
- The variables get `CACHE_STORE=redis`, `REDIS_CLIENT=phpredis`, `REDIS_HOST`, `REDIS_PORT`, `REDIS_USERNAME`, `REDIS_PASSWORD` and `BREWLESS_REDIS_CA`, the certificate of the cache's cluster. With `brewless/laravel` 0.8 or later your redis connections speak TLS and trust that certificate and no other.
- A cache that stood there already and has no endpoint on the network gets one; its other endpoints stay.

Scaleway offers Managed Database for Redis in Paris, Amsterdam and Warsaw, not in Milan. A cache that stands is not swapped for another name or size from `brewless.yml`; that is refused. `cache: false` lets it go from the environment: it keeps running, and costing, at Scaleway until you remove it there.

### From brewless.yml

`brewless deploy` sets the environment up from your `brewless.yml` before it deploys, so a new environment is a few lines in the file:

```yaml brewless.yml
environments:
  staging:
    kind: staging
    region: fr-par
    database: shop-staging
    queue: sqs
    storage: shop-staging-files
```

- An environment the file names that does not exist yet is made, with the kind and region of the file; without them it is staging, in Paris.
- `database` names the database. One that Brewless manages already, also for another application, is linked with a login of the environment's own, as on the [Databases](/running/databases#environments-and-sharing) page; a new environment is set up first and linked right after. Another one of that name that stands in the region is used as it is; otherwise a Serverless SQL Database of that name is made. `storage` names the bucket that is made. `queue` is `sqs`, `database` or `false`. `network: private` puts the environment on the project's Private Network; see [A Private Network](#a-private-network). `cache` gives it a Managed Database for Redis; see [A cache](#a-cache).
- Only what the file names is made. An environment the file sets up without a `database` has none.

For an environment that runs already, the file can add what it does not have yet: a database, a queue at Scaleway Queues, a bucket or a bucket for backups. Their variables are added to the environment's own, so those have to be kept through Brewless (push them once with `brewless env:push`). A name your variables have keeps its value, unless it is still the one Brewless gave the environment without that resource, such as `QUEUE_CONNECTION=sync` before a queue was added. That is a new revision of your variables, which the release of the same deploy takes.

Domains the file names are added after a yes; see [Domains](/running/domains).

What stands holds data, so a deploy never switches it for something else. Another region, another kind, another database or bucket, a bucket for backups with another name or region, or a queue other than the one the environment was set up with, is refused before anything is made, with what stands. The one switch a deploy makes is `queue: sqs` for an environment whose jobs waited in its database: that only adds a queue at Scaleway Queues, and `QUEUE_CONNECTION` becomes `sqs` when it still says what Brewless set (a value you set yourself stays). Let the jobs in the database finish first: the worker no longer looks there afterwards. `false` for a database, a bucket, `backup` or `cache` lets it go from the environment: the resource itself keeps running at Scaleway, and your variables keep pointing at it until you change them. A key you leave out keeps what stands. `brewless plan` shows each of these lines before you deploy.

If you have containers at your provider already, [adopt](#resources) them instead.

## Resources

Everything an environment uses at your providers is listed under **Resources**: containers, databases, buckets, secrets, pull zones and DNS zones.

A database, a bucket or a DNS zone can serve more than one environment: staging and test sharing one database, for example. On the Resources page of the second environment it is offered under *Adopt existing resources*, marked with the environment that uses it already; adopting it there shares it. Releasing it from one environment keeps it for the others. A container, a secret or a pull zone is one environment's own and cannot be shared.

Under **Resources** in the organisation's menu, everything in your Scaleway projects and bunny.net account is listed at once, each thing with its project when there are several: what Brewless manages, with the environments each thing serves, and what stands there in no environment.

- **Adopting** a resource that already exists at your provider records its current settings as what Brewless expects. Nothing at the provider is changed.
- **Differences** are shown when what Brewless recorded no longer matches what stands at the provider. Brewless reports them; it does not change anything by itself.
- **Releasing** a resource removes the reference from Brewless. The resource itself keeps running at the provider.

## Leaving with an environment

You can take an environment out of Brewless at any moment without touching what runs. See [Leaving Brewless](/applications/leaving).

## Removing an application

Removing an application removes it and its environments from Brewless. Nothing in your own provider account is touched: containers keep running and databases keep their data until you remove them at the provider yourself. Only the [test addresses](/running/domains#the-test-address) of its environments stop leading anywhere: their records are in Brewless's own zone.
