diff --git a/sites/platform/src/administration/users.md b/sites/platform/src/administration/users.md index 2d744eb678..776dafa7de 100644 --- a/sites/platform/src/administration/users.md +++ b/sites/platform/src/administration/users.md @@ -42,7 +42,7 @@ A user can have one of the following roles on an environment type which grants t | Contributor | Yes | No | Yes | Yes | Yes | No | No | | Viewer | Yes | No | No | Yes | No | No | No | -To customize which roles can use SSH, set [`access` in your app configuration](/create-apps/app-reference/single-runtime-image.md#access). +To customize which roles can use SSH, set [`access` in your app configuration](/create-apps/image-properties/access.md). ### View a user's permissions across all of the projects in your organization diff --git a/sites/platform/src/create-apps/app-reference/_index.md b/sites/platform/src/create-apps/app-reference/_index.md index c76a52b910..b9a8580a1b 100644 --- a/sites/platform/src/create-apps/app-reference/_index.md +++ b/sites/platform/src/create-apps/app-reference/_index.md @@ -1,13 +1,49 @@ --- -title: "App reference" -weight: 4 +title: "Choose an image type" +weight: -19 description: Configure your app and control how it's built and deployed on {{% vendor/name %}}. layout: single --- + + +An _image_ represents the configuration for the container that contains the application (or service) that you want to deploy. + + To define your app, you can either use one of {{% vendor/name %}}'s [single-runtime image](/create-apps/app-reference/single-runtime-image.md) or its [composable image (BETA)](/create-apps/app-reference/composable-image.md). +The single-runtime image type has the following characteristics: +- Can contain only a single runtime +- Requires more manual configuration the composable images, but are more flexible +- Initial build takes +- `type` defines your image version (for example, `php:8.4`) +- You can move to a composable image later, if your application needs change + +The composable image type has the following characteristics: +- Can contain multiple runtimes +- Requires less manual configuration than single-runtime images and offers more flexibility in other ways +- Initial build and rebuilds and can take a long time, but caching increases the speed +- `type` defines your Nix channel +- Can be used for applications only, not services + + + + ## Single-runtime image {{% vendor/name %}} provides and maintains a list of single-runtime images you can use for each of your application containers.
@@ -15,10 +51,15 @@ See [all of the options you can use](/create-apps/app-reference/single-runtime-i ## Composable image (BETA) -The {{% vendor/name %}} composable image provides more flexibility than single-runtime images. -When using a composable image, you can define a stack (or group of packages) for your application container to use. +The {{% vendor/name %}} composable image provides more flexibility than single-runtime images. This image type enables you to define or "compose" the stack (or group of packages) to include in the container that runs your application. + +Composable images can be used for applications only, not for services. This image type enables you to install multiple runtimes (such as PHP, Ruby, and so on) as well aXXX in your application container. + + -There are over 80,000 packages available from the [Nix Packages collection](https://search.nixos.org/) that you can add to your stack. +There are over 120,000 packages available from the [Nix Packages collection](https://search.nixos.org/) that you can add to your stack. You can add as many packages to your application container as you need. {{% note %}} diff --git a/sites/platform/src/create-apps/app-reference/composable-image.md b/sites/platform/src/create-apps/app-reference/composable-image.md index 89b956294b..2a81ba6c94 100644 --- a/sites/platform/src/create-apps/app-reference/composable-image.md +++ b/sites/platform/src/create-apps/app-reference/composable-image.md @@ -1,6 +1,6 @@ --- title: "Composable image" -weight: 5 +weight: 3 description: Use {{% vendor/name %}}'s composable image to build and deploy your app. keywords: - sleepy crons @@ -32,31 +32,33 @@ If you're pressed for time, jump to this comprehensive [configuration example](/ ## Top-level properties -The following table presents all the properties you can use at the top level of your app's YAML configuration file. +The following table lists all the properties you can use at the top level of your app's YAML configuration file. The column _Set in instance?_ defines whether the given property can be overridden within a `web` or `workers` instance. To override any part of a property, you have to provide the entire property. +- **Note:** Except for the `stack` key, the keys listed below are available in **both** the single-runtime and composable image types. Clicking the link for their details leads you to a separate topic for that property. Descriptions for keys that are **unique** to this image type are provided later in this topic. + | Name | Type | Required | Set in instance? | Description | |--------------------|--------------------------------------------------------------------------|----------|------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `name` | `string` | Yes | No | A unique name for the app. Must be lowercase alphanumeric characters. Changing the name destroys data associated with the app. | -| `type` | A type | Yes | No | [Defines the version of the Nix channel](#supported-nix-channels). Example: `type: "composable:25.05"` | -| `stack` | An array of [Nix packages](#stack) | Yes | No | A list of packages from the {{% vendor/name %}} collection of [supported runtimes](#supported-nix-packages) and/or from [Nixpkgs](https://search.nixos.org/packages). | -| `size` | A [size](#sizes) | | Yes | How much resources to devote to the app. Defaults to `AUTO` in production environments. | -| `relationships` | A dictionary of [relationships](#relationships) | | Yes | Connections to other services and apps. | -| `disk` | `integer` or `null` | | Yes | The size of the disk space for the app in [MB](/glossary/_index.md#mb). Minimum value is `128`. Defaults to `null`, meaning no disk is available. See [note on available space](#available-disk-space). | -| `mounts` | A dictionary of [mounts](#mounts) | | Yes | Directories that are writable even after the app is built. If set as a local source, `disk` is required. | -| `web` | A [web instance](#web) | | N/A | How the web application is served. | -| `workers` | A [worker instance](#workers) | | N/A | Alternate copies of the application to run as background processes. | +| `type` | A type | Yes | No | [Defines the version of the Nix channel](#supported-nix-channels). Example: `type: "composable:25.05"`. If not present, defaults to last stable version. | +| [`stack`](#stack) | An array of Nix packages | Yes | No | A list of packages from the {{% vendor/name %}} collection of [supported runtimes](#supported-nix-packages) and/or from [Nixpkgs](https://search.nixos.org/packages). | +| [`size`](/create-apps/image-properties/size.md) | A size | | Yes | How much resources to devote to the app. Defaults to `AUTO` in production environments. | +| [`relationships`](/create-apps/image-properties/relationships.md) | A dictionary of relationships | | Yes | Connections to other services and apps. | +| [`disk`](/create-apps/image-properties/disk.md) | `integer` or `null` | | Yes | The size of the disk space for the app in [MB](/glossary/_index.md#mb). Minimum value is `128`. Defaults to `null`, meaning no disk is available. | +| [`mounts`](/create-apps/image-properties/mounts.md) | A dictionary of mounts | | Yes | Directories that are writable even after the app is built. If set as a local source, `disk` is required. | +| [`web`](/create-apps/image-properties/web.md) | A web instance | | N/A | How the web application is served. | +| [`workers`](/create-apps/image-properties/workers.md) | A worker instance | | N/A | Alternate copies of the application to run as background processes. | | `timezone` | `string` | | No | The timezone for crons to run. Format: a [TZ database name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Defaults to `UTC`, which is the timezone used for all logs no matter the value here. See also [app runtime timezones](/create-apps/timezone.md). | -| `access` | An [access dictionary](#access) | | Yes | Access control for roles accessing app environments. | -| `variables` | A [variables dictionary](#variables) | | Yes | Variables to control the environment. | -| `firewall` | A [firewall dictionary](#firewall) | | Yes | Outbound firewall rules for the application. | -| `hooks` | A [hooks dictionary](#hooks) | | No | What commands run at different stages in the build and deploy process. | -| `crons` | A [cron dictionary](#crons) | | No | Scheduled tasks for the app. | -| `source` | A [source dictionary](#source) | | No | Information on the app's source code and operations that can be run on it. | -| `additional_hosts` | An [additional hosts dictionary](#additional-hosts) | | Yes | Maps of hostnames to IP addresses. | -| `operations` | A [dictionary of Runtime operations](/create-apps/runtime-operations.md) | | No | Runtime operations for the application. | +| [`access`](/create-apps/image-properties/access.md) | An access dictionary | | Yes | Access control for roles accessing app environments. | +| [`variables`](/create-apps/image-properties/variables.md) | A variables dictionary | | Yes | Variables to control the environment. | +| [`firewall`](/create-apps/image-properties/firewall.md) | A firewall dictionary | | Yes | Outbound firewall rules for the application. | +| [`hooks`](/create-apps/image-properties/hooks.md) | A hooks dictionary | | No | What commands run at different stages in the build and deploy process. | +| [`crons`](/create-apps/image-properties/crons.md) | A cron dictionary | | No | Scheduled tasks for the app. | +| [`source`](/create-apps/image-properties/source.md) | A source dictionary | | No | Information on the app's source code and operations that can be run on it. | +| [`additional_hosts`](/create-apps/image-properties/additional_hosts.md) | An additional hosts dictionary | | Yes | Maps of hostnames to IP addresses. | +| [`operations`](/create-apps/runtime-operations.md) | A dictionary of runtime operations | | No | Runtime operations for the application. | {{% note %}} The ``build``, ``dependencies``, and ``runtime`` keys are only supported when using a [single-runtime image](/create-apps/app-reference/single-runtime-image.md). @@ -65,7 +67,7 @@ They are replaced by the `stack` key. {{% /note %}} -## Stack +## `stack` {#stack} Use the ``stack`` key to define which runtimes and binaries you want to install in your application container. Define them as a YAML array as follows: @@ -282,1123 +284,3 @@ and visit the documentation page dedicated to your language. If you use PHP, note that PHP-FPM is only started automatically if PHP is defined as the primary runtime. {{% /note %}} - -## Sizes - -Resources are distributed across all containers in an environment from the total available from your [plan size](/administration/pricing/_index.md). -So if you have more than just a single app, it doesn't get all of the resources available. -Each environment has its own resources and there are different [sizing rules for preview environments](#sizes-in-preview-environments). - -By default, resource sizes (CPU and memory) are chosen automatically for an app -based on the plan size and the number of other containers in the cluster. -Most of the time, this automatic sizing is enough. - -You can set sizing suggestions for production environments when you know a given container has specific needs. -Such as a worker that doesn't need much and can free up resources for other apps. -To do so, set `size` to one of the following values: - -- `S` -- `M` -- `L` -- `XL` -- `2XL` -- `4XL` - -The total resources allocated across all apps and services can't exceed what's in your plan. - -### Container profiles: CPU and memory - -By default, {{% vendor/name %}} allocates a container profile to each app and service depending on: - -- The range of resources it’s expected to need -- Your [plan size](/administration/pricing/_index.md), as resources are distributed across containers. - Ideally you want to give databases the biggest part of your memory, and apps the biggest part of your CPU. - -The container profile and the [size of the container](#sizes) determine -how much CPU and memory (in [MB](/glossary/_index.md#mb)) the container gets. - -There are three container profiles available: ``HIGH_CPU``, ``BALANCED``, and ``HIGH_MEMORY``. - -#### ``HIGH_CPU`` container profile - -| Size | CPU | MEMORY | -| ---- | ----- | -------- | -| S | 0.40 | 128 MB | -| M | 0.40 | 128 MB | -| L | 1.20 | 256 MB | -| XL | 2.50 | 384 MB | -| 2XL | 5.00 | 768 MB | -| 4XL | 10.00 | 1536 MB | - -#### `BALANCED` container profile - -| Size | CPU | MEMORY | -| ---- | ---- | -------- | -| S | 0.05 | 32 MB | -| M | 0.05 | 64 MB | -| L | 0.08 | 256 MB | -| XL | 0.10 | 512 MB | -| 2XL | 0.20 | 1024 MB | -| 4XL | 0.40 | 2048 MB | - -#### `HIGH_MEMORY` container profile - -| Size | CPU | MEMORY | -| ---- | ---- | --------- | -| S | 0.25 | 128 MB | -| M | 0.25 | 288 MB | -| L | 0.40 | 1280 MB | -| XL | 0.75 | 2624 MB | -| 2XL | 1.50 | 5248 MB | -| 4XL | 3.00 | 10496 MB | - -#### Container profile reference - -The following table shows which container profiles {{% vendor/name %}} applies when deploying your project. - -| Container | Profile | -|-------------------------|---------------| -| Chrome Headless | HIGH_CPU | -| .NET | HIGH_CPU | -| Elasticsearch | HIGH_MEMORY | -| Elasticsearch Premium | HIGH_MEMORY | -| Elixir | HIGH_CPU | -| Go | HIGH_CPU | -| Gotenberg | HIGH_MEMORY | -| InfluxDB | HIGH_MEMORY | -| Java | HIGH_MEMORY | -| Kafka | HIGH_MEMORY | -| Lisp | HIGH_CPU | -| MariaDB | HIGH_MEMORY | -| Memcached | BALANCED | -| MongoDB | HIGH_MEMORY | -| MongoDB Premium | HIGH_MEMORY | -| Network Storage | HIGH_MEMORY | -| Node.js | HIGH_CPU | -| OpenSearch | HIGH_MEMORY | -| Oracle MySQL | HIGH_MEMORY | -| PHP | HIGH_CPU | -| PostgreSQL | HIGH_MEMORY | -| Python | HIGH_CPU | -| RabbitMQ | HIGH_MEMORY | -| Redis ephemeral | BALANCED | -| Redis persistent | BALANCED | -| Ruby | HIGH_CPU | -| Rust | HIGH_CPU | -| Solr | HIGH_MEMORY | -| Varnish | HIGH_MEMORY | -| Vault KMS | HIGH_MEMORY | - -### Sizes in preview environments - -Containers in preview environments don't follow the `size` specification. -Application containers are set based on the plan's setting for **Environments application size**. -The default is size **S**, but you can increase it by editing your plan. -(Service containers in preview environments are always set to size **S**.) - -## Relationships - -To allow containers in your project to communicate with one another, -you need to define relationships between them. -You can define a relationship between an app and a service, or [between two apps](/create-apps/multi-app/relationships.md). - -The quickest way to define a relationship between your app and a service -is to use the service's default endpoint.
-However, some services allow you to define multiple databases, cores, and/or permissions. -In these cases, you can't rely on default endpoints. -Instead, you can explicitly define multiple endpoints when setting up your relationships. - -{{< note >}} -App containers don't have a default endpoint like services. -To connect your app to another app in your project, -you need to explicitly define the `http` endpoint as the endpoint to connect both apps.
-For more information, see how to [define relationships between your apps](/create-apps/multi-app/relationships.md). -{{< /note >}} - -{{< note title="Availability" theme="info">}} - -New syntax (default and explicit endpoints) described below is supported by most, but not all, image types -(`Relationship 'SERVICE_NAME' of application 'myapp' ... targets a service without a valid default endpoint configuration.`). -This syntax is currently being rolled out for all images. -If you encounter this error, use the "legacy" {{% vendor/name %}} configuration noted at the bottom of this section. - -{{< /note >}} - -To define a relationship between your app and a service: - -{{< codetabs >}} - -+++ -title=Using default endpoints -+++ - -Use the following configuration: - -```yaml {configFile="app"} -relationships: - {{% variable "SERVICE_NAME" %}}: -``` - -The `SERVICE_NAME` is the name of the service as defined in its [configuration](/add-services/_index.md). -It is used as the relationship name, and associated with a `null` value. -This instructs {{% vendor/name %}} to use the service's default endpoint to connect your app to the service. - -For example, if you define the following configuration: - -```yaml {configFile="app"} -relationships: - mariadb: -``` - -{{% vendor/name %}} looks for a service named `mariadb` in your `{{% vendor/configfile "services" %}}` file, -and connects your app to it through the service's default endpoint. - -For reference, the equivalent configuration using explicit endpoints would be the following: - -```yaml {configFile="app"} -relationships: - mariadb: - service: mariadb - endpoint: mysql -``` - -You can define any number of relationships in this way: - -```yaml {configFile="app"} -relationships: - mariadb: - redis: - elasticsearch: -``` - -{{< note title="Tip" theme="info" >}} - -An even quicker way to define many relationships is to use the following single-line configuration: - -```yaml {configFile="app"} -relationships: {{{< variable "SERVICE_NAME_A" >}}, {{< variable "SERVICE_NAME_B" >}}, {{< variable "SERVICE_NAME_C" >}}} -``` - -where - -```yaml {configFile="services"} -{{< variable "SERVICE_NAME_A" >}}: - type: mariadb:{{% latest "mariadb" %}} - disk: 256 -{{< variable "SERVICE_NAME_B" >}}: - type: redis:{{% latest "redis" %}} - disk: 256 -{{< variable "SERVICE_NAME_C" >}}: - type: elasticsearch:{{% latest "elasticsearch" %}} - disk: 256 -``` - -{{< /note >}} - -<---> - -+++ -title=Using explicit endpoints -+++ - -Use the following configuration: - -```yaml {configFile="app"} -relationships: - {{% variable "RELATIONSHIP_NAME" %}}: - service: {{% variable "SERVICE_NAME" %}} - endpoint: {{% variable "ENDPOINT_NAME" %}} -``` - -- `RELATIONSHIP_NAME` is the name you want to give to the relationship. -- `SERVICE_NAME` is the name of the service as defined in its [configuration](/add-services/_index.md). -- `ENDPOINT_NAME` is the endpoint your app will use to connect to the service (refer to the service reference to know which value to use). - -For example, to define a relationship named `database` that connects your app to a service called `mariadb` through the `db1` endpoint, -use the following configuration: - -```yaml {configFile="app"} -relationships: - database: # The name of the relationship. - service: mariadb - endpoint: db1 -``` - -For more information on how to handle multiple databases, multiple cores, -and/or different permissions with services that support such features, -see each service's dedicated page: - - - [MariaDB/MySQL](/add-services/mysql/_index.md#multiple-databases) (multiple databases and permissions) - - [PostgreSQL](/add-services/postgresql/_index.md#multiple-databases) (multiple databases and permissions) - - [Redis](/add-services/redis/_index.md#multiple-databases) (multiple databases) - - [Solr](add-services/solr/_index.md#solr-6-and-later) (multiple cores) - - [Vault KMS](add-services/vault.md#multiple-endpoints-configuration) (multiple permissions) - - You can add as many relationships as you want to your app configuration, - using both default and explicit endpoints according to your needs: - -```yaml {configFile="app"} -relationships: - database1: - service: mariadb - endpoint: admin - database2: - service: mariadb - endpoint: legacy - cache: - service: redis - search: - service: elasticsearch -``` - -{{< /codetabs >}} - -{{< note theme="info" title="Legacy" >}} - -The following legacy syntax for specifying relationships is still supported by {{% vendor/name %}}: - -```yaml {configFile="app"} -relationships: - : ":" -``` - -For example: - -```yaml {configFile="app"} -relationships: - database: "mariadb:mysql" -``` - -Feel free to use this until the default and explicit endpoint syntax is supported on all images. - -{{< /note >}} - -## Available disk space - -The maximum total space available to all apps and services is set by the storage in your plan settings. -When deploying your project, the sum of all `disk` keys defined in app and service configurations -must be *equal or less* than the plan storage size. - -So if your *plan storage size* is 5 GB, you can, for example, assign it in one of the following ways: - -- 2 GB to your app, 3 GB to your database -- 1 GB to your app, 4 GB to your database -- 1 GB to your app, 1 GB to your database, 3 GB to your OpenSearch service - -If you exceed the total space available, you receive an error on pushing your code. -You need to either increase your plan's storage or decrease the `disk` values you've assigned. - -You configure the disk size in [MB](/glossary/_index.md#mb). Your actual available disk space is slightly smaller with some space used for formatting and the filesystem journal. When checking available space, note whether it’s reported in MB or MiB. - -### Downsize a disk - -You can decrease the size of an existing disk for an app. If you do so, be aware that: - -- The downsize fails if there's more data on the disk than the desired size. -- Backups from before the downsize can still be restored. - -## Mounts - -After your app is built, its file system is read-only. -To make changes to your app's code, you need to use Git. - -For enhanced flexibility, {{% vendor/name %}} allows you to define and use writable directories called "mounts". -Mounts give you write access to files generated by your app (such as cache and log files) -and uploaded files without going through Git. - -When you define a mount, you are mounting an external directory to your app container, -much like you would plug a hard drive into your computer to transfer data. - -{{% note %}} - -- Mounts aren't available during the build -- When you [back up an environment](/environments/backup.md), the mounts on that environment are backed up too - -{{% /note %}} - -### Define a mount - -To define a mount, use the following configuration: - -```yaml {configFile="app"} -mounts: - '{{< variable "MOUNT_PATH" >}}': - source: {{< variable "MOUNT_TYPE" >}} - source_path: {{< variable "SOURCE_PATH_LOCATION" >}} -``` - -{{< variable "MOUNT_PATH" >}} is the path to your mount **within the app container** (relative to the app's root). -If you already have a directory with that name, you get a warning that it isn't accessible after the build. -See how to [troubleshoot the warning](/create-apps/troubleshoot-mounts.md#overlapping-folders). - -| Name | Type | Required | Description | -| ------------- |-------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `source` | `local`, `service`, or `tmp` | Yes | Specifies the type of the mount:

- `local` mounts are unique to your app. They can be useful to store files that remain local to the app instance, such as application logs.
`local` mounts require disk space. To successfully set up a local mount, set the `disk` key in your app configuration.

- `service` mounts point to [Network Storage](/add-services/network-storage.md) services that can be shared between several apps.

- `tmp` mounts are local ephemeral mounts, where an external directory is mounted to the `/tmp` directory of your app.
The content of a `tmp` mount **may be removed during infrastructure maintenance operations**. Therefore, `tmp` mounts allow you to **store files that you’re not afraid to lose**, such as your application cache that can be seamlessly rebuilt.
Note that the `/tmp` directory has **a maximum allocation of 8 GB**. | -| `source_path` | `string` | No | Specifies where the mount points **inside the [external directory](#mounts)**.

- If you explicitly set a `source_path`, your mount points to a specific subdirectory in the external directory.

- If the `source_path` is an empty string (`""`), your mount points to the entire external directory.

- If you don't define a `source_path`, {{% vendor/name %}} uses the {{< variable "MOUNT_PATH" >}} as default value, without leading or trailing slashes.
For example, if your mount lives in the `/web/uploads/` directory in your app container, it will point to a directory named `web/uploads` in the external directory.

**WARNING:** Changing the name of your mount affects the `source_path` when it's undefined. See [how to ensure continuity](#ensure-continuity-when-changing-the-name-of-your-mount) and maintain access to your files. | -| `service` | `string` | | Only for `service` mounts: the name of the [Network Storage service](/add-services/network-storage.md). | - - -The accessibility to the web of a mounted directory depends on the [`web.locations` configuration](#web). -Files can be all public, all private, or with different rules for different paths and file types. - -Note that when you remove a `local` mount from your `{{< vendor/configfile "app" >}}` file, -the mounted directory isn't deleted. -The files still exist on disk until manually removed -(or until the app container is moved to another host during a maintenance operation in the case of a `tmp` mount). - -### Example configuration - -```yaml {configFile="app"} -mounts: - 'web/uploads': - source: local - source_path: uploads - '/.tmp_platformsh': - source: tmp - source_path: files/.tmp_platformsh - '/build': - source: local - source_path: files/build - '/.cache': - source: tmp - source_path: files/.cache - '/node_modules/.cache': - source: tmp - source_path: files/node_modules/.cache -``` - -For examples of how to set up a `service` mount, see the dedicated [Network Storage page](/add-services/network-storage.md). - -### Ensure continuity when changing the name of your mount - -Changing the name of your mount affects the default `source_path`. - -Say you have a `/my/cache/` mount with an undefined `source_path`: - -```yaml {configFile="app"} -mounts: - '/my/cache/': - source: tmp -``` - -If you rename the mount to `/cache/files/`, it will point to a new, empty `/cache/files/` directory. - -To ensure continuity, you need to explicitly define the `source_path` as the previous name of the mount, without leading or trailing slashes: - - ```yaml {configFile="app"} -mounts: - '/cache/files/': - source: tmp - source_path: my/cache -``` - -The `/cache/files/` mount will point to the original `/my/cache/` directory, maintaining access to all your existing files in that directory. - -### Overlapping mounts - -The locations of mounts as they are visible to application containers can overlap somewhat. -For example: - -```yaml {configFile="apps"} -applications: - myapp: - # ... - mounts: - 'var/cache_a': - source: service - service: ns_service - source_path: cacheA - 'var/cache_b': - source: tmp - source_path: cacheB - 'var/cache_c': - source: local - source_path: cacheC -``` - -In this case, it does not matter that each mount is of a different `source` type. -Each mount is restricted to a subfolder within `var`, and all is well. - -The following, however, is not allowed and will result in a failure: - -```yaml {configFile="apps"} -applications: - myapp: - # ... - mounts: - 'var/': - source: service - service: ns_service - source_path: cacheA - 'var/cache_b': - source: tmp - source_path: cacheB - 'var/cache_c': - source: local - source_path: cacheC -``` - -The `service` mount type specifically exists to share data between instances of the same application, whereas `tmp` and `instance` are meant to restrict data to build time and runtime of a single application instance, respectively. -These allowances are not compatible, and will result in an error if pushed. - -## Web - -Use the `web` key to configure the web server running in front of your app. - -| Name | Type | Required | Description | -|-------------|--------------------------------------------|-------------------------------|------------------------------------------------------| -| `commands` | A [web commands dictionary](#web-commands) | See [note](#required-command) | The command to launch your app. | -| `upstream` | An [upstream dictionary](#upstream) | | How the front server connects to your app. | -| `locations` | A [locations dictionary](#locations) | | How the app container responds to incoming requests. | - -See some [examples of how to configure what's served](/create-apps/web/_index.md). - -### Web commands - -| Name | Type | Required | Description | -|--------------|----------|-------------------------------|------------------------------------------------------------------------------------------------------| -| `pre_start` | `string` | | Command runs just prior to `start`, which can be useful when you need to run _per-instance_ actions. | -| `start` | `string` | See [note](#required-command) | The command to launch your app. If it terminates, it's restarted immediately. | -| `post_start` | `string` | | Command runs **before** adding the container to the router and **after** the `start` command. | - -{{< note theme="info" >}} -The `post_start` feature is _experimental_ and may change. Please share your feedback in the -[{{% vendor/name %}} discord](https://discord.gg/platformsh). -{{< /note >}} - - -Example: - -```yaml {configFile="app"} -web: - commands: - start: 'uwsgi --ini conf/server.ini' -``` - -This command runs every time your app is restarted, regardless of whether or not new code is deployed. - -{{< note >}} - -Never "background" a start process using `&`. -That's interpreted as the command terminating and the supervisor process starts a second copy, -creating an infinite loop until the container crashes. -Just run it as normal and allow the {{% vendor/name %}} supervisor to manage it. - -{{< /note >}} - -#### Required command - -On all containers other than PHP, the value for `start` should be treated as required. - -On PHP containers, it's optional and defaults to starting PHP-FPM (`/usr/bin/start-php-app`). -It can also be set explicitly on a PHP container to run a dedicated process, -such as [React PHP](https://github.com/platformsh-examples/platformsh-example-reactphp) -or [Amp](https://github.com/platformsh-examples/platformsh-example-amphp). -See how to set up [alternate start commands on PHP](/languages/php/_index.md#alternate-start-commands). - -### Upstream - -| Name | Type | Required | Description | Default | -|-----------------|---------------------|----------|-------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------| -| `socket_family` | `tcp` or `unix` | | Whether your app listens on a Unix or TCP socket. | Defaults to `tcp` for all [primary runtimes](#primary-runtime) except PHP; for PHP the default is `unix`. | -| `protocol` | `http` or `fastcgi` | | Whether your app receives incoming requests over HTTP or FastCGI. | Default varies based on the [primary runtimes](#primary-runtime). | - -For PHP, the defaults are configured for PHP-FPM and shouldn't need adjustment. -For all other containers, the default for `protocol` is `http`. - -The following example is the default on non-PHP containers: - -```yaml {configFile="app"} -web: - upstream: - socket_family: tcp - protocol: http -``` - -#### Where to listen - -Where to listen depends on your setting for `web.upstream.socket_family` (defaults to `tcp`). - -| `socket_family` | Where to listen | -|-----------------|---------------------------------------------------------------------------------------------------------------------------------------| -| `tcp` | The port specified by the [`PORT` environment variable](/development/variables/use-variables.md#use-provided-variables) | -| `unix` | The Unix socket file specified by the [`SOCKET` environment variable](/development/variables/use-variables.md#use-provided-variables) | - -If your application isn't listening at the same place that the runtime is sending requests, -you see `502 Bad Gateway` errors when you try to connect to your website. - -### Locations - -Each key in the `locations` dictionary is a path on your site with a leading `/`. -For `example.com`, a `/` matches `example.com/` and `/admin` matches `example.com/admin`. -When multiple keys match an incoming request, the most-specific applies. - -The following table presents possible properties for each location: - -| Name | Type | Default | Description | -|---------------------|------------------------------------------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `root` | `string` | | The directory to serve static assets for this location relative to the app's root directory ([see `source.root`](#source)). Must be an actual directory inside the root directory. | -| `passthru` | `boolean` or `string` | `false` | Whether to forward disallowed and missing resources from this location to the app. A string is a path with a leading `/` to the controller, such as `/index.php`.

If your app is in PHP, when setting `passthru` to `true`, you might want to set `scripts` to `false` for enhanced security. This prevents PHP scripts from being executed from the specified location. You might also want to set `allow` to `false` so that not only PHP scripts can't be executed, but their source code also can't be delivered. | -| `index` | Array of `string`s or `null` | | Files to consider when serving a request for a directory. When set, requires access to the files through the `allow` or `rules` keys. | -| `expires` | `string` | `-1` | How long static assets are cached. The default means no caching. Setting it to a value enables the `Cache-Control` and `Expires` headers. Times can be suffixed with `ms` = milliseconds, `s` = seconds, `m` = minutes, `h` = hours, `d` = days, `w` = weeks, `M` = months/30d, or `y` = years/365d. | -| `allow` | `boolean` | `true` | Whether to allow serving files which don't match a rule. | -| `scripts` | `boolean` | | Whether to allow scripts to run. Doesn't apply to paths specified in `passthru`. Meaningful only on PHP containers. | -| `headers` | A headers dictionary | | Any additional headers to apply to static assets, mapping header names to values (see [Set custom headers on static content](/create-apps/web/custom-headers.html)). Responses from the app aren't affected. | -| `request_buffering` | A [request buffering dictionary](#request-buffering) | See below | Handling for chunked requests. | -| `rules` | A [rules dictionary](#rules) | | Specific overrides for specific locations. | - -#### Rules - -The rules dictionary can override most other keys according to a regular expression. -The key of each item is a regular expression to match paths exactly. -If an incoming request matches the rule, it's handled by the properties under the rule, -overriding any conflicting rules from the rest of the `locations` dictionary. - -Under `rules`, you can set all the other possible [`locations` properties](#locations) -except `root`, `index`, `rules` and `request_buffering`. - -In the following example, the `allow` key disallows requests for static files anywhere in the site. -This is overridden by a rule that explicitly allows common image file formats. - -```yaml {configFile="app"} -web: - locations: - '/': - # Handle dynamic requests - root: 'public' - passthru: '/index.php' - # Disallow static files - allow: false - rules: - # Allow common image files only. - '\.(jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff2?|otf|ttf)$': - allow: true -``` - -#### Request buffering - -Request buffering is enabled by default to handle chunked requests as most app servers don't support them. -The following table shows the keys in the `request_buffering` dictionary: - -| Name | Type | Required | Default | Description | -|--------------------|-----------|----------|---------|-------------------------------------------| -| `enabled` | `boolean` | Yes | `true` | Whether request buffering is enabled. | -| `max_request_size` | `string` | | `250m` | The maximum size to allow in one request. | - -The default configuration would look like this: - -```yaml {configFile="app"} -web: - locations: - '/': - passthru: true - request_buffering: - enabled: true - max_request_size: 250m -``` - -## Workers - -Workers are exact copies of the code and compilation output as a `web` instance after a [`build` hook](#hooks). -They use the same container image. - -Workers can't accept public requests and so are suitable only for background tasks. -If they exit, they're automatically restarted. - -The keys of the `workers` definition are the names of the workers. -You can then define how each worker differs from the `web` instance using -the [top-level properties](#top-level-properties). - -Each worker can differ from the `web` instance in all properties _except_ for: - -- `crons` as cron jobs don't run on workers -- `hooks` as the `build` hook must be the same - and the `deploy` and `post_deploy` hooks don't run on workers. - -A worker named `queue` that was small and had a different start command could look like this: - -```yaml {configFile="app"} -workers: - queue: - size: S - commands: - start: | - ./worker.sh -``` - -For resource allocation, using workers in your project requires a [{{< partial "plans/multiapp-plan-name" >}} plan or larger](https://platform.sh/pricing/). - -## Access - -The `access` dictionary has one allowed key: - -| Name | Allowed values | Default | Description | -|-------|-------------------------------------|---------------|-----------------------------------------------------------------------| -| `ssh` | `admin`, `contributor`, or `viewer` | `contributor` | Defines the minimum role required to access app environments via SSH. | - -In the following example, only users with `admin` permissions for the -given [environment type](/administration/users.md#environment-type-roles) -can access the deployed environment via SSH: - -```yaml {configFile="app"} -access: - ssh: admin -``` - -## Variables - -{{% vendor/name %}} provides a number of ways to set [variables](/development/variables/_index.md). -Variables set in your app configuration have the lowest precedence, -meaning they're overridden by any conflicting values provided elsewhere. - -All variables set in your app configuration must have a prefix. -Some [prefixes have specific meanings](/development/variables/_index.md#variable-prefixes). - -Variables with the prefix `env` are available as a separate environment variable. -All other variables are available in -the [`PLATFORM_VARIABLES` environment variable](/development/variables/use-variables.md#use-provided-variables). - -The following example sets two variables: - -- A variable named `env:AUTHOR` with the value `Juan` that's available in the environment as `AUTHOR` -- A variable named `d8config:system.site:name` with the value `My site rocks` - that's available in the `PLATFORM_VARIABLES` environment variable - -```yaml {configFile="app"} -variables: - env: - AUTHOR: 'Juan' - d8config: - "system.site:name": 'My site rocks' -``` - -You can also define and access more [complex values](/development/variables/use-variables.md#access-complex-values). - -## Firewall - -{{< premium-features/tiered "Elite and Enterprise" >}} - -Set limits in outbound traffic from your app with no impact on inbound requests. - -The `outbound` key is required and contains one or more rules. -The rules define what traffic is allowed; anything unspecified is blocked. - -Each rule has the following properties where at least one is required and `ips` and `domains` can't be specified -together: - -| Name | Type | Default | Description | -|-----------|---------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `ips` | Array of `string`s | `["0.0.0.0/0"]` | IP addresses in [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing). See a [CIDR format converter](https://www.ipaddressguide.com/cidr). | -| `domains` | Array of `string`s | | [Fully qualified domain names](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) to specify specific destinations by hostname. | -| `ports` | Array of `integer`s | | Ports from 1 to 65535 that are allowed. If any ports are specified, all unspecified ports are blocked. If no ports are specified, all ports are allowed. Port `25`, the SMTP port for sending email, is always blocked. | - -The default settings would look like this: - -```yaml {configFile="app"} -firewall: - outbound: - - ips: [ "0.0.0.0/0" ] -``` - -### Support for rules - -Where outbound rules for firewalls are supported in all environments. -For {{% names/dedicated-gen-2 %}} projects, contact support for configuration. - -### Multiple rules - -Multiple firewall rules can be specified. -In such cases, a given outbound request is allowed if it matches _any_ of the defined rules. - -So in the following example requests to any IP on port 80 are allowed -and requests to 1.2.3.4 on either port 80 or 443 are allowed: - -```yaml {configFile="app"} -firewall: - outbound: - - ips: [ "1.2.3.4/32" ] - ports: [ 443 ] - - ports: [ 80 ] -``` - -### Outbound traffic to CDNs - -Be aware that many services are behind a content delivery network (CDN). -For most CDNs, routing is done via domain name, not IP address, -so thousands of domain names may share the same public IP addresses at the CDN. -If you allow the IP address of a CDN, you are usually allowing many or all of the other customers hosted behind that -CDN. - -### Outbound traffic by domain - -You can filter outbound traffic by domain. -Using domains in your rules rather than IP addresses is generally more specific and secure. -For example, if you use an IP address for a service with a CDN, -you have to allow the IP address for the CDN. -This means that you allow potentially hundreds or thousands of other servers also using the CDN. - -An example rule filtering by domain: - -```yaml {configFile="app"} -firewall: - outbound: - - protocol: tcp - domains: ["api.stripe.com", "api.twilio.com"] - ports: [80, 443] - - protocol: tcp - ips: ["1.2.3.4/29","2.3.4.5"] - ports: [22] -``` - -#### Determine which domains to allow - -To determine which domains to include in your filtering rules, -find the domains your site has requested the DNS to resolve. -Run the following command to parse your server’s `dns.log` file -and display all Fully Qualified Domain Names that have been requested: - -```bash -awk '/query\[[^P]\]/ { print $6 | "sort -u" }' /var/log/dns.log -``` - -The output includes all DNS requests that were made, including those blocked by your filtering rules. -It doesn't include any requests made using an IP address. - -Example output: - -```bash -facebook.com -fastly.com -platform.sh -www.google.com -www.platform.sh -``` - -## Hooks - -There are three different hooks that run as part of the process of building and deploying your app. -These are places where you can run custom scripts. -They are: the `build` hook, the `deploy` hook, and the `post_deploy` hook. -Only the `build` hook is run for [worker instances](#workers), while [web instances](#web) run all three. - -The process is ordered as: - -1. Variables accessible at build time become available. -1. The `build` hook is run. -1. The file system is changed to read only (except for any [mounts](#mounts)). -1. The app container starts. Variables accessible at runtime and services become available. -1. The `deploy` hook is run. -1. The app container begins accepting requests. -1. The `post_deploy` hook is run. - -Note that if an environment changes by no code changes, only the last step is run. -If you want the entire process to run, see how to [manually trigger builds](/development/troubleshoot.md#manually-trigger-builds). - -### Writable directories during build - -During the `build` hook, there are three writeable directories: - -- `PLATFORM_APP_DIR`: - Where your code is checked out and the working directory when the `build` hook starts. - Becomes the app that gets deployed. -- `PLATFORM_CACHE_DIR`: - Persists between builds, but isn't deployed. - Shared by all builds on all branches. -- `/tmp`: - Isn't deployed and is wiped between each build. - Note that `PLATFORM_CACHE_DIR` is mapped to `/tmp` - and together they offer about 8GB of free space. - -### Hook failure - -Each hook is executed as a single script, so they're considered to have failed only if the final command in them fails. -To cause them to fail on the first failed command, add `set -e` to the beginning of the hook. - -If a `build` hook fails for any reason, the build is aborted and the deploy doesn't happen. -Note that this only works for `build` hooks -- -if other hooks fail, the app is still deployed. - -#### Automated testing - -It’s preferable that you set up and run automated tests in a dedicated CI/CD tool. -Relying on {{% vendor/name %}} hooks for such tasks can prove difficult. - -During the `build` hook, you can halt the deployment on a test failure but the following limitations apply: - -- Access to services such as databases, Redis, Vault KMS, and even writable mounts is disabled. - So any testing that relies on it is sure to fail. -- If you haven’t made changes to your app, an existing build image is reused and the build hook isn’t run. -- Test results are written into your app container, so they might get exposed to a third party. - -During the `deploy` hook, you can access services but **you can’t halt the deployment based on a test failure**. -Note that there are other downsides: - -- Your app container is read-only during the deploy hook, - so if your tests need to write reports and other information, you need to create a file mount for them. -- Your app can only be deployed once the deploy hook has been completed. - Therefore, running automated testing via the deploy hook generates slower deployments. -- Your environment isn’t available externally during the deploy hook. - Unit and integration testing might work without the environment being available, - but you can’t typically perform end-to-end testing until after the environment is up and available. - -## Crons - -The keys of the `crons` definition are the names of the cron jobs. -The names must be unique. - -If an application defines both a `web` instance and `worker` instances, cron jobs run only on the `web` instance. - -See how to [get cron logs](/increase-observability/logs/access-logs.md#container-logs). - -The following table shows the properties for each job: - -| Name | Type | Required | Description | -|--------------------|----------------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `spec` | `string` | Yes | The [cron specification](https://en.wikipedia.org/wiki/Cron#Cron_expression). To prevent competition for resources that might hurt performance, use `H` in definitions to indicate an unspecified but invariant time. For example, instead of using `0 * * * *` to indicate the cron job runs at the start of every hour, you can use `H * * * *` to indicate it runs every hour, but not necessarily at the start. This prevents multiple cron jobs from trying to start at the same time. | -| `commands` | A [cron commands dictionary](#cron-commands) | Yes | A definition of what commands to run when starting and stopping the cron job. | -| `shutdown_timeout` | `integer` | No | When a cron is canceled, this represents the number of seconds after which a `SIGKILL` signal is sent to the process to force terminate it. The default is `10` seconds. | -| `timeout` | `integer` | No | The maximum amount of time a cron can run before it's terminated. Defaults to the maximum allowed value of `86400` seconds (24 hours). | - -Note that you can [cancel pending or running crons](/environments/cancel-activity.md). - -{{< note >}} - -The use of the `cmd` key is now deprecated in favor of the `commands`key.
-Make sure you set your new cron jobs using the `commands` key, -and update your existing cron jobs to ensure continuity. - -{{< /note >}} - -### Cron commands - -| Name | Type | Required | Description | -|---------|----------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `start` | `string` | Yes | The command that's run. It's run in [Dash](https://en.wikipedia.org/wiki/Almquist_shell). | -| `stop` | `string` | No | The command that's issued to give the cron command a chance to shutdown gracefully, such as to finish an active item in a list of tasks. Issued when a cron task is interrupted by a user through the CLI or Console. If not specified, a `SIGTERM` signal is sent to the process. | - -```yaml {configFile="app"} -crons: - mycommand: - spec: 'H * * * *' - commands: - start: sleep 60 && echo sleep-60-finished && date - stop: killall sleep - shutdown_timeout: 18 -``` - -In this example configuration, the [cron specification](#crons) uses the `H` syntax. - -Note that this syntax is only supported on Grid and {{% names/dedicated-gen-3 %}} projects. -On {{% names/dedicated-gen-2 %}} projects, use the [standard cron syntax](https://en.wikipedia.org/wiki/Cron#Cron_expression). - -### Example cron jobs - - -{{< codetabs >}} - -+++ -title=Drupal -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -stack: [ "php@{{% latest php %}}" ] -crons: - # Run Drupal's cron tasks every 19 minutes. - drupal: - spec: '*/19 * * * *' - commands: - start: 'cd web ; drush core-cron' - # But also run pending queue tasks every 7 minutes. - # Use an odd number to avoid running at the same time as the `drupal` cron. - drush-queue: - spec: '*/7 * * * *' - commands: - start: 'cd web ; drush queue-run aggregator_feeds' -{{< /snippet >}} -``` - -<---> - -+++ -title=Ruby on Rails -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -stack: [ "ruby@{{% latest ruby %}}" ] -crons: - # Execute a rake script every 19 minutes. - ruby: - spec: '*/19 * * * *' - commands: - start: 'bundle exec rake some:task' -{{< /snippet >}} -``` - -<---> - -+++ -title=Laravel -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -stack: [ "php@{{% latest php %}}" ] -crons: - # Run Laravel's scheduler every 5 minutes. - scheduler: - spec: '*/5 * * * *' - commands: - start: 'php artisan schedule:run' -{{< /snippet >}} -``` - -<---> - -+++ -title=Symfony -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -stack: [ "php@{{% latest php %}}" ] -crons: - # Take a backup of the environment every day at 5:00 AM. - snapshot: - spec: 0 5 * * * - commands: - start: | - # Only run for the production environment, aka main branch - if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then - croncape symfony ... - fi -{{< /snippet >}} -``` - -{{< /codetabs >}} - - -### Conditional crons - -If you want to set up customized cron schedules depending on the environment type, -define conditional crons. -To do so, use a configuration similar to the following: - -```yaml {configFile="app"} -crons: - update: - spec: '0 0 * * *' - commands: - start: | - if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then - {{% vendor/cli %}} backup:create --yes --no-wait - {{% vendor/cli %}} source-operation:run update --no-wait --yes - fi -``` - -### Cron job timing - -Minimum time between cron jobs being triggered: - -| Plan | Time | -|-------------------- | --------- | -| Professional | 5 minutes | -| Elite or Enterprise | 1 minute | - -For each app container, only one cron job can run at a time. -If a new job is triggered while another is running, the new job is paused until the other completes. - -To minimize conflicts, a random offset is applied to all triggers. -The offset is a random number of seconds up to 20 minutes or the cron frequency, whichever is smaller. - -Crons are also paused while activities such as [backups](/environments/backup.md) are running. -The crons are queued to run after the other activity finishes. - -To run cron jobs in a timezone other than UTC, set the [timezone property](#top-level-properties). - -### Paused crons - -[Preview environments](/glossary/_index.md#preview-environment) are often used for a limited time and then abandoned. -While it's useful for environments under active development to have scheduled tasks, -unused environments don't need to run cron jobs. -To minimize unnecessary resource use, -crons on environments with no deployments are paused. - -This affects all environments that aren't live environments. -This means all environments on Development plans -and all preview environments on higher plans. - -Such environments with deployments within 14 days have crons with the status `running`. -If there haven't been any deployments within 14 days, the status is `paused`. - -You can see the status in the Console -or using the CLI by running `{{% vendor/cli %}} environment:info` and looking under `deployment_state`. - -#### Restarting paused crons - -If the crons on your preview environment are paused but you're still using them, -you can push changes to the environment or redeploy it. - -To restart crons without changing anything: - -{{< codetabs >}} - -+++ -title=In the Console -+++ - -1. In the Console, navigate to your project. -1. Open the environment where you'd like the crons to run. -1. Click `Redeploy` next to the cron status of `Paused`. - -<---> - -+++ -title=Using the CLI -+++ - -Run the following command: - -```bash -{{% vendor/cli %}} redeploy -``` - -{{< /codetabs >}} - -### Sizing hints - -The following table shows the properties that can be set in `sizing_hints`: - -| Name | Type | Default | Minimum | Description | -|-------------------|-----------|---------|---------|------------------------------------------------| -| `request_memory` | `integer` | 45 | 10 | The average memory consumed per request in MB. | -| `reserved_memory` | `integer` | 70 | 70 | The amount of memory reserved in MB. | - -See more about [PHP-FPM workers and sizing](/languages/php/fpm.md). - -## Source - -The following table shows the properties that can be set in `source`: - -| Name | Type | Required | Description | -|--------------|--------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------| -| `operations` | An operations dictionary | | Operations that can be applied to the source code. See [source operations](/create-apps/source-operations.md) | -| `root` | `string` | | The path where the app code lives. Defaults to the root project directory. Useful for [multi-app setups](/create-apps/multi-app/_index.md). | - -## Additional hosts - -If you're using a private network with specific IP addresses you need to connect to, -you might want to map those addresses to hostnames to better remember and organize them. -In such cases, you can add a map of those IP addresses to whatever hostnames you like. -Then when your app tries to access the hostname, it's sent to the proper IP address. - -So in the following example, if your app tries to access `api.example.com`, it's sent to `192.0.2.23`. - -```yaml {configFile="app"} -additional_hosts: - api.example.com: "192.0.2.23" - web.example.com: "203.0.113.42" -``` - -This is equivalent to adding the mapping to the `/etc/hosts` file for the container. diff --git a/sites/platform/src/create-apps/app-reference/single-runtime-image.md b/sites/platform/src/create-apps/app-reference/single-runtime-image.md index c211bc6e10..920b6817ed 100644 --- a/sites/platform/src/create-apps/app-reference/single-runtime-image.md +++ b/sites/platform/src/create-apps/app-reference/single-runtime-image.md @@ -1,6 +1,6 @@ --- title: "Single-runtime image" -weight: 4 +weight: 2 description: See all of the options for controlling your apps and how they're built and deployed on {{% vendor/name %}}. keywords: - sleepy crons @@ -19,34 +19,36 @@ For reference, see a [log of changes to app configuration](/create-apps/upgradin ## Top-level properties -The following table presents all properties available at the top level of the YAML for the app. +The following table lists all properties available at the top level of the YAML for the app. The column _Set in instance?_ defines whether the given property can be overridden within a `web` or `workers` instance. To override any part of a property, you have to provide the entire property. +- **Note:** Except for the `build`, `dependencies`, and `runtime` keys, the keys listed below are available in **both** the single-runtime and composable image types. Clicking the link for their details leads you to a separate topic for that property. Descriptions for properties that are **unique** to this image type are provided later in this topic. + + | Name | Type | Required | Set in instance? | Description | |--------------------|--------------------------------------------------------------------------|----------|------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `name` | `string` | Yes | No | A unique name for the app. Must be lowercase alphanumeric characters. Changing the name destroys data associated with the app. | -| `type` | A [type](#types) | Yes | No | The base image to use with a specific app language. Format: `runtime:version`. | -| `size` | A [size](#sizes) | | Yes | How much resources to devote to the app. Defaults to `AUTO` in production environments. | -| `relationships` | A dictionary of [relationships](#relationships) | | Yes | Connections to other services and apps. | -| `disk` | `integer` or `null` | | Yes | The size of the disk space for the app in [MB](/glossary/_index.md#mb). Minimum value is `128`. Defaults to `null`, meaning no disk is available. See [note on available space](#available-disk-space) | -| `mounts` | A dictionary of [mounts](#mounts) | | Yes | Directories that are writable even after the app is built. If set as a local source, `disk` is required. | -| `web` | A [web instance](#web) | | N/A | How the web application is served. | -| `workers` | A [worker instance](#workers) | | N/A | Alternate copies of the application to run as background processes. | +| [`type`](#types) | A type | Yes | No | The base image to use with a specific app language. Format: `runtime:version`. | +| [`size`](/create-apps/image-properties/size.md) | A size | | Yes | How much resources to devote to the app. Defaults to `AUTO` in production environments. | +| [`relationships`](/create-apps/image-properties/relationships.md) | A dictionary of relationships | | Yes | Connections to other services and apps. | +| [`disk`](/create-apps/image-properties/disk.md) | `integer` or `null` | | Yes | The size of the disk space for the app in [MB](/glossary/_index.md#mb). Minimum value is `128`. Defaults to `null`, meaning no disk is available. See the [`disk`](/create-apps/image-properties/disk.md) property details. | +| [`mounts`](/create-apps/image-properties/mounts.md) | A dictionary of mounts | | Yes | Directories that are writable even after the app is built. If set as a local source, `disk` is required. | +| [`web`](/create-apps/image-properties/web.md) | A web instance | | N/A | How the web application is served. | +| [`workers`](/create-apps/image-properties/workers.md) | A worker instance | | N/A | Alternate copies of the application to run as background processes. | | `timezone` | `string` | | No | The timezone for crons to run. Format: a [TZ database name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Defaults to `UTC`, which is the timezone used for all logs no matter the value here. See also [app runtime timezones](/create-apps/timezone.md) | -| `access` | An [access dictionary](#access) | | Yes | Access control for roles accessing app environments. | -| `variables` | A [variables dictionary](#variables) | | Yes | Variables to control the environment. | -| `firewall` | A [firewall dictionary](#firewall) | | Yes | Outbound firewall rules for the application. | -| `build` | A [build dictionary](#build) | | No | What happens when the app is built. | -| `dependencies` | A [dependencies dictionary](#dependencies) | | No | What global dependencies to install before the `build` hook is run. | -| `hooks` | A [hooks dictionary](#hooks) | | No | What commands run at different stages in the build and deploy process. | -| `crons` | A [cron dictionary](#crons) | | No | Scheduled tasks for the app. | -| `source` | A [source dictionary](#source) | | No | Information on the app's source code and operations that can be run on it. | -| `runtime` | A [runtime dictionary](#runtime) | | No | Customizations to your PHP runtime. | -| `additional_hosts` | An [additional hosts dictionary](#additional-hosts) | | Yes | Maps of hostnames to IP addresses. | -| `operations` | A [dictionary of Runtime operations](/create-apps/runtime-operations.md) | | No | Runtime operations for the application. | - +| [`access`](/create-apps/image-properties/access.md) | An access dictionary | | Yes | Access control for roles accessing app environments. | +| [`variables`](/create-apps/image-properties/variables.md) | A variables dictionary | | Yes | Variables to control the environment. | +| [`firewall`](/create-apps/image-properties/firewall.md) | A [firewall dictionary | | Yes | Outbound firewall rules for the application. | +| [`build`](#build) | A build dictionary | | No | What happens when the app is built. | +| [`dependencies`](#dependencies) | A dependencies dictionary | | No | What global dependencies to install before the `build` hook is run. | +| [`hooks`](/create-apps/image-properties/hooks.md) | A hooks dictionary | | No | What commands run at different stages in the build and deploy process. | +| [`crons`](/create-apps/image-properties/crons.md) | A cron dictionary | | No | Scheduled tasks for the app. | +| [`source`](/create-apps/image-properties/source.md) | A source dictionary | | No | Information on the app's source code and operations that can be run on it. | +| [`runtime`](#runtime) | A runtime dictionary | | No | Customizations to your PHP runtime. | +| [`additional_hosts`](/create-apps/image-properties/additional_hosts.md) | An additional hosts dictionary | | Yes | Maps of hostnames to IP addresses. | +| [`operations`](/create-apps/runtime-operations.md) | A dictionary of Runtime operations | | No | Runtime operations for the application. | ## Root directory Some of the properties you can define are relative to your app's root directory. @@ -57,7 +59,7 @@ That is, if a custom value for `source.root` is not provided in your configurati To specify another directory, for example for a [multi-app project](/create-apps/multi-app/_index.md), use the [`source.root` property](#source). -## Types +## `type` {#types} {{% note theme="info" %}} You can now use the {{% vendor/name %}} composable image (BETA) to install runtimes and tools in your application container. @@ -82,792 +84,7 @@ These are used in the format `runtime:version`: type: 'php:{{% latest "php" %}}' ``` -## Sizes - -Resources are distributed across all containers in an environment from the total available from your [plan size](/administration/pricing/_index.md). -So if you have more than just a single app, it doesn't get all of the resources available. -Each environment has its own resources and there are different [sizing rules for preview environments](#sizes-in-preview-environments). - -By default, resource sizes (CPU and memory) are chosen automatically for an app -based on the plan size and the number of other containers in the cluster. -Most of the time, this automatic sizing is enough. - -You can set sizing suggestions for production environments when you know a given container has specific needs. -Such as a worker that doesn't need much and can free up resources for other apps. -To do so, set `size` to one of the following values: - -- `S` -- `M` -- `L` -- `XL` -- `2XL` -- `4XL` - -The total resources allocated across all apps and services can't exceed what's in your plan. - -### Container profiles: CPU and memory - -By default, {{% vendor/name %}} allocates a container profile to each app and service depending on: - -- The range of resources it’s expected to need -- Your [plan size](/administration/pricing/_index.md), as resources are distributed across containers. - Ideally you want to give databases the biggest part of your memory, and apps the biggest part of your CPU. - -The container profile and the [size of the container](#sizes) determine -how much CPU and memory (in [MB](/glossary/_index.md#mb)) the container gets. - -There are three container profiles available: ``HIGH_CPU``, ``BALANCED``, and ``HIGH_MEMORY``. - -#### ``HIGH_CPU`` container profile - -| Size | CPU | MEMORY | -| ---- | ----- | -------- | -| S | 0.40 | 128 MB | -| M | 0.40 | 128 MB | -| L | 1.20 | 256 MB | -| XL | 2.50 | 384 MB | -| 2XL | 5.00 | 768 MB | -| 4XL | 10.00 | 1536 MB | - -#### `BALANCED` container profile - -| Size | CPU | MEMORY | -| ---- | ---- | -------- | -| S | 0.05 | 32 MB | -| M | 0.05 | 64 MB | -| L | 0.08 | 256 MB | -| XL | 0.10 | 512 MB | -| 2XL | 0.20 | 1024 MB | -| 4XL | 0.40 | 2048 MB | - -#### `HIGH_MEMORY` container profile - -| Size | CPU | MEMORY | -| ---- | ---- | --------- | -| S | 0.25 | 128 MB | -| M | 0.25 | 288 MB | -| L | 0.40 | 1280 MB | -| XL | 0.75 | 2624 MB | -| 2XL | 1.50 | 5248 MB | -| 4XL | 3.00 | 10496 MB | - -#### Container profile reference - -The following table shows which container profiles {{% vendor/name %}} applies when deploying your project. - -| Container | Profile | -|-----------------------|-------------| -| Chrome Headless | HIGH_CPU | -| .NET | HIGH_CPU | -| Elasticsearch | HIGH_MEMORY | -| Elasticsearch Premium | HIGH_MEMORY | -| Elixir | HIGH_CPU | -| Go | HIGH_CPU | -| Gotenberg | HIGH_MEMORY | -| InfluxDB | HIGH_MEMORY | -| Java | HIGH_MEMORY | -| Kafka | HIGH_MEMORY | -| MariaDB | HIGH_MEMORY | -| Memcached | BALANCED | -| MongoDB | HIGH_MEMORY | -| MongoDB Premium | HIGH_MEMORY | -| Network Storage | HIGH_MEMORY | -| Node.js | HIGH_CPU | -| OpenSearch | HIGH_MEMORY | -| Oracle MySQL | HIGH_MEMORY | -| PHP | HIGH_CPU | -| PostgreSQL | HIGH_MEMORY | -| Python | HIGH_CPU | -| RabbitMQ | HIGH_MEMORY | -| Redis ephemeral | BALANCED | -| Redis persistent | BALANCED | -| Ruby | HIGH_CPU | -| Rust | HIGH_CPU | -| Solr | HIGH_MEMORY | -| Varnish | HIGH_MEMORY | -| Vault KMS | HIGH_MEMORY | - -### Sizes in preview environments - -Containers in preview environments don't follow the `size` specification. -Application containers are set based on the plan's setting for **Environments application size**. -The default is size **S**, but you can increase it by editing your plan. -(Service containers in preview environments are always set to size **S**.) - -## Relationships - -To allow containers in your project to communicate with one another, -you need to define relationships between them. -You can define a relationship between an app and a service, or [between two apps](/create-apps/multi-app/relationships.md). - -The quickest way to define a relationship between your app and a service -is to use the service's default endpoint.
-However, some services allow you to define multiple databases, cores, and/or permissions. -In these cases, you can't rely on default endpoints. -Instead, you can explicitly define multiple endpoints when setting up your relationships. - -{{< note >}} -App containers don't have a default endpoint like services. -To connect your app to another app in your project, -you need to explicitly define the `http` endpoint as the endpoint to connect both apps.
-For more information, see how to [define relationships between your apps](/create-apps/multi-app/relationships.md). -{{< /note >}} - -{{< note title="Availability" theme="info">}} - -New syntax (default and explicit endpoints) described below is supported by most, but not all, image types -(`Relationship 'SERVICE_NAME' of application 'myapp' ... targets a service without a valid default endpoint configuration.`). -This syntax is currently being rolled out for all images. -If you encounter this error, use the "legacy" {{% vendor/name %}} configuration noted at the bottom of this section. - -{{< /note >}} - -To define a relationship between your app and a service: - -{{< codetabs >}} - -+++ -title=Using default endpoints -+++ - -Use the following configuration: - -```yaml {configFile="app"} -relationships: - {{% variable "SERVICE_NAME" %}}: -``` - -The `SERVICE_NAME` is the name of the service as defined in its [configuration](/add-services/_index.md). -It is used as the relationship name, and associated with a `null` value. -This instructs {{% vendor/name %}} to use the service's default endpoint to connect your app to the service. - -For example, if you define the following configuration: - -```yaml {configFile="app"} -relationships: - mariadb: -``` - -{{% vendor/name %}} looks for a service named `mariadb` in your `{{% vendor/configfile "services" %}}` file, -and connects your app to it through the service's default endpoint. - -For reference, the equivalent configuration using explicit endpoints would be the following: - -```yaml {configFile="app"} -relationships: - mariadb: - service: mariadb - endpoint: mysql -``` - -You can define any number of relationships in this way: - -```yaml {configFile="app"} -relationships: - mariadb: - redis: - elasticsearch: -``` - -{{< note title="Tip" theme="info" >}} - -An even quicker way to define many relationships is to use the following single-line configuration: - -```yaml {configFile="app"} -relationships: {{{< variable "SERVICE_NAME_A" >}}, {{< variable "SERVICE_NAME_B" >}}, {{< variable "SERVICE_NAME_C" >}}} -``` - -where - -```yaml {configFile="services"} -{{< variable "SERVICE_NAME_A" >}}: - type: mariadb:{{% latest "mariadb" %}} - disk: 256 -{{< variable "SERVICE_NAME_B" >}}: - type: redis:{{% latest "redis" %}} - disk: 256 -{{< variable "SERVICE_NAME_C" >}}: - type: elasticsearch:{{% latest "elasticsearch" %}} - disk: 256 -``` - -{{< /note >}} - -<---> - -+++ -title=Using explicit endpoints -+++ - -Use the following configuration: - -```yaml {configFile="app"} -relationships: - {{% variable "RELATIONSHIP_NAME" %}}: - service: {{% variable "SERVICE_NAME" %}} - endpoint: {{% variable "ENDPOINT_NAME" %}} -``` - -- `RELATIONSHIP_NAME` is the name you want to give to the relationship. -- `SERVICE_NAME` is the name of the service as defined in its [configuration](/add-services/_index.md). -- `ENDPOINT_NAME` is the endpoint your app will use to connect to the service (refer to the service reference to know which value to use). - -For example, to define a relationship named `database` that connects your app to a service called `mariadb` through the `db1` endpoint, -use the following configuration: - -```yaml {configFile="app"} -relationships: - database: # The name of the relationship. - service: mariadb - endpoint: db1 -``` - -For more information on how to handle multiple databases, multiple cores, -and/or different permissions with services that support such features, -see each service's dedicated page: - - - [MariaDB/MySQL](/add-services/mysql/_index.md#multiple-databases) (multiple databases and permissions) - - [PostgreSQL](/add-services/postgresql/_index.md#multiple-databases) (multiple databases and permissions) - - [Redis](/add-services/redis/_index.md#multiple-databases) (multiple databases) - - [Solr](add-services/solr/_index.md#solr-6-and-later) (multiple cores) - - [Vault KMS](add-services/vault.md#multiple-endpoints-configuration) (multiple permissions) - - You can add as many relationships as you want to your app configuration, - using both default and explicit endpoints according to your needs: - -```yaml {configFile="app"} -relationships: - database1: - service: mariadb - endpoint: admin - database2: - service: mariadb - endpoint: legacy - cache: - service: redis - search: - service: elasticsearch -``` - -{{< /codetabs >}} - -{{< note theme="info" title="Legacy" >}} - -The following legacy syntax for specifying relationships is still supported by {{% vendor/name %}}: - -```yaml {configFile="app"} -relationships: - : ":" -``` - -For example: - -```yaml {configFile="app"} -relationships: - database: "mariadb:mysql" -``` - -Feel free to use this until the default and explicit endpoint syntax is supported on all images. - -{{< /note >}} - -## Available disk space - -The maximum total space available to all apps and services is set by the storage in your plan settings. -When deploying your project, the sum of all `disk` keys defined in app and service configurations -must be *equal or less* than the plan storage size. - -So if your *plan storage size* is 5 GB, you can, for example, assign it in one of the following ways: - -- 2 GB to your app, 3 GB to your database -- 1 GB to your app, 4 GB to your database -- 1 GB to your app, 1 GB to your database, 3 GB to your OpenSearch service - -If you exceed the total space available, you receive an error on pushing your code. -You need to either increase your plan's storage or decrease the `disk` values you've assigned. - -You configure the disk size in [MB](/glossary/_index.md#mb). Your actual available disk space is slightly smaller with some space used for formatting and the filesystem journal. When checking available space, note whether it’s reported in MB or MiB. - -### Downsize a disk - -You can decrease the size of an existing disk for an app. If you do so, be aware that: - -- Backups from before the downsize are incompatible and can no longer be used. You need to [create new backups](/environments/backup.md). -- The downsize fails if there’s more data on the disk than the desired size. - -## Mounts - -After your app is built, its file system is read-only. -To make changes to your app's code, you need to use Git. - -For enhanced flexibility, {{% vendor/name %}} allows you to define and use writable directories called "mounts". -Mounts give you write access to files generated by your app (such as cache and log files) -and uploaded files without going through Git. - -When you define a mount, you are mounting an external directory to your app container, -much like you would plug a hard drive into your computer to transfer data. - -{{% note %}} - -- Mounts aren't available during the build -- When you [back up an environment](/environments/backup.md), the mounts on that environment are backed up too - -{{% /note %}} - -### Define a mount - -To define a mount, use the following configuration: - -```yaml {configFile="app"} -mounts: - '{{< variable "MOUNT_PATH" >}}': - source: {{< variable "MOUNT_TYPE" >}} - source_path: {{< variable "SOURCE_PATH_LOCATION" >}} -``` - -{{< variable "MOUNT_PATH" >}} is the path to your mount **within the app container** (relative to the app's root). -If you already have a directory with that name, you get a warning that it isn't accessible after the build. -See how to [troubleshoot the warning](/create-apps/troubleshoot-mounts.md#overlapping-folders). - -| Name | Type | Required | Description | -| ------------- |-------------------------------| -------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `source` | `local`, `service`, or `tmp` | Yes | Specifies the type of the mount:

- `local` mounts are unique to your app. They can be useful to store files that remain local to the app instance, such as application logs.
`local` mounts require disk space. To successfully set up a local mount, set the `disk` key in your app configuration.

- `service` mounts point to [Network Storage](/add-services/network-storage.md) services that can be shared between several apps.

- `tmp` mounts are local ephemeral mounts, where an external directory is mounted to the `/tmp` directory of your app.
The content of a `tmp` mount **may be removed during infrastructure maintenance operations**. Therefore, `tmp` mounts allow you to **store files that you’re not afraid to lose**, such as your application cache that can be seamlessly rebuilt.
Note that the `/tmp` directory has **a maximum allocation of 8 GB**. | -| `source_path` | `string` | No | Specifies where the mount points **inside the [external directory](#mounts)**.

- If you explicitly set a `source_path`, your mount points to a specific subdirectory in the external directory.

- If the `source_path` is an empty string (`""`), your mount points to the entire external directory.

- If you don't define a `source_path`, {{% vendor/name %}} uses the {{< variable "MOUNT_PATH" >}} as default value, without leading or trailing slashes.
For example, if your mount lives in the `/web/uploads/` directory in your app container, it will point to a directory named `web/uploads` in the external directory.

**WARNING:** Changing the name of your mount affects the `source_path` when it's undefined. See [how to ensure continuity](#ensure-continuity-when-changing-the-name-of-your-mount) and maintain access to your files. | -| `service` | `string` | | Only for `service` mounts: the name of the [Network Storage service](/add-services/network-storage.md). | - - -The accessibility to the web of a mounted directory depends on the [`web.locations` configuration](#web). -Files can be all public, all private, or with different rules for different paths and file types. - -Note that when you remove a `local` mount from your `{{< vendor/configfile "app" >}}` file, -the mounted directory isn't deleted. -The files still exist on disk until manually removed -(or until the app container is moved to another host during a maintenance operation in the case of a `tmp` mount). - -### Example configuration - -```yaml {configFile="app"} -mounts: - 'web/uploads': - source: local - source_path: uploads - '/.tmp_platformsh': - source: tmp - source_path: files/.tmp_platformsh - '/build': - source: local - source_path: files/build - '/.cache': - source: tmp - source_path: files/.cache - '/node_modules/.cache': - source: tmp - source_path: files/node_modules/.cache -``` - -For examples of how to set up a `service` mount, see the dedicated [Network Storage page](/add-services/network-storage.md). - -### Ensure continuity when changing the name of your mount - -Changing the name of your mount affects the default `source_path`. - -Say you have a `/my/cache/` mount with an undefined `source_path`: - -```yaml {configFile="app"} -mounts: - '/my/cache/': - source: tmp -``` - -If you rename the mount to `/cache/files/`, it will point to a new, empty `/cache/files/` directory. - -To ensure continuity, you need to explicitly define the `source_path` as the previous name of the mount, without leading or trailing slashes: - - ```yaml {configFile="app"} -mounts: - '/cache/files/': - source: tmp - source_path: my/cache -``` - -The `/cache/files/` mount will point to the original `/my/cache/` directory, maintaining access to all your existing files in that directory. - -### Overlapping mounts - -The locations of mounts as they are visible to application containers can overlap somewhat. -For example: - -```yaml {configFile="apps"} -applications: - myapp: - # ... - mounts: - 'var/cache_a': - source: service - service: ns_service - source_path: cacheA - 'var/cache_b': - source: tmp - source_path: cacheB - 'var/cache_c': - source: local - source_path: cacheC -``` - -In this case, it does not matter that each mount is of a different `source` type. -Each mount is restricted to a subfolder within `var`, and all is well. - -The following, however, is not allowed and will result in a failure: - -```yaml {configFile="apps"} -applications: - myapp: - # ... - mounts: - 'var/': - source: service - service: ns_service - source_path: cacheA - 'var/cache_b': - source: tmp - source_path: cacheB - 'var/cache_c': - source: local - source_path: cacheC -``` - -The `service` mount type specifically exists to share data between instances of the same application, whereas `tmp` and `instance` are meant to restrict data to build time and runtime of a single application instance, respectively. -These allowances are not compatible, and will result in an error if pushed. - -## Web - -Use the `web` key to configure the web server running in front of your app. -Defaults may vary with a different [image `type`](#types). - -| Name | Type | Required | Description | -|-------------|--------------------------------------------|-------------------------------|------------------------------------------------------| -| `commands` | A [web commands dictionary](#web-commands) | See [note](#required-command) | The command to launch your app. | -| `upstream` | An [upstream dictionary](#upstream) | | How the front server connects to your app. | -| `locations` | A [locations dictionary](#locations) | | How the app container responds to incoming requests. | - -See some [examples of how to configure what's served](/create-apps/web/_index.md). - -### Web commands - - -| Name | Type | Required | Description | -|--------------|----------|-------------------------------|-----------------------------------------------------------------------------------------------------| -| `pre_start` | `string` | | Command run just prior to `start`, which can be useful when you need to run _per-instance_ actions. | -| `start` | `string` | See [note](#required-command) | The command to launch your app. If it terminates, it's restarted immediately. | -| `post_start` | `string` | | Command runs **before** adding the container to the router and **after** the `start` command. | - -{{< note theme="info" >}} -The `post_start` feature is _experimental_ and may change. Please share your feedback in the -[{{% vendor/name %}} discord](https://discord.gg/platformsh). -{{< /note >}} - - -Example: - -```yaml {configFile="app"} -web: - commands: - start: 'uwsgi --ini conf/server.ini' -``` - -This command runs every time your app is restarted, regardless of whether or not new code is deployed. - -{{< note >}} - -Never "background" a start process using `&`. -That's interpreted as the command terminating and the supervisor process starts a second copy, -creating an infinite loop until the container crashes. -Just run it as normal and allow the {{% vendor/name %}} supervisor to manage it. - -{{< /note >}} - -#### Required command - -On all containers other than PHP, the value for `start` should be treated as required. - -On PHP containers, it's optional and defaults to starting PHP-FPM (`/usr/bin/start-php-app`). -It can also be set explicitly on a PHP container to run a dedicated process, -such as [React PHP](https://github.com/platformsh-examples/platformsh-example-reactphp) -or [Amp](https://github.com/platformsh-examples/platformsh-example-amphp). -See how to set up [alternate start commands on PHP](/languages/php/_index.md#alternate-start-commands). - -### Upstream - -| Name | Type | Required | Description | Default | -| --------------- |---------------------| -------- |-------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------| -| `socket_family` | `tcp` or `unix` | | Whether your app listens on a Unix or TCP socket. | Defaults to `tcp` for all [image types](#types) except PHP; for PHP image types the default is `unix`. | -| `protocol` | `http` or `fastcgi` | | Whether your app receives incoming requests over HTTP or FastCGI. | Default varies based on [image `type`](#types). | - -For PHP, the defaults are configured for PHP-FPM and shouldn't need adjustment. -For all other containers, the default for `protocol` is `http`. - -The following example is the default on non-PHP containers: - -```yaml {configFile="app"} -web: - upstream: - socket_family: tcp - protocol: http -``` -#### Where to listen - -Where to listen depends on your setting for `web.upstream.socket_family` (defaults to `tcp`). - -| `socket_family` | Where to listen | -|------------------|---------------------------------------------------------------------------------------------------------------------------------------| -| `tcp` | The port specified by the [`PORT` environment variable](/development/variables/use-variables.md#use-provided-variables) | -| `unix` | The Unix socket file specified by the [`SOCKET` environment variable](/development/variables/use-variables.md#use-provided-variables) | - -If your application isn't listening at the same place that the runtime is sending requests, -you see `502 Bad Gateway` errors when you try to connect to your website. - -### Locations - -Each key in the `locations` dictionary is a path on your site with a leading `/`. -For `example.com`, a `/` matches `example.com/` and `/admin` matches `example.com/admin`. -When multiple keys match an incoming request, the most-specific applies. - -The following table presents possible properties for each location: - -| Name | Type | Default | Description | -| ------------------- | ---------------------------------------------------- |------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `root` | `string` | | The directory to serve static assets for this location relative to the [app's root directory](#root-directory). Must be an actual directory inside the root directory. | -| `passthru` | `boolean` or `string` | `false` | Whether to forward disallowed and missing resources from this location to the app. A string is a path with a leading `/` to the controller, such as `/index.php`.

If your app is in PHP, when setting `passthru` to `true`, you might want to set `scripts` to `false` for enhanced security. This prevents PHP scripts from being executed from the specified location. You might also want to set `allow` to `false` so that not only PHP scripts can't be executed, but their source code also can't be delivered. | -| `index` | Array of `string`s or `null` | | Files to consider when serving a request for a directory. When set, requires access to the files through the `allow` or `rules` keys. | -| `expires` | `string` | `-1` | How long static assets are cached. The default means no caching. Setting it to a value enables the `Cache-Control` and `Expires` headers. Times can be suffixed with `ms` = milliseconds, `s` = seconds, `m` = minutes, `h` = hours, `d` = days, `w` = weeks, `M` = months/30d, or `y` = years/365d. If a `Cache-Control` appears on the `headers` configuration, `expires`, if set, will be ignored. Thus, make sure to set the `Cache-Control`'s `max-age` value when specifying a the header. | -| `allow` | `boolean` | `true` | Whether to allow serving files which don't match a rule. | -| `scripts` | `boolean` | | Whether to allow scripts to run. Doesn't apply to paths specified in `passthru`. Meaningful only on PHP containers. | -| `headers` | A headers dictionary | | Any additional headers to apply to static assets, mapping header names to values (see [Set custom headers on static content](/create-apps/web/custom-headers.html)). Responses from the app aren't affected. | -| `request_buffering` | A [request buffering dictionary](#request-buffering) | See below | Handling for chunked requests. | -| `rules` | A [rules dictionary](#rules) | | Specific overrides for specific locations. | - -#### Rules - -The rules dictionary can override most other keys according to a regular expression. -The key of each item is a regular expression to match paths exactly. -If an incoming request matches the rule, it's handled by the properties under the rule, -overriding any conflicting rules from the rest of the `locations` dictionary. - -Under `rules`, you can set all the other possible [`locations` properties](#locations) -except `root`, `index`, `rules` and `request_buffering`. - -In the following example, the `allow` key disallows requests for static files anywhere in the site. -This is overridden by a rule that explicitly allows common image file formats. - -```yaml {configFile="app"} -web: - locations: - '/': - # Handle dynamic requests - root: 'public' - passthru: '/index.php' - # Disallow static files - allow: false - rules: - # Allow common image files only. - '\.(jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff2?|otf|ttf)$': - allow: true -``` -#### Request buffering - -Request buffering is enabled by default to handle chunked requests as most app servers don't support them. -The following table shows the keys in the `request_buffering` dictionary: - -| Name | Type | Required | Default | Description | -| ------------------ | --------- |----------| ------- |-------------------------------------------| -| `enabled` | `boolean` | Yes | `true` | Whether request buffering is enabled. | -| `max_request_size` | `string` | | `250m` | The maximum size to allow in one request. | - -The default configuration would look like this: - -```yaml {configFile="app"} -web: - locations: - '/': - passthru: true - request_buffering: - enabled: true - max_request_size: 250m -``` -## Workers - -Workers are exact copies of the code and compilation output as a `web` instance after a [`build` hook](#hooks). -They use the same container image. - -Workers can't accept public requests and so are suitable only for background tasks. -If they exit, they're automatically restarted. - -The keys of the `workers` definition are the names of the workers. -You can then define how each worker differs from the `web` instance using -the [top-level properties](#top-level-properties). - -Each worker can differ from the `web` instance in all properties _except_ for: - -- `build` and `dependencies` properties, which must be the same -- `crons` as cron jobs don't run on workers -- `hooks` as the `build` hook must be the same - and the `deploy` and `post_deploy` hooks don't run on workers. - -A worker named `queue` that was small and had a different start command could look like this: - -```yaml {configFile="app"} -workers: - queue: - size: S - commands: - start: | - ./worker.sh -``` - -For resource allocation, using workers in your project requires a [{{< partial "plans/multiapp-plan-name" >}} plan or larger](https://platform.sh/pricing/). - -## Access - -The `access` dictionary has one allowed key: - -| Name | Allowed values | Default | Description | -| ----- | ----------------------------------- | ------------- | ----------- | -| `ssh` | `admin`, `contributor`, or `viewer` | `contributor` | Defines the minimum role required to access app environments via SSH. | - -In the following example, only users with `admin` permissions for the given [environment type](/administration/users.md#environment-type-roles) -can access the deployed environment via SSH: - -```yaml {configFile="app"} -access: - ssh: admin -``` -## Variables - -{{% vendor/name %}} provides a number of ways to set [variables](/development/variables/_index.md). -Variables set in your app configuration have the lowest precedence, -meaning they're overridden by any conflicting values provided elsewhere. - -All variables set in your app configuration must have a prefix. -Some [prefixes have specific meanings](/development/variables/_index.md#variable-prefixes). - -Variables with the prefix `env` are available as a separate environment variable. -All other variables are available in the [`PLATFORM_VARIABLES` environment variable](/development/variables/use-variables.md#use-provided-variables). - -The following example sets two variables: - -- A variable named `env:AUTHOR` with the value `Juan` that's available in the environment as `AUTHOR` -- A variable named `d8config:system.site:name` with the value `My site rocks` - that's available in the `PLATFORM_VARIABLES` environment variable - -```yaml {configFile="app"} -variables: - env: - AUTHOR: 'Juan' - d8config: - "system.site:name": 'My site rocks' -``` - -You can also define and access more [complex values](/development/variables/use-variables.md#access-complex-values). - -## Firewall - -{{< premium-features/tiered "Elite and Enterprise" >}} - -Set limits in outbound traffic from your app with no impact on inbound requests. - -The `outbound` key is required and contains one or more rules. -The rules define what traffic is allowed; anything unspecified is blocked. - -Each rule has the following properties where at least one is required and `ips` and `domains` can't be specified together: - -| Name | Type | Default | Description | -| --------- |---------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `ips` | Array of `string`s | `["0.0.0.0/0"]` | IP addresses in [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing). See a [CIDR format converter](https://www.ipaddressguide.com/cidr). | -| `domains` | Array of `string`s | | [Fully qualified domain names](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) to specify specific destinations by hostname. | -| `ports` | Array of `integer`s | | Ports from 1 to 65535 that are allowed. If any ports are specified, all unspecified ports are blocked. If no ports are specified, all ports are allowed. Port `25`, the SMTP port for sending email, is always blocked. | - -The default settings would look like this: - -```yaml {configFile="app"} -firewall: - outbound: - - ips: ["0.0.0.0/0"] -``` - -### Support for rules - -Where outbound rules for firewalls are supported in all environments. -For {{% names/dedicated-gen-2 %}} projects, contact support for configuration. - -### Multiple rules - -Multiple firewall rules can be specified. -In such cases, a given outbound request is allowed if it matches _any_ of the defined rules. - -So in the following example requests to any IP on port 80 are allowed -and requests to 1.2.3.4 on either port 80 or 443 are allowed: - -```yaml {configFile="app"} -firewall: - outbound: - - ips: ["1.2.3.4/32"] - ports: [443] - - ports: [80] -``` - -### Outbound traffic to CDNs - -Be aware that many services are behind a content delivery network (CDN). -For most CDNs, routing is done via domain name, not IP address, -so thousands of domain names may share the same public IP addresses at the CDN. -If you allow the IP address of a CDN, you are usually allowing many or all of the other customers hosted behind that -CDN. - -### Outbound traffic by domain - -You can filter outbound traffic by domain. -Using domains in your rules rather than IP addresses is generally more specific and secure. -For example, if you use an IP address for a service with a CDN, -you have to allow the IP address for the CDN. -This means that you allow potentially hundreds or thousands of other servers also using the CDN. - -An example rule filtering by domain: - -```yaml {configFile="app"} -firewall: - outbound: - - protocol: tcp - domains: ["api.stripe.com", "api.twilio.com"] - ports: [80, 443] - - protocol: tcp - ips: ["1.2.3.4/29","2.3.4.5"] - ports: [22] -``` -#### Determine which domains to allow - -To determine which domains to include in your filtering rules, -find the domains your site has requested the DNS to resolve. -Run the following command to parse your server’s `dns.log` file -and display all Fully Qualified Domain Names that have been requested: - -```bash -awk '/query\[[^P]\]/ { print $6 | "sort -u" }' /var/log/dns.log -``` - -The output includes all DNS requests that were made, including those blocked by your filtering rules. -It doesn't include any requests made using an IP address. - -Example output: - -```bash -facebook.com -fastly.com -platform.sh -www.google.com -www.platform.sh -``` - -## Build +## `build` {#build} The only property of the `build` dictionary is `flavor`, which specifies a default set of build tasks to run. Flavors are language-specific. @@ -884,7 +101,7 @@ In all languages, you can also specify a flavor of `none` to take no action at a build: flavor: none ``` -## Dependencies +## `dependencies` {#dependencies} Installs global dependencies as part of the build process. They're independent of your app's dependencies @@ -919,300 +136,7 @@ dependencies: pm2: '^4.5.0' ``` -## Hooks - -There are three different hooks that run as part of the process of building and deploying your app. -These are places where you can run custom scripts. -They are: the `build` hook, the `deploy` hook, and the `post_deploy` hook. -Only the `build` hook is run for [worker instances](#workers), while [web instances](#web) run all three. - -The process is ordered as: - -1. Variables accessible at build time become available. -1. [Build flavor](#build) runs if applicable. -1. Any [dependencies](#dependencies) are installed. -1. The `build` hook is run. -1. The file system is changed to read only (except for any [mounts](#mounts)). -1. The app container starts. Variables accessible at runtime and services become available. -1. The `deploy` hook is run. -1. The app container begins accepting requests. -1. The `post_deploy` hook is run. - -Note that if an environment changes by no code changes, only the last step is run. -If you want the entire process to run, see how -to [manually trigger builds](/development/troubleshoot.md#manually-trigger-builds). - -### Writable directories during build - -During the `build` hook, there are three writeable directories: - -- `PLATFORM_APP_DIR`: - Where your code is checked out and the working directory when the `build` hook starts. - Becomes the app that gets deployed. -- `PLATFORM_CACHE_DIR`: - Persists between builds, but isn't deployed. - Shared by all builds on all branches. -- `/tmp`: - Isn't deployed and is wiped between each build. - Note that `PLATFORM_CACHE_DIR` is mapped to `/tmp` - and together they offer about 8GB of free space. - -### Hook failure - -Each hook is executed as a single script, so they're considered to have failed only if the final command in them fails. -To cause them to fail on the first failed command, add `set -e` to the beginning of the hook. - -If a `build` hook fails for any reason, the build is aborted and the deploy doesn't happen. -Note that this only works for `build` hooks -- -if other hooks fail, the app is still deployed. - -#### Automated testing - -It’s preferable that you set up and run automated tests in a dedicated CI/CD tool. -Relying on {{% vendor/name %}} hooks for such tasks can prove difficult. - -During the `build` hook, you can halt the deployment on a test failure but the following limitations apply: - -- Access to services such as databases, Redis, Vault KMS, and even writable mounts is disabled. - So any testing that relies on it is sure to fail. -- If you haven’t made changes to your app, an existing build image is reused and the build hook isn’t run. -- Test results are written into your app container, so they might get exposed to a third party. - -During the `deploy` hook, you can access services but **you can’t halt the deployment based on a test failure**. -Note that there are other downsides: - -- Your app container is read-only during the deploy hook, - so if your tests need to write reports and other information, you need to create a file mount for them. -- Your app can only be deployed once the deploy hook has been completed. - Therefore, running automated testing via the deploy hook generates slower deployments. -- Your environment isn’t available externally during the deploy hook. - Unit and integration testing might work without the environment being available, - but you can’t typically perform end-to-end testing until after the environment is up and available. - -## Crons - -The keys of the `crons` definition are the names of the cron jobs. -The names must be unique. - -If an application defines both a `web` instance and `worker` instances, cron jobs run only on the `web` instance. - -See how to [get cron logs](/increase-observability/logs/access-logs.md#container-logs). - -The following table shows the properties for each job: - -| Name | Type | Required | Description | -| ------------------ | -------------------------------------------- | -------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `spec` | `string` | Yes | The [cron specification](https://en.wikipedia.org/wiki/Cron#Cron_expression). To prevent competition for resources that might hurt performance, on **Grid or {{% names/dedicated-gen-3 %}}** projects use `H` in definitions to indicate an unspecified but invariant time. For example, instead of using `0 * * * *` to indicate the cron job runs at the start of every hour, you can use `H * * * *` to indicate it runs every hour, but not necessarily at the start. This prevents multiple cron jobs from trying to start at the same time. **The `H` syntax isn't available on {{% names/dedicated-gen-2 %}} projects.** | -| `commands` | A [cron commands dictionary](#cron-commands) | Yes | A definition of what commands to run when starting and stopping the cron job. | -| `shutdown_timeout` | `integer` | No | When a cron is canceled, this represents the number of seconds after which a `SIGKILL` signal is sent to the process to force terminate it. The default is `10` seconds. | -| `timeout` | `integer` | No | The maximum amount of time a cron can run before it's terminated. Defaults to the maximum allowed value of `86400` seconds (24 hours). - -Note that you can [cancel pending or running crons](/environments/cancel-activity.md). - -{{< note >}} - -The use of the `cmd` key is now deprecated in favor of the `commands`key.
-Make sure you set your new cron jobs using the `commands` key, -and update your existing cron jobs to ensure continuity. - -{{< /note >}} - -### Cron commands - -| Name | Type | Required | Description | -| ------------------ | --------- | -------- | ----------- | -| `start` | `string` | Yes | The command that's run. It's run in [Dash](https://en.wikipedia.org/wiki/Almquist_shell). | -| `stop` | `string` | No | The command that's issued to give the cron command a chance to shutdown gracefully, such as to finish an active item in a list of tasks. Issued when a cron task is interrupted by a user through the CLI or Console. If not specified, a `SIGTERM` signal is sent to the process. | - -```yaml {configFile="app"} -crons: - mycommand: - spec: 'H * * * *' - commands: - start: sleep 60 && echo sleep-60-finished && date - stop: killall sleep - shutdown_timeout: 18 -``` -In this example configuration, the [cron specification](#crons) uses the `H` syntax. - -Note that this syntax is only supported on Grid and {{% names/dedicated-gen-3 %}} projects. -On {{% names/dedicated-gen-2 %}} projects, use the [standard cron syntax](https://en.wikipedia.org/wiki/Cron#Cron_expression). - -### Example cron jobs - - -{{< codetabs >}} - -+++ -title=Drupal -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -type: 'php:{{% latest "php" %}}' -crons: - # Run Drupal's cron tasks every 19 minutes. - drupal: - spec: '*/19 * * * *' - commands: - start: 'cd web ; drush core-cron' - # But also run pending queue tasks every 7 minutes. - # Use an odd number to avoid running at the same time as the `drupal` cron. - drush-queue: - spec: '*/7 * * * *' - commands: - start: 'cd web ; drush queue-run aggregator_feeds' -{{< /snippet >}} -``` - -<---> - -+++ -title=Ruby on Rails -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -type: 'ruby:{{% latest "ruby" %}}' -crons: - # Execute a rake script every 19 minutes. - ruby: - spec: '*/19 * * * *' - commands: - start: 'bundle exec rake some:task' -{{< /snippet >}} -``` - -<---> - -+++ -title=Laravel -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -type: 'php:{{% latest "php" %}}' -crons: - # Run Laravel's scheduler every 5 minutes. - scheduler: - spec: '*/5 * * * *' - commands: - start: 'php artisan schedule:run' -{{< /snippet >}} -``` - -<---> - -+++ -title=Symfony -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -type: 'php:{{% latest "php" %}}' -crons: - # Take a backup of the environment every day at 5:00 AM. - snapshot: - spec: 0 5 * * * - commands: - start: | - # Only run for the production environment, aka main branch - if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then - croncape symfony ... - fi -{{< /snippet >}} -``` - -{{< /codetabs >}} - - -### Conditional crons - -If you want to set up customized cron schedules depending on the environment type, -define conditional crons. -To do so, use a configuration similar to the following: - -```yaml {configFile="app"} -crons: - update: - spec: '0 0 * * *' - commands: - start: | - if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then - {{% vendor/cli %}} backup:create --yes --no-wait - {{% vendor/cli %}} source-operation:run update --no-wait --yes - fi -``` -### Cron job timing - -Minimum time between cron jobs being triggered: - -| Plan | Time | -|-------------------- | --------- | -| Professional | 5 minutes | -| Elite or Enterprise | 1 minute | - -For each app container, only one cron job can run at a time. -If a new job is triggered while another is running, the new job is paused until the other completes. - -To minimize conflicts, a random offset is applied to all triggers. -The offset is a random number of seconds up to 20 minutes or the cron frequency, whichever is smaller. - -Crons are also paused while activities such as [backups](/environments/backup.md) are running. -The crons are queued to run after the other activity finishes. - -To run cron jobs in a timezone other than UTC, set the [timezone property](#top-level-properties). - -### Paused crons - -[Preview environments](/glossary/_index.md#preview-environment) are often used for a limited time and then abandoned. -While it's useful for environments under active development to have scheduled tasks, -unused environments don't need to run cron jobs. -To minimize unnecessary resource use, -crons on environments with no deployments are paused. - -This affects all environments that aren't live environments. -This means all environments on Development plans -and all preview environments on higher plans. - -Such environments with deployments within 14 days have crons with the status `running`. -If there haven't been any deployments within 14 days, the status is `paused`. - -You can see the status in the Console -or using the CLI by running `{{% vendor/cli %}} environment:info` and looking under `deployment_state`. - -#### Restarting paused crons - -If the crons on your preview environment are paused but you're still using them, -you can push changes to the environment or redeploy it. - -To restart crons without changing anything: - -{{< codetabs >}} - -+++ -title=In the Console -+++ - -1. In the Console, navigate to your project. -1. Open the environment where you'd like the crons to run. -1. Click `Redeploy` next to the cron status of `Paused`. - -<---> - -+++ -title=Using the CLI -+++ - -Run the following command: - -```bash -{{% vendor/cli %}} redeploy -``` - -{{< /codetabs >}} - -## Runtime +## `runtime` {#runtime} The following table presents the various possible modifications to your PHP runtime: @@ -1267,30 +191,3 @@ The following table shows the properties that can be set in `sizing_hints`: | `reserved_memory` | `integer` | 70 | 70 | The amount of memory reserved in MB. | See more about [PHP-FPM workers and sizing](/languages/php/fpm.md). - -## Source - -The following table shows the properties that can be set in `source`: - - -| Name | Type | Required | Description | -| ------------ | ------------------------ | -------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `operations` | An operations dictionary | | Operations that can be applied to the source code. See [source operations](/create-apps/source-operations.md) | -| `root` | `string` | | The path where the app code lives. Defaults to the directory of the `{{< vendor/configfile "app" >}}` file. Useful for [multi-app setups](/create-apps/multi-app/_index.md). | - -## Additional hosts - -If you're using a private network with specific IP addresses you need to connect to, -you might want to map those addresses to hostnames to better remember and organize them. -In such cases, you can add a map of those IP addresses to whatever hostnames you like. -Then when your app tries to access the hostname, it's sent to the proper IP address. - -So in the following example, if your app tries to access `api.example.com`, it's sent to `192.0.2.23`. - -```yaml {configFile="app"} -additional_hosts: - api.example.com: "192.0.2.23" - web.example.com: "203.0.113.42" -``` - -This is equivalent to adding the mapping to the `/etc/hosts` file for the container. diff --git a/sites/platform/src/create-apps/image-properties/_index.md b/sites/platform/src/create-apps/image-properties/_index.md new file mode 100644 index 0000000000..0fea96b27a --- /dev/null +++ b/sites/platform/src/create-apps/image-properties/_index.md @@ -0,0 +1,11 @@ +--- +title: "Image properties" +weight: 4 +description: Details about image properties in the {{% vendor/name %}} config.yaml file +--- + +**Note:** The properties below are available in **both** [single-runtime image](/create-apps/app-reference/single-runtime-image.md#) and [composable image](/create-apps/app-reference/composable-image.md#) types. + +For most of these properties, the syntax and details are the same for both image types. Differences in meaning and syntax are noted as needed for each property. + +To learn about the properties that are **unique to each image type**, refer to the top-level properties described in the [single-runtime image](/create-apps/app-reference/single-runtime-image.md#) topic or the primary application properties described in the [composable image](/create-apps/app-reference/composable-image.md#) topic. diff --git a/sites/platform/src/create-apps/image-properties/access.md b/sites/platform/src/create-apps/image-properties/access.md new file mode 100644 index 0000000000..8bb0e6ec2f --- /dev/null +++ b/sites/platform/src/create-apps/image-properties/access.md @@ -0,0 +1,24 @@ +--- +title: "`access`" +weight: 4 +description: An access dictionary that defines the access control for roles accessing app environments. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#top-level-properties) and [composable](/create-apps/app-reference/composable-image.md#top-level-properties) images. + + +The `access` dictionary has one allowed key: + +| Name | Allowed values | Default | Description | +| ----- | ----------------------------------- | ------------- | ----------- | +| `ssh` | `admin`, `contributor`, or `viewer` | `contributor` | Defines the minimum role required to access app environments via SSH. | + +In the following example, only users with `admin` permissions for the given [environment type](/administration/users.md#environment-type-roles) +can access the deployed environment via SSH: + +```yaml {configFile="app"} +access: + ssh: admin +``` diff --git a/sites/platform/src/create-apps/image-properties/additional_hosts.md b/sites/platform/src/create-apps/image-properties/additional_hosts.md new file mode 100644 index 0000000000..e73a6e6529 --- /dev/null +++ b/sites/platform/src/create-apps/image-properties/additional_hosts.md @@ -0,0 +1,25 @@ +--- +title: "`additional_hosts`" +weight: 4 +description: An additional hosts dictionary that maps hostnames to IP addresses. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#top-level-properties) and [composable](/create-apps/app-reference/composable-image.md#top-level-properties) images. + +If you're using a private network with specific IP addresses you need to connect to, +you might want to map those addresses to hostnames to better remember and organize them. +In such cases, you can add a map of those IP addresses to whatever hostnames you like. +Then when your app tries to access the hostname, it's sent to the proper IP address. + +So in the following example, if your app tries to access `api.example.com`, it's sent to `192.0.2.23`. + +```yaml {configFile="app"} +additional_hosts: + api.example.com: "192.0.2.23" + web.example.com: "203.0.113.42" +``` + +This is equivalent to adding the mapping to the `/etc/hosts` file for the container. + diff --git a/sites/platform/src/create-apps/image-properties/crons.md b/sites/platform/src/create-apps/image-properties/crons.md new file mode 100644 index 0000000000..e707d9f98f --- /dev/null +++ b/sites/platform/src/create-apps/image-properties/crons.md @@ -0,0 +1,331 @@ +--- +title: "`crons`" +weight: 4 +description: A cron dictionary that defines scheduled tasks for the app. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#top-level-properties) and [composable](/create-apps/app-reference/composable-image.md#top-level-properties) images. + +The keys of the `crons` definition are the names of the cron jobs. +The names must be unique. + +If an application defines both a `web` instance and `worker` instances, cron jobs run only on the `web` instance. + +See how to [get cron logs](/increase-observability/logs/access-logs.md#container-logs). + +The following table shows the properties for each job: + +| Name | Type | Required | Description | +| ------------------ | -------------------------------------------- | -------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `spec` | `string` | Yes | The [cron specification](https://en.wikipedia.org/wiki/Cron#Cron_expression). To prevent competition for resources that might hurt performance, on **Grid** projects use `H` in definitions to indicate an unspecified but invariant time. For example, instead of using `0 * * * *` to indicate the cron job runs at the start of every hour, you can use `H * * * *` to indicate it runs every hour, but not necessarily at the start. This prevents multiple cron jobs from trying to start at the same time.

**Single-runtime image**: The `H` syntax is available on Grid projects only, and not on {{% names/dedicated-gen-2 %}} projects. | +| `commands` | A [cron commands dictionary](#cron-commands) | Yes | A definition of what commands to run when starting and stopping the cron job. | +| `shutdown_timeout` | `integer` | No | When a cron is canceled, this represents the number of seconds after which a `SIGKILL` signal is sent to the process to force terminate it. The default is `10` seconds. | +| `timeout` | `integer` | No | The maximum amount of time a cron can run before it's terminated. Defaults to the maximum allowed value of `86400` seconds (24 hours). + +Note that you can [cancel pending or running crons](/environments/cancel-activity.md). + +{{< note >}} + +The use of the `cmd` key is now deprecated in favor of the `commands`key.
+Make sure you set your new cron jobs using the `commands` key, +and update your existing cron jobs to ensure continuity. + +{{< /note >}} + +### Cron commands + +| Name | Type | Required | Description | +| ------------------ | --------- | -------- | ----------- | +| `start` | `string` | Yes | The command that's run. It's run in [Dash](https://en.wikipedia.org/wiki/Almquist_shell). | +| `stop` | `string` | No | The command that's issued to give the cron command a chance to shutdown gracefully, such as to finish an active item in a list of tasks. Issued when a cron task is interrupted by a user through the CLI or Console. If not specified, a `SIGTERM` signal is sent to the process. | + +```yaml {configFile="app"} +crons: + mycommand: + spec: 'H * * * *' + commands: + start: sleep 60 && echo sleep-60-finished && date + stop: killall sleep + shutdown_timeout: 18 +``` +In this example configuration, the crons [`spec`](#crons) uses the `H` syntax. + +Note that this syntax is only supported on Grid projects. +On {{% names/dedicated-gen-2 %}} projects, use the [standard cron syntax](https://en.wikipedia.org/wiki/Cron#Cron_expression). + +### Single-runtime image: Example cron jobs + + +{{< codetabs >}} + ++++ +title=Drupal ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +type: 'php:{{% latest "php" %}}' +crons: + # Run Drupal's cron tasks every 19 minutes. + drupal: + spec: '*/19 * * * *' + commands: + start: 'cd web ; drush core-cron' + # But also run pending queue tasks every 7 minutes. + # Use an odd number to avoid running at the same time as the `drupal` cron. + drush-queue: + spec: '*/7 * * * *' + commands: + start: 'cd web ; drush queue-run aggregator_feeds' +{{< /snippet >}} +``` + +<---> + ++++ +title=Ruby on Rails ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +type: 'ruby:{{% latest "ruby" %}}' +crons: + # Execute a rake script every 19 minutes. + ruby: + spec: '*/19 * * * *' + commands: + start: 'bundle exec rake some:task' +{{< /snippet >}} +``` + +<---> + ++++ +title=Laravel ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +type: 'php:{{% latest "php" %}}' +crons: + # Run Laravel's scheduler every 5 minutes. + scheduler: + spec: '*/5 * * * *' + commands: + start: 'php artisan schedule:run' +{{< /snippet >}} +``` + +<---> + ++++ +title=Symfony ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +type: 'php:{{% latest "php" %}}' +crons: + # Take a backup of the environment every day at 5:00 AM. + snapshot: + spec: 0 5 * * * + commands: + start: | + # Only run for the production environment, aka main branch + if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then + croncape symfony ... + fi +{{< /snippet >}} +``` + +{{< /codetabs >}} + + +### Composable image: Example cron jobs + + +{{< codetabs >}} + ++++ +title=Drupal ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +stack: [ "php@{{% latest php %}}" ] +crons: + # Run Drupal's cron tasks every 19 minutes. + drupal: + spec: '*/19 * * * *' + commands: + start: 'cd web ; drush core-cron' + # But also run pending queue tasks every 7 minutes. + # Use an odd number to avoid running at the same time as the `drupal` cron. + drush-queue: + spec: '*/7 * * * *' + commands: + start: 'cd web ; drush queue-run aggregator_feeds' +{{< /snippet >}} +``` + +<---> + ++++ +title=Ruby on Rails ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +stack: [ "ruby@{{% latest ruby %}}" ] +crons: + # Execute a rake script every 19 minutes. + ruby: + spec: '*/19 * * * *' + commands: + start: 'bundle exec rake some:task' +{{< /snippet >}} +``` + +<---> + ++++ +title=Laravel ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +stack: [ "php@{{% latest php %}}" ] +crons: + # Run Laravel's scheduler every 5 minutes. + scheduler: + spec: '*/5 * * * *' + commands: + start: 'php artisan schedule:run' +{{< /snippet >}} +``` + +<---> + ++++ +title=Symfony ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +stack: [ "php@{{% latest php %}}" ] +crons: + # Take a backup of the environment every day at 5:00 AM. + snapshot: + spec: 0 5 * * * + commands: + start: | + # Only run for the production environment, aka main branch + if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then + croncape symfony ... + fi +{{< /snippet >}} +``` + +{{< /codetabs >}} + + +### Conditional crons + +If you want to set up customized cron schedules depending on the environment type, +define conditional crons. +To do so, use a configuration similar to the following: + +```yaml {configFile="app"} +crons: + update: + spec: '0 0 * * *' + commands: + start: | + if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then + {{% vendor/cli %}} backup:create --yes --no-wait + {{% vendor/cli %}} source-operation:run update --no-wait --yes + fi +``` +### Cron job timing + +Minimum time between cron jobs being triggered: + +| Plan | Time | +|-------------------- | --------- | +| Professional | 5 minutes | +| Elite or Enterprise | 1 minute | + +For each app container, only one cron job can run at a time. +If a new job is triggered while another is running, the new job is paused until the other completes. + +To minimize conflicts, a random offset is applied to all triggers. +The offset is a random number of seconds up to 20 minutes or the cron frequency, whichever is smaller. + +Crons are also paused while activities such as [backups](/environments/backup.md) are running. +The crons are queued to run after the other activity finishes. + +To run cron jobs in a timezone other than UTC, set the `timezone` property as described for the image type ([single-runtime image](/create-apps/app-reference/single-runtime-image.md#top-level-properties) or +[composable image](/create-apps/app-reference/composable-image.md#top-level-properties)). + +### Paused crons + +[Preview environments](/glossary/_index.md#preview-environment) are often used for a limited time and then abandoned. +While it's useful for environments under active development to have scheduled tasks, +unused environments don't need to run cron jobs. +To minimize unnecessary resource use, +crons on environments with no deployments are paused. + +This affects all environments that aren't live environments. +This means all environments on Development plans +and all preview environments on higher plans. + +Such environments with deployments within 14 days have crons with the status `running`. +If there haven't been any deployments within 14 days, the status is `paused`. + +You can see the status in the Console +or using the CLI by running `{{% vendor/cli %}} environment:info` and looking under `deployment_state`. + +#### Restarting paused crons + +If the crons on your preview environment are paused but you're still using them, +you can push changes to the environment or redeploy it. + +To restart crons without changing anything: + +{{< codetabs >}} + ++++ +title=In the Console ++++ + +1. In the Console, navigate to your project. +1. Open the environment where you'd like the crons to run. +1. Click `Redeploy` next to the cron status of `Paused`. + +<---> + ++++ +title=Using the CLI ++++ + +Run the following command: + +```bash +{{% vendor/cli %}} redeploy +``` + +{{< /codetabs >}} + +### Composable image only: Sizing hints + +The following table shows the properties that can be set in `sizing_hints`: + +| Name | Type | Default | Minimum | Description | +|-------------------|-----------|---------|---------|------------------------------------------------| +| `request_memory` | `integer` | 45 | 10 | The average memory consumed per request in MB. | +| `reserved_memory` | `integer` | 70 | 70 | The amount of memory reserved in MB. | + +See more about [PHP-FPM workers and sizing](/languages/php/fpm.md). + diff --git a/sites/platform/src/create-apps/image-properties/disk.md b/sites/platform/src/create-apps/image-properties/disk.md new file mode 100644 index 0000000000..98eef2f202 --- /dev/null +++ b/sites/platform/src/create-apps/image-properties/disk.md @@ -0,0 +1,32 @@ +--- +title: "`disk`" +weight: 4 +description: An `integer` (or `null`) that defines the disk space allocated (in MB) to an app. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#top-level-properties) and [composable](/create-apps/app-reference/composable-image.md#top-level-properties) images. + +The maximum total space available to all apps and services is set by the storage in your plan settings. +When deploying your project, the sum of all `disk` keys defined in app and service configurations +must be *equal or less* than the plan storage size. + +So if your *plan storage size* is 5 GB, you can, for example, assign it in one of the following ways: + +- 2 GB to your app, 3 GB to your database +- 1 GB to your app, 4 GB to your database +- 1 GB to your app, 1 GB to your database, 3 GB to your OpenSearch service + +If you exceed the total space available, you receive an error on pushing your code. +You need to either increase your plan's storage or decrease the `disk` values you've assigned. + +You configure the disk size in [MB](/glossary/_index.md#mb). Your actual available disk space is slightly smaller with some space used for formatting and the filesystem journal. When checking available space, note whether it’s reported in MB or MiB. + +### Altering `disk` values + +It's a best practice to [back up your environment](/environments/backup.md) **before and after** you increase **or** decrease the `disk` value (the amount of allocated storage space) of an app or service. + +You can decrease the size of an existing disk for an app. If you do so, be aware that: +- Downsizing fails if the amount of data exceeds the configured `disk` value. +- Backups completed before the downsizing a disk are incompatible and can no longer be used to restore applications. You need to [create new backups](/environments/backup.md). diff --git a/sites/platform/src/create-apps/image-properties/firewall.md b/sites/platform/src/create-apps/image-properties/firewall.md new file mode 100644 index 0000000000..74db9c42f7 --- /dev/null +++ b/sites/platform/src/create-apps/image-properties/firewall.md @@ -0,0 +1,109 @@ +--- +title: "`firewall`" +weight: 4 +description: A firewall dictionary that defines the outbound firewall rules for the application. +--- + +{{< premium-features/tiered "Elite and Enterprise" >}} + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#top-level-properties) and [composable](/create-apps/app-reference/composable-image.md#top-level-properties) images. + +This property enables you to set limits in outbound traffic from your app with no impact on inbound requests. + +The `outbound` key is required and contains one or more rules. +The rules define what traffic is allowed; anything unspecified is blocked. + +Each rule has the following properties where at least one is required and `ips` and `domains` can't be specified together: + +| Name | Type | Default | Description | +| --------- |---------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `ips` | Array of `string`s | `["0.0.0.0/0"]` | IP addresses in [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing). See a [CIDR format converter](https://www.ipaddressguide.com/cidr). | +| `domains` | Array of `string`s | | [Fully qualified domain names](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) to specify specific destinations by hostname. | +| `ports` | Array of `integer`s | | Ports from 1 to 65535 that are allowed. If any ports are specified, all unspecified ports are blocked. If no ports are specified, all ports are allowed. Port `25`, the SMTP port for sending email, is always blocked. | + +The default settings would look like this: + +```yaml {configFile="app"} +firewall: + outbound: + - ips: ["0.0.0.0/0"] +``` + +### Support for rules + +Where outbound rules for firewalls are supported in all environments. +For {{% names/dedicated-gen-2 %}} projects, contact support for configuration. + +### Multiple rules + +Multiple firewall rules can be specified. +In such cases, a given outbound request is allowed if it matches _any_ of the defined rules. + +So in the following example requests to any IP on port 80 are allowed +and requests to 1.2.3.4 on either port 80 or 443 are allowed: + +```yaml {configFile="app"} +firewall: + outbound: + - ips: ["1.2.3.4/32"] + ports: [443] + - ports: [80] +``` + +### Outbound traffic to CDNs + +Be aware that many services are behind a content delivery network (CDN). +For most CDNs, routing is done via domain name, not IP address, +so thousands of domain names may share the same public IP addresses at the CDN. +If you allow the IP address of a CDN, you are usually allowing many or all of the other customers hosted behind that +CDN. + +### Outbound traffic by domain + +You can filter outbound traffic by domain. +Using domains in your rules rather than IP addresses is generally more specific and secure. +For example, if you use an IP address for a service with a CDN, +you have to allow the IP address for the CDN. +This means that you allow potentially hundreds or thousands of other servers also using the CDN. + +An example rule filtering by domain: + +```yaml {configFile="app"} +firewall: + outbound: + - protocol: tcp + domains: ["api.stripe.com", "api.twilio.com"] + ports: [80, 443] + - protocol: tcp + ips: ["1.2.3.4/29","2.3.4.5"] + ports: [22] +``` +#### Determine which domains to allow + +To determine which domains to include in your filtering rules, +find the domains your site has requested the DNS to resolve. +Run the following command to parse your server’s `dns.log` file +and display all Fully Qualified Domain Names that have been requested: + +```bash +awk '/query\[[^P]\]/ { print $6 | "sort -u" }' /var/log/dns.log +``` + +The output includes all DNS requests that were made, including those blocked by your filtering rules. +It doesn't include any requests made using an IP address. + +Example output: + +```bash +facebook.com +fastly.com +platform.sh +www.google.com +www.platform.sh +``` + + + + diff --git a/sites/platform/src/create-apps/image-properties/hooks.md b/sites/platform/src/create-apps/image-properties/hooks.md new file mode 100644 index 0000000000..85b9acdef7 --- /dev/null +++ b/sites/platform/src/create-apps/image-properties/hooks.md @@ -0,0 +1,103 @@ +--- +title: "`hooks`" +weight: 4 +description: A hooks dictionary that defines which commands run at different stages in the build and deploy process. +keywords: + - hooks + - hooks +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#top-level-properties) and [composable](/create-apps/app-reference/composable-image.md#top-level-properties) images. + +There are three different hooks that run as part of the process of building and deploying your app. +These are places where you can run custom scripts. +They are: the `build` hook, the `deploy` hook, and the `post_deploy` hook. +Only the `build` hook is run for [worker instances](/create-apps/image-properties/workers.md), while [web instances](/create-apps/image-properties/web.md) run all three. + +The process is ordered as: + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +1. Variables accessible at build time become available. +1. [Build flavor](/create-apps/app-reference/single-runtime-image.md#build) runs if applicable. +1. Any [dependencies](/create-apps/app-reference/single-runtime-image.md#dependencies) are installed. +1. The `build` hook is run. +1. The file system is changed to read only, except for any [mounts](/create-apps/image-properties/mounts.md). +1. The app container starts. Variables accessible at runtime and services become available. +1. The `deploy` hook is run. +1. The app container begins accepting requests. +1. The `post_deploy` hook is run. + +<---> + ++++ +title=Composable image ++++ + +1. Variables accessible at build time become available. +1. The `build` hook is run. +1. The file system is changed to read only, except for any [mounts](/create-apps/image-properties/mounts.md). +1. The app container starts. Variables accessible at runtime and services become available. +1. The `deploy` hook is run. +1. The app container begins accepting requests. +1. The `post_deploy` hook is run. + +{{< /codetabs >}} + +Note that if an environment changes by no code changes, only the last step is run. +If you want the entire process to run, see how +to [manually trigger builds](/development/troubleshoot.md#manually-trigger-builds). + +### Writable directories during build + +During the `build` hook, there are three writeable directories: + +- `PLATFORM_APP_DIR`: + Where your code is checked out and the working directory when the `build` hook starts. + Becomes the app that gets deployed. +- `PLATFORM_CACHE_DIR`: + Persists between builds, but isn't deployed. + Shared by all builds on all branches. +- `/tmp`: + Isn't deployed and is wiped between each build. + Note that `PLATFORM_CACHE_DIR` is mapped to `/tmp` + and together they offer about 8GB of free space. + +### Hook failure + +Each hook is executed as a single script, so they're considered to have failed only if the final command in them fails. +To cause them to fail on the first failed command, add `set -e` to the beginning of the hook. + +If a `build` hook fails for any reason, the build is aborted and the deploy doesn't happen. +Note that this only works for `build` hooks -- +if other hooks fail, the app is still deployed. + +#### Automated testing + +It’s preferable that you set up and run automated tests in a dedicated CI/CD tool. +Relying on {{% vendor/name %}} hooks for such tasks can prove difficult. + +During the `build` hook, you can halt the deployment on a test failure but the following limitations apply: + +- Access to services such as databases, Redis, Vault KMS, and even writable mounts is disabled. + So any testing that relies on it is sure to fail. +- If you haven’t made changes to your app, an existing build image is reused and the build hook isn’t run. +- Test results are written into your app container, so they might get exposed to a third party. + +During the `deploy` hook, you can access services but **you can’t halt the deployment based on a test failure**. +Note that there are other downsides: + +- Your app container is read-only during the deploy hook, + so if your tests need to write reports and other information, you need to create a file mount for them. +- Your app can only be deployed once the deploy hook has been completed. + Therefore, running automated testing via the deploy hook generates slower deployments. +- Your environment isn’t available externally during the deploy hook. + Unit and integration testing might work without the environment being available, + but you can’t typically perform end-to-end testing until after the environment is up and available. + diff --git a/sites/platform/src/create-apps/image-properties/mounts.md b/sites/platform/src/create-apps/image-properties/mounts.md new file mode 100644 index 0000000000..b6704d3120 --- /dev/null +++ b/sites/platform/src/create-apps/image-properties/mounts.md @@ -0,0 +1,154 @@ +--- +title: "`mounts`" +weight: 4 +description: Defines the directories that are writable even after the app is built. +--- + +{{% description %}} If set as a local source, disk is required. + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#top-level-properties) and [composable](/create-apps/app-reference/composable-image.md#top-level-properties) images. + +After your app is built, its file system is read-only. +To make changes to your app's code, you need to use Git. + +For enhanced flexibility, {{% vendor/name %}} allows you to define and use writable directories called "mounts". +Mounts give you write access to files generated by your app (such as cache and log files) +and uploaded files without going through Git. + +When you define a mount, you are mounting an external directory to your app container, +much like you would plug a hard drive into your computer to transfer data. + +{{% note %}} + +- Mounts aren't available during the build +- When you [back up an environment](/environments/backup.md), the mounts on that environment are backed up too + +{{% /note %}} + +### Define a mount + +To define a mount, use the following configuration: + +```yaml {configFile="app"} +mounts: + '{{< variable "MOUNT_PATH" >}}': + source: {{< variable "MOUNT_TYPE" >}} + source_path: {{< variable "SOURCE_PATH_LOCATION" >}} +``` + +{{< variable "MOUNT_PATH" >}} is the path to your mount **within the app container** (relative to the app's root). +If you already have a directory with that name, you get a warning that it isn't accessible after the build. +See how to [troubleshoot the warning](/create-apps/troubleshoot-mounts.md#overlapping-folders). + +| Name | Type | Required | Description | +| ------------- |-------------------------------| -------- |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `source` | `local`, `service`, or `tmp` | Yes | Specifies the type of the mount:

- `local` mounts are unique to your app. They can be useful to store files that remain local to the app instance, such as application logs.
`local` mounts require disk space. To successfully set up a local mount, set the `disk` key in your app configuration.

- `service` mounts point to [Network Storage](/add-services/network-storage.md) services that can be shared between several apps.

- `tmp` mounts are local ephemeral mounts, where an external directory is mounted to the `/tmp` directory of your app.
The content of a `tmp` mount **may be removed during infrastructure maintenance operations**. Therefore, `tmp` mounts allow you to **store files that you’re not afraid to lose**, such as your application cache that can be seamlessly rebuilt.
Note that the `/tmp` directory has **a maximum allocation of 8 GB**. | +| `source_path` | `string` | No | Specifies where the mount points **inside the [external directory](#mounts)**.

- If you explicitly set a `source_path`, your mount points to a specific subdirectory in the external directory.

- If the `source_path` is an empty string (`""`), your mount points to the entire external directory.

- If you don't define a `source_path`, {{% vendor/name %}} uses the {{< variable "MOUNT_PATH" >}} as default value, without leading or trailing slashes.
For example, if your mount lives in the `/web/uploads/` directory in your app container, it will point to a directory named `web/uploads` in the external directory.

**WARNING:** Changing the name of your mount affects the `source_path` when it's undefined. See [how to ensure continuity](#ensure-continuity-when-changing-the-name-of-your-mount) and maintain access to your files. | +| `service` | `string` | | Only for `service` mounts: the name of the [Network Storage service](/add-services/network-storage.md). | + + +The accessibility to the web of a mounted directory depends on the [`web.locations` configuration](/create-apps/image-properties/web.md). +Files can be all public, all private, or with different rules for different paths and file types. + +Note that when you remove a `local` mount from your `{{< vendor/configfile "app" >}}` file, +the mounted directory isn't deleted. +The files still exist on disk until manually removed +(or until the app container is moved to another host during a maintenance operation in the case of a `tmp` mount). + +### Example configuration + +```yaml {configFile="app"} +mounts: + 'web/uploads': + source: local + source_path: uploads + '/.tmp_platformsh': + source: tmp + source_path: files/.tmp_platformsh + '/build': + source: local + source_path: files/build + '/.cache': + source: tmp + source_path: files/.cache + '/node_modules/.cache': + source: tmp + source_path: files/node_modules/.cache +``` + +For examples of how to set up a `service` mount, see the dedicated [Network Storage page](/add-services/network-storage.md). + +### Ensure continuity when changing the name of your mount + +Changing the name of your mount affects the default `source_path`. + +Say you have a `/my/cache/` mount with an undefined `source_path`: + +```yaml {configFile="app"} +mounts: + '/my/cache/': + source: tmp +``` + +If you rename the mount to `/cache/files/`, it will point to a new, empty `/cache/files/` directory. + +To ensure continuity, you need to explicitly define the `source_path` as the previous name of the mount, without leading or trailing slashes: + + ```yaml {configFile="app"} +mounts: + '/cache/files/': + source: tmp + source_path: my/cache +``` + +The `/cache/files/` mount will point to the original `/my/cache/` directory, maintaining access to all your existing files in that directory. + +### Overlapping mounts + +The locations of mounts as they are visible to application containers can overlap somewhat. +For example: + +```yaml {configFile="apps"} +applications: + myapp: + # ... + mounts: + 'var/cache_a': + source: service + service: ns_service + source_path: cacheA + 'var/cache_b': + source: tmp + source_path: cacheB + 'var/cache_c': + source: local + source_path: cacheC +``` + +In this case, it does not matter that each mount is of a different `source` type. +Each mount is restricted to a subfolder within `var`, and all is well. + +The following, however, is not allowed and will result in a failure: + +```yaml {configFile="apps"} +applications: + myapp: + # ... + mounts: + 'var/': + source: service + service: ns_service + source_path: cacheA + 'var/cache_b': + source: tmp + source_path: cacheB + 'var/cache_c': + source: local + source_path: cacheC +``` + +The `service` mount type specifically exists to share data between instances of the same application, whereas `tmp` and `instance` are meant to restrict data to build time and runtime of a single application instance, respectively. +These allowances are not compatible, and will result in an error if pushed. + + + diff --git a/sites/platform/src/create-apps/image-properties/relationships.md b/sites/platform/src/create-apps/image-properties/relationships.md new file mode 100644 index 0000000000..3864e2bb7d --- /dev/null +++ b/sites/platform/src/create-apps/image-properties/relationships.md @@ -0,0 +1,187 @@ +--- +title: "`relationships`" +weight: 4 +description: A dictionary of relationships that defines the connections to other services and apps. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#top-level-properties) and [composable](/create-apps/app-reference/composable-image.md#top-level-properties) images. + +To allow containers in your project to communicate with one another, +you need to define relationships between them. +You can define a relationship between an app and a service, or [between two apps](/create-apps/multi-app/relationships.md). + +The quickest way to define a relationship between your app and a service +is to use the service's default endpoint.
+However, some services allow you to define multiple databases, cores, and/or permissions. +In these cases, you can't rely on default endpoints. +Instead, you can explicitly define multiple endpoints when setting up your relationships. + +{{< note >}} +App containers don't have a default endpoint like services. +To connect your app to another app in your project, +you need to explicitly define the `http` endpoint as the endpoint to connect both apps.
+For more information, see how to [define relationships between your apps](/create-apps/multi-app/relationships.md). +{{< /note >}} + +{{< note title="Availability" theme="info">}} + +New syntax (default and explicit endpoints) described below is supported by most, but not all, image types +(`Relationship 'SERVICE_NAME' of application 'myapp' ... targets a service without a valid default endpoint configuration.`). +This syntax is currently being rolled out for all images. +If you encounter this error, use the "legacy" {{% vendor/name %}} configuration noted at the bottom of this section. + +{{< /note >}} + +To define a relationship between your app and a service: + +{{< codetabs >}} + ++++ +title=Using default endpoints ++++ + +Use the following configuration: + +```yaml {configFile="app"} +relationships: + {{% variable "SERVICE_NAME" %}}: +``` + +The `SERVICE_NAME` is the name of the service as defined in its [configuration](/add-services/_index.md). +It is used as the relationship name, and associated with a `null` value. +This instructs {{% vendor/name %}} to use the service's default endpoint to connect your app to the service. + +For example, if you define the following configuration: + +```yaml {configFile="app"} +relationships: + mariadb: +``` + +{{% vendor/name %}} looks for a service named `mariadb` in your `{{% vendor/configfile "services" %}}` file, +and connects your app to it through the service's default endpoint. + +For reference, the equivalent configuration using explicit endpoints would be the following: + +```yaml {configFile="app"} +relationships: + mariadb: + service: mariadb + endpoint: mysql +``` + +You can define any number of relationships in this way: + +```yaml {configFile="app"} +relationships: + mariadb: + redis: + elasticsearch: +``` + +{{< note title="Tip" theme="info" >}} + +An even quicker way to define many relationships is to use the following single-line configuration: + +```yaml {configFile="app"} +relationships: {{{< variable "SERVICE_NAME_A" >}}, {{< variable "SERVICE_NAME_B" >}}, {{< variable "SERVICE_NAME_C" >}}} +``` + +where + +```yaml {configFile="services"} +{{< variable "SERVICE_NAME_A" >}}: + type: mariadb:{{% latest "mariadb" %}} + disk: 256 +{{< variable "SERVICE_NAME_B" >}}: + type: redis:{{% latest "redis" %}} + disk: 256 +{{< variable "SERVICE_NAME_C" >}}: + type: elasticsearch:{{% latest "elasticsearch" %}} + disk: 256 +``` + +{{< /note >}} + +<---> + ++++ +title=Using explicit endpoints ++++ + +Use the following configuration: + +```yaml {configFile="app"} +relationships: + {{% variable "RELATIONSHIP_NAME" %}}: + service: {{% variable "SERVICE_NAME" %}} + endpoint: {{% variable "ENDPOINT_NAME" %}} +``` + +- `RELATIONSHIP_NAME` is the name you want to give to the relationship. +- `SERVICE_NAME` is the name of the service as defined in its [configuration](/add-services/_index.md). +- `ENDPOINT_NAME` is the endpoint your app will use to connect to the service (refer to the service reference to know which value to use). + +For example, to define a relationship named `database` that connects your app to a service called `mariadb` through the `db1` endpoint, +use the following configuration: + +```yaml {configFile="app"} +relationships: + database: # The name of the relationship. + service: mariadb + endpoint: db1 +``` + +For more information on how to handle multiple databases, multiple cores, +and/or different permissions with services that support such features, +see each service's dedicated page: + + - [MariaDB/MySQL](/add-services/mysql/_index.md#multiple-databases) (multiple databases and permissions) + - [PostgreSQL](/add-services/postgresql/_index.md#multiple-databases) (multiple databases and permissions) + - [Redis](/add-services/redis/_index.md#multiple-databases) (multiple databases) + - [Solr](add-services/solr/_index.md#solr-6-and-later) (multiple cores) + - [Vault KMS](add-services/vault.md#multiple-endpoints-configuration) (multiple permissions) + + You can add as many relationships as you want to your app configuration, + using both default and explicit endpoints according to your needs: + +```yaml {configFile="app"} +relationships: + database1: + service: mariadb + endpoint: admin + database2: + service: mariadb + endpoint: legacy + cache: + service: redis + search: + service: elasticsearch +``` + +{{< /codetabs >}} + +{{< note theme="info" title="Legacy" >}} + +The following legacy syntax for specifying relationships is still supported by {{% vendor/name %}}: + +```yaml {configFile="app"} +relationships: + : ":" +``` + +For example: + +```yaml {configFile="app"} +relationships: + database: "mariadb:mysql" +``` + +Feel free to use this until the default and explicit endpoint syntax is supported on all images. + +{{< /note >}} + + + diff --git a/sites/platform/src/create-apps/image-properties/size.md b/sites/platform/src/create-apps/image-properties/size.md new file mode 100644 index 0000000000..6acdb752df --- /dev/null +++ b/sites/platform/src/create-apps/image-properties/size.md @@ -0,0 +1,123 @@ +--- +title: "`size`" +weight: 4 +description: Defines the amount of resources to dedicate to the app. +keywords: + - resource sizing +--- + + + +{{% description %}} Defaults to `AUTO` in production environments. + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#top-level-properties) and [composable](/create-apps/app-reference/composable-image.md#top-level-properties) images. + +Resources are distributed across all containers in an environment from the total available from your [plan size](/administration/pricing/_index.md). +So if you have more than just a single app, it doesn't get all of the resources available. +Each environment has its own resources and there are different [sizing rules for preview environments](#sizes-in-preview-environments). + +By default, resource sizes (CPU and memory) are chosen automatically for an app +based on the plan size and the number of other containers in the cluster. +Most of the time, this automatic sizing is enough. + +You can set sizing suggestions for production environments when you know a given container has specific needs. +Such as a worker that doesn't need much and can free up resources for other apps. +To do so, set `size` to one of the following values: + +- `S` +- `M` +- `L` +- `XL` +- `2XL` +- `4XL` + +The total resources allocated across all apps and services can't exceed what's in your plan. + +### Container profiles: CPU and memory + +By default, {{% vendor/name %}} allocates a container profile to each app and service depending on: + +- The range of resources it’s expected to need +- Your [plan size](/administration/pricing/_index.md), as resources are distributed across containers. + Ideally you want to give databases the biggest part of your memory, and apps the biggest part of your CPU. + +The container profile and the [size of the container](#sizes) determine +how much CPU and memory (in [MB](/glossary/_index.md#mb)) the container gets. + +There are three container profiles available: ``HIGH_CPU``, ``BALANCED``, and ``HIGH_MEMORY``. + +#### ``HIGH_CPU`` container profile + +| Size | CPU | MEMORY | +| ---- | ----- | -------- | +| S | 0.40 | 128 MB | +| M | 0.40 | 128 MB | +| L | 1.20 | 256 MB | +| XL | 2.50 | 384 MB | +| 2XL | 5.00 | 768 MB | +| 4XL | 10.00 | 1536 MB | + +#### `BALANCED` container profile + +| Size | CPU | MEMORY | +| ---- | ---- | -------- | +| S | 0.05 | 32 MB | +| M | 0.05 | 64 MB | +| L | 0.08 | 256 MB | +| XL | 0.10 | 512 MB | +| 2XL | 0.20 | 1024 MB | +| 4XL | 0.40 | 2048 MB | + +#### `HIGH_MEMORY` container profile + +| Size | CPU | MEMORY | +| ---- | ---- | --------- | +| S | 0.25 | 128 MB | +| M | 0.25 | 288 MB | +| L | 0.40 | 1280 MB | +| XL | 0.75 | 2624 MB | +| 2XL | 1.50 | 5248 MB | +| 4XL | 3.00 | 10496 MB | + +#### Container profile reference + +The following table shows which container profiles {{% vendor/name %}} applies when deploying your project. + +| Container | Profile | +|-----------------------|-------------| +| Chrome Headless | HIGH_CPU | +| .NET | HIGH_CPU | +| Elasticsearch | HIGH_MEMORY | +| Elasticsearch Premium | HIGH_MEMORY | +| Elixir | HIGH_CPU | +| Go | HIGH_CPU | +| Gotenberg | HIGH_MEMORY | +| InfluxDB | HIGH_MEMORY | +| Java | HIGH_MEMORY | +| Kafka | HIGH_MEMORY | +| MariaDB | HIGH_MEMORY | +| Memcached | BALANCED | +| MongoDB | HIGH_MEMORY | +| MongoDB Premium | HIGH_MEMORY | +| Network Storage | HIGH_MEMORY | +| Node.js | HIGH_CPU | +| OpenSearch | HIGH_MEMORY | +| Oracle MySQL | HIGH_MEMORY | +| PHP | HIGH_CPU | +| PostgreSQL | HIGH_MEMORY | +| Python | HIGH_CPU | +| RabbitMQ | HIGH_MEMORY | +| Redis ephemeral | BALANCED | +| Redis persistent | BALANCED | +| Ruby | HIGH_CPU | +| Rust | HIGH_CPU | +| Solr | HIGH_MEMORY | +| Varnish | HIGH_MEMORY | +| Vault KMS | HIGH_MEMORY | + +### Sizes in preview environments + +Containers in preview environments don't follow the `size` specification. +Application containers are set based on the plan's setting for **Environments application size**. +The default is size **S**, but you can increase it by editing your plan. +(Service containers in preview environments are always set to size **S**.) diff --git a/sites/platform/src/create-apps/image-properties/source.md b/sites/platform/src/create-apps/image-properties/source.md new file mode 100644 index 0000000000..c310285495 --- /dev/null +++ b/sites/platform/src/create-apps/image-properties/source.md @@ -0,0 +1,17 @@ +--- +title: "`source`" +weight: 4 +description: Contains information about the app’s source code and operations that can be run on it. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#top-level-properties) and [composable](/create-apps/app-reference/composable-image.md#top-level-properties) images. + +The following table shows the properties that can be set in `source`: + + +| Name | Type | Required | Description | +| ------------ | ------------------------ | -------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `operations` | An operations dictionary | | Operations that can be applied to the source code. See [source operations](/create-apps/source-operations.md). | +| `root` | `string` | | The path where the app code lives. Useful for [multi-app setups](/create-apps/multi-app/_index.md).
**Single-runtime image**: Defaults to the directory of the `{{< vendor/configfile "app" >}}` file.
**Composable image**: Defaults to the root project directory. | diff --git a/sites/platform/src/create-apps/image-properties/variables.md b/sites/platform/src/create-apps/image-properties/variables.md new file mode 100644 index 0000000000..e962bff8c8 --- /dev/null +++ b/sites/platform/src/create-apps/image-properties/variables.md @@ -0,0 +1,37 @@ +--- +title: "`variables`" +weight: 4 +description: A variables dictionary that defines variables to control the environment. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#top-level-properties) and [composable](/create-apps/app-reference/composable-image.md#top-level-properties) images. + +{{% vendor/name %}} provides a number of ways to set [variables](/development/variables/_index.md). +Variables set in your app configuration have the lowest precedence, +meaning they're overridden by any conflicting values provided elsewhere. + +All variables set in your app configuration must have a prefix. +Some [prefixes have specific meanings](/development/variables/_index.md#variable-prefixes). + +Variables with the prefix `env` are available as a separate environment variable. +All other variables are available in the [`PLATFORM_VARIABLES` environment variable](/development/variables/use-variables.md#use-provided-variables). + +The following example sets two variables: + +- A variable named `env:AUTHOR` with the value `Juan` that's available in the environment as `AUTHOR` +- A variable named `d8config:system.site:name` with the value `My site rocks` + that's available in the `PLATFORM_VARIABLES` environment variable + +```yaml {configFile="app"} +variables: + env: + AUTHOR: 'Juan' + d8config: + "system.site:name": 'My site rocks' +``` + +You can also define and access more [complex values](/development/variables/use-variables.md#access-complex-values). + + diff --git a/sites/platform/src/create-apps/image-properties/web.md b/sites/platform/src/create-apps/image-properties/web.md new file mode 100644 index 0000000000..166127345d --- /dev/null +++ b/sites/platform/src/create-apps/image-properties/web.md @@ -0,0 +1,165 @@ +--- +title: "`web`" +weight: 4 +description: A web instance that defines how the web application is served. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#top-level-properties) and [composable](/create-apps/app-reference/composable-image.md#top-level-properties) images. + +Use the `web` key to configure the web server running in front of your app. +In single-runtime images, defaults may vary with a different [image `type`](/create-apps/app-reference/single-runtime-image.md#types). + +| Name | Type | Required | Description | +|-------------|--------------------------------------------|-------------------------------|------------------------------------------------------| +| `commands` | A [web commands dictionary](/create-apps/image-properties/web.md#web-commands) | See [note](#required-command) | The command to launch your app. | +| `upstream` | An [upstream dictionary](#upstream) | | How the front server connects to your app. | +| `locations` | A [locations dictionary](#locations) | | How the app container responds to incoming requests. | + +See some [examples of how to configure what's served](/create-apps/web/_index.md). + +### Web commands + + +| Name | Type | Required | Description | +|--------------|----------|-------------------------------|-----------------------------------------------------------------------------------------------------| +| `pre_start` | `string` | | Command run just prior to `start`, which can be useful when you need to run _per-instance_ actions. | +| `start` | `string` | See [note](#required-command) | The command to launch your app. If it terminates, it's restarted immediately. | +| `post_start` | `string` | | Command runs **before** adding the container to the router and **after** the `start` command. | + +{{< note theme="info" >}} +The `post_start` feature is _experimental_ and may change. Please share your feedback in the +[{{% vendor/name %}} discord](https://discord.gg/platformsh). +{{< /note >}} + + +Example: + +```yaml {configFile="app"} +web: + commands: + start: 'uwsgi --ini conf/server.ini' +``` + +This command runs every time your app is restarted, regardless of whether or not new code is deployed. + +{{< note >}} + +Never "background" a start process using `&`. +That's interpreted as the command terminating and the supervisor process starts a second copy, +creating an infinite loop until the container crashes. +Just run it as normal and allow the {{% vendor/name %}} supervisor to manage it. + +{{< /note >}} + +#### Required command + +On all containers other than PHP, the value for `start` should be treated as required. + +On PHP containers, it's optional and defaults to starting PHP-FPM (`/usr/bin/start-php-app`). +It can also be set explicitly on a PHP container to run a dedicated process, +such as [React PHP](https://github.com/platformsh-examples/platformsh-example-reactphp) +or [Amp](https://github.com/platformsh-examples/platformsh-example-amphp). +See how to set up [alternate start commands on PHP](/languages/php/_index.md#alternate-start-commands). + +### Upstream + +| Name | Type | Required | Description | Default | +| --------------- |---------------------| -------- |-------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------| +| `socket_family` | `tcp` or `unix` | | Whether your app listens on a Unix or TCP socket. | **Single-runtime image**: Defaults to `tcp` for all [image types](/create-apps/app-reference/single-runtime-image.md#types) except PHP; for PHP image types the default is `unix`.
**Composable image**: Defaults to `tcp` for all [primary runtimes](/create-apps/app-reference/composable-image.md#primary-runtime) except PHP; for PHP the default is `unix`.| +| `protocol` | `http` or `fastcgi` | | Whether your app receives incoming requests over HTTP or FastCGI. | **Single-runtime image**: Default varies based on [image `type`](/create-apps/app-reference/single-runtime-image.md#types).
**Composable image**: Default varies based on the [primary runtimes](/create-apps/app-reference/composable-image.md#primary-runtime). | + +For PHP, the defaults are configured for PHP-FPM and shouldn't need adjustment. +For all other containers, the default for `protocol` is `http`. + +The following example is the default on non-PHP containers: + +```yaml {configFile="app"} +web: + upstream: + socket_family: tcp + protocol: http +``` +#### Where to listen + +Where to listen depends on your setting for `web.upstream.socket_family` (defaults to `tcp`). + +| `socket_family` | Where to listen | +|------------------|---------------------------------------------------------------------------------------------------------------------------------------| +| `tcp` | The port specified by the [`PORT` environment variable](/development/variables/use-variables.md#use-provided-variables) | +| `unix` | The Unix socket file specified by the [`SOCKET` environment variable](/development/variables/use-variables.md#use-provided-variables) | + +If your application isn't listening at the same place that the runtime is sending requests, +you see `502 Bad Gateway` errors when you try to connect to your website. + +### Locations + +Each key in the `locations` dictionary is a path on your site with a leading `/`. +For `example.com`, a `/` matches `example.com/` and `/admin` matches `example.com/admin`. +When multiple keys match an incoming request, the most-specific applies. + +The following table presents possible properties for each location: + +| Name | Type | Default | Description | +| ------------------- | ---------------------------------------------------- |------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `root` | `string` | | The directory to serve static assets for this location relative to the app's root directory ([single-runtime image](/create-apps/app-reference/single-runtime-image.md#root-directory); [composable image](/create-apps/app-reference/composable-image.md#primary-runtime)). Must be an actual directory inside the root directory. | +| `passthru` | `boolean` or `string` | `false` | Whether to forward disallowed and missing resources from this location to the app. A string is a path with a leading `/` to the controller, such as `/index.php`.

If your app is in PHP, when setting `passthru` to `true`, you might want to set `scripts` to `false` for enhanced security. This prevents PHP scripts from being executed from the specified location. You might also want to set `allow` to `false` so that not only PHP scripts can't be executed, but their source code also can't be delivered. | +| `index` | Array of `string`s or `null` | | Files to consider when serving a request for a directory. When set, requires access to the files through the `allow` or `rules` keys. | +| `expires` | `string` | `-1` | How long static assets are cached. The default means no caching. Setting it to a value enables the `Cache-Control` and `Expires` headers. Times can be suffixed with `ms` = milliseconds, `s` = seconds, `m` = minutes, `h` = hours, `d` = days, `w` = weeks, `M` = months/30d, or `y` = years/365d.
**Additionally, for single-runtime image only:** If a `Cache-Control` appears on the `headers` configuration, `expires`, if set, will be ignored. Thus, make sure to set the `Cache-Control`'s `max-age` value when specifying a header. | +| `allow` | `boolean` | `true` | Whether to allow serving files which don't match a rule. | +| `scripts` | `boolean` | | Whether to allow scripts to run. Doesn't apply to paths specified in `passthru`. Meaningful only on PHP containers. | +| `headers` | A headers dictionary | | Any additional headers to apply to static assets, mapping header names to values (see [Set custom headers on static content](/create-apps/web/custom-headers.html)). Responses from the app aren't affected. | +| `request_buffering` | A [request buffering dictionary](#request-buffering) | See below | Handling for chunked requests. | +| `rules` | A [rules dictionary](#rules) | | Specific overrides for specific locations. | + +#### Rules + +The rules dictionary can override most other keys according to a regular expression. +The key of each item is a regular expression to match paths exactly. +If an incoming request matches the rule, it's handled by the properties under the rule, +overriding any conflicting rules from the rest of the `locations` dictionary. + +Under `rules`, you can set all the other possible [`locations` properties](#locations) +except `root`, `index`, `rules` and `request_buffering`. + +In the following example, the `allow` key disallows requests for static files anywhere in the site. +This is overridden by a rule that explicitly allows common image file formats. + +```yaml {configFile="app"} +web: + locations: + '/': + # Handle dynamic requests + root: 'public' + passthru: '/index.php' + # Disallow static files + allow: false + rules: + # Allow common image files only. + '\.(jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff2?|otf|ttf)$': + allow: true +``` +#### Request buffering + +Request buffering is enabled by default to handle chunked requests as most app servers don't support them. +The following table shows the keys in the `request_buffering` dictionary: + +| Name | Type | Required | Default | Description | +| ------------------ | --------- |----------| ------- |-------------------------------------------| +| `enabled` | `boolean` | Yes | `true` | Whether request buffering is enabled. | +| `max_request_size` | `string` | | `250m` | The maximum size to allow in one request. | + +The default configuration would look like this: + +```yaml {configFile="app"} +web: + locations: + '/': + passthru: true + request_buffering: + enabled: true + max_request_size: 250m +``` + + diff --git a/sites/platform/src/create-apps/image-properties/workers.md b/sites/platform/src/create-apps/image-properties/workers.md new file mode 100644 index 0000000000..f545d22c56 --- /dev/null +++ b/sites/platform/src/create-apps/image-properties/workers.md @@ -0,0 +1,39 @@ +--- +title: "`workers`" +weight: 4 +description: Defines the list of worker names, which are alternate copies of the application to run as background processes. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#top-level-properties) and [composable](/create-apps/app-reference/composable-image.md#top-level-properties) images. + +Workers are exact copies of the code and compilation output as a `web` instance after a [`build` hook](/create-apps/image-properties/hooks.md). +They use the same container image. + +Workers can't accept public requests and so are suitable only for background tasks. +If they exit, they're automatically restarted. + +The keys of the `workers` definition are the names of the workers. +You can then define how each worker differs from the `web` instance using +the top-level properties (see details for [single-runtime image](/create-apps/app-reference/single-runtime-image.md#top-level-properties) or [composable image](/create-apps/app-reference/composable-image.md#top-level-properties) top-level properties). + +Each worker can differ from the `web` instance in all properties _except_ for: + +- `build` and `dependencies` properties, which must be the same +- `crons` as cron jobs don't run on workers +- `hooks` as the `build` hook must be the same + and the `deploy` and `post_deploy` hooks don't run on workers. + +A worker named `queue` that was small and had a different start command could look like this: + +```yaml {configFile="app"} +workers: + queue: + size: S + commands: + start: | + ./worker.sh +``` + +For resource allocation, using workers in your project requires a [{{< partial "plans/multiapp-plan-name" >}} plan or larger](https://platform.sh/pricing/). diff --git a/sites/platform/src/create-apps/multi-app/_index.md b/sites/platform/src/create-apps/multi-app/_index.md index dc6ce6ab82..6ee2c5e39e 100644 --- a/sites/platform/src/create-apps/multi-app/_index.md +++ b/sites/platform/src/create-apps/multi-app/_index.md @@ -5,7 +5,7 @@ description: Create multiple apps within a single project, such as a CMS backend banner: title: Feature availability type: tiered-feature - body: This page applies to Grid and {{% names/dedicated-gen-3 %}} projects. To ensure you have enough resources to support multiple apps, you need at least a [{{< partial "plans/multiapp-plan-name" >}} plan](/administration/pricing/_index.md#multiple-apps-in-a-single-project). To set up multiple apps on {{% names/dedicated-gen-2 %}} environments, [contact Sales](https://platform.sh/contact/). + body: This page applies to Grid projects. To ensure you have enough resources to support multiple apps, you need at least a [{{< partial "plans/multiapp-plan-name" >}} plan](/administration/pricing/_index.md#multiple-apps-in-a-single-project). To set up multiple apps on {{% names/dedicated-gen-2 %}} environments, [contact Sales](https://platform.sh/contact/). weight: 8 --- diff --git a/sites/platform/src/create-apps/multi-app/project-structure.md b/sites/platform/src/create-apps/multi-app/project-structure.md index 1f35a4cca8..59404cd8e8 100644 --- a/sites/platform/src/create-apps/multi-app/project-structure.md +++ b/sites/platform/src/create-apps/multi-app/project-structure.md @@ -5,7 +5,7 @@ description: Explore possible code structures you can apply to your multiple app banner: title: Feature availability type: tiered-feature - body: This page applies to Grid and {{% names/dedicated-gen-3 %}} projects. To ensure you have enough resources to support multiple apps, you need at least a [{{< partial "plans/multiapp-plan-name" >}} plan](/administration/pricing/_index.md#multiple-apps-in-a-single-project). To set up multiple apps on {{% names/dedicated-gen-2 %}} environments, [contact Sales](https://platform.sh/contact/). + body: This page applies to Grid projects. To ensure you have enough resources to support multiple apps, you need at least a [{{< partial "plans/multiapp-plan-name" >}} plan](/administration/pricing/_index.md#multiple-apps-in-a-single-project). To set up multiple apps on {{% names/dedicated-gen-2 %}} environments, [contact Sales](https://platform.sh/contact/). --- How you structure a project with multiple apps depends on how your code is organized diff --git a/sites/platform/src/create-apps/multi-app/relationships.md b/sites/platform/src/create-apps/multi-app/relationships.md index f4e516ed12..36a68bccbd 100644 --- a/sites/platform/src/create-apps/multi-app/relationships.md +++ b/sites/platform/src/create-apps/multi-app/relationships.md @@ -6,7 +6,7 @@ description: Find out how relationships are managed between your apps. banner: title: Feature availability type: tiered-feature - body: This page applies to Grid and {{% names/dedicated-gen-3 %}} projects. To ensure you have enough resources to support multiple apps, you need at least a [{{< partial "plans/multiapp-plan-name" >}} plan](/administration/pricing/_index.md#multiple-apps-in-a-single-project). To set up multiple apps on {{% names/dedicated-gen-2 %}} environments, [contact Sales](https://platform.sh/contact/). + body: This page applies to Grid projects. To ensure you have enough resources to support multiple apps, you need at least a [{{< partial "plans/multiapp-plan-name" >}} plan](/administration/pricing/_index.md#multiple-apps-in-a-single-project). To set up multiple apps on {{% names/dedicated-gen-2 %}} environments, [contact Sales](https://platform.sh/contact/). --- When you set up a project containing multiple applications, diff --git a/sites/platform/src/create-apps/runtime-operations.md b/sites/platform/src/create-apps/runtime-operations.md index baa57c787d..c5c166ce6b 100644 --- a/sites/platform/src/create-apps/runtime-operations.md +++ b/sites/platform/src/create-apps/runtime-operations.md @@ -5,7 +5,7 @@ weight: 6 --- Runtime operations allow you to trigger one-off commands or scripts on your project. -Similar to [crons](/create-apps/app-reference/single-runtime-image.md#crons), they run in the app container but not on a specific schedule. +Similar to [crons](/create-apps/image-properties/crons.md), they run in the app container but not on a specific schedule. You can [define runtime operations](#define-a-runtime-operation) in your [app configuration](/create-apps/app-reference/single-runtime-image.md) and [trigger them](#run-a-runtime-operation) at any time through the {{% vendor/name %}} CLI. diff --git a/sites/platform/src/create-apps/source-operations.md b/sites/platform/src/create-apps/source-operations.md index 71a99cfdb8..0feed0d03b 100644 --- a/sites/platform/src/create-apps/source-operations.md +++ b/sites/platform/src/create-apps/source-operations.md @@ -21,7 +21,7 @@ or [revert to the last commit](#revert-to-the-last-commit) pushed to your Git re To run your source operations, you can use the [{{% vendor/name %}} CLI](/administration/cli/_index.md) or the [Console](https://console.platform.sh). If you want to run your source operations and update your code automatically, -you can also define [cron jobs](/create-apps/app-reference/single-runtime-image.md#crons). +you can also define [cron jobs](/create-apps/image-properties/crons.md). ## How source operations work diff --git a/sites/platform/src/create-apps/upgrading.md b/sites/platform/src/create-apps/upgrading.md index 52ca84f7a3..b2dc63059b 100644 --- a/sites/platform/src/create-apps/upgrading.md +++ b/sites/platform/src/create-apps/upgrading.md @@ -26,7 +26,7 @@ weight: 12 ``` The new syntax offers greater flexibility and configuration. - For more details, see the [full specification for cron jobs](/create-apps/app-reference/single-runtime-image.md#crons). + For more details, see the [full specification for cron jobs](/create-apps/image-properties/crons.md). ## Changes in version 2019.05 diff --git a/sites/platform/src/create-apps/workers.md b/sites/platform/src/create-apps/workers.md index c5e9664df4..640e7e09b5 100644 --- a/sites/platform/src/create-apps/workers.md +++ b/sites/platform/src/create-apps/workers.md @@ -73,13 +73,13 @@ The `start` key specifies the command to use to launch your worker application. It may be any valid shell command, although most often it runs a command in your application in the language of your application. If the command specified by the `start` key terminates, it's restarted automatically. -Note that [`deploy` and `post_deploy` hooks](/create-apps/hooks/_index.md) as well as [`cron` commands](/create-apps/app-reference/single-runtime-image.md#crons) +Note that [`deploy` and `post_deploy` hooks](/create-apps/hooks/_index.md) as well as [`cron` commands](/create-apps/image-properties/crons.md) run only on the [`web`](/create-apps/app-reference/single-runtime-image.md#web) container, not on workers. ## Inheritance -Any top-level definitions for [`size`](/create-apps/app-reference/single-runtime-image.md#sizes), [`relationships`](/create-apps/app-reference/single-runtime-image.md#relationships), -[`access`](/create-apps/app-reference/single-runtime-image.md#access), [`disk`](/create-apps/app-reference/single-runtime-image.md), [`mount`](/create-apps/app-reference/single-runtime-image.md#mounts), and [`variables`](/create-apps/app-reference/single-runtime-image.md#variables) +Any top-level definitions for [`size`](/create-apps/image-properties/size.md), [`relationships`](/create-apps/image-properties/relationships.md), +[`access`](/create-apps/image-properties/access.md), [`disk`](/create-apps/image-properties/disk.md), [`mount`](/create-apps/image-properties/mounts.md), and [`variables`](/create-apps/image-properties/variables.md) are inherited by every worker, unless overridden explicitly. That means, for example, that the following two `{{< vendor/configfile "app" >}}` definitions produce identical workers. diff --git a/sites/platform/src/dedicated-environments/dedicated-gen-2/environment-differences.md b/sites/platform/src/dedicated-environments/dedicated-gen-2/environment-differences.md index dd67b7485d..28671902f6 100644 --- a/sites/platform/src/dedicated-environments/dedicated-gen-2/environment-differences.md +++ b/sites/platform/src/dedicated-environments/dedicated-gen-2/environment-differences.md @@ -76,7 +76,7 @@ On {{% names/dedicated-gen-2 %}} Environments, it runs as [SolrCloud](https://so ## Cron tasks interrupted by deploys -How [cron tasks](/create-apps/app-reference/single-runtime-image.md#crons) interact with deploys changes based on the environment. +How [cron tasks](/create-apps/image-properties/crons.md) interact with deploys changes based on the environment. On Grid environments, a running cron task blocks a deploy until the cron is complete. On {{% names/dedicated-gen-2 %}} environments, a deploy terminates a running cron task. diff --git a/sites/platform/src/development/troubleshoot.md b/sites/platform/src/development/troubleshoot.md index bd65b3fdf8..00ba05a6ac 100644 --- a/sites/platform/src/development/troubleshoot.md +++ b/sites/platform/src/development/troubleshoot.md @@ -291,7 +291,7 @@ strace -T {{< variable "YOUR_HOOK_COMMAND" >}} # Print a system call report ### Cron jobs -Containers can't be shutdown while long-running [cron jobs and scheduled tasks](/create-apps/app-reference/single-runtime-image.md#crons) are active. +Containers can't be shutdown while long-running [cron jobs and scheduled tasks](/create-apps/image-properties/crons.md) are active. That means long-running cron jobs block a container from being shut down to make way for a new deploy. Make sure your custom cron jobs run quickly and properly. diff --git a/sites/platform/src/environments/backup.md b/sites/platform/src/environments/backup.md index ddf51a09ac..37aaee0267 100644 --- a/sites/platform/src/environments/backup.md +++ b/sites/platform/src/environments/backup.md @@ -180,7 +180,7 @@ title=In the Console ### Automate manual backups -You can also automate the process of creating manual backups through [cron jobs](/create-apps/app-reference/single-runtime-image.md#crons). +You can also automate the process of creating manual backups through [cron jobs](/create-apps/image-properties/crons.md). The cron job uses the CLI command to back up the environment. It requires you to [set up the CLI on the environment with an API token](/administration/cli/api-tokens.md#authenticate-in-an-environment). diff --git a/sites/platform/src/increase-observability/logs/access-logs.md b/sites/platform/src/increase-observability/logs/access-logs.md index 6a11e86238..202d77c035 100644 --- a/sites/platform/src/increase-observability/logs/access-logs.md +++ b/sites/platform/src/increase-observability/logs/access-logs.md @@ -120,7 +120,7 @@ title=Using SSH directly {{< /codetabs >}} All log files are trimmed to 100 MB automatically. -If you need larger logs, set up a [cron job](/create-apps/app-reference/single-runtime-image.md#crons) to upload them to third-party storage. +If you need larger logs, set up a [cron job](/create-apps/image-properties/crons.md) to upload them to third-party storage. See an example of [uploading logs to Amazon S3](https://gitlab.com/contextualcode/platformsh-store-logs-at-s3) from Contextual Code. ### Types of container logs diff --git a/sites/platform/src/integrations/activity/reference.md b/sites/platform/src/integrations/activity/reference.md index f949679dd6..d48c318d4c 100644 --- a/sites/platform/src/integrations/activity/reference.md +++ b/sites/platform/src/integrations/activity/reference.md @@ -123,7 +123,7 @@ The following table presents the possible activity types: | `environment.backup.delete` | A user deleted a [backup](/environments/backup.md). | | `environment.branch` | A [new branch](/environments.md#create-environments) has been created via the CLI, Console, or API. A branch created via Git shows up as `environment.push`. | | `environment.certificate.renewal` | An environment's SSL certificate has been [renewed](/define-routes/https.md#certificate-renewals). | -| `environment.cron` | A [cron job](/create-apps/app-reference/single-runtime-image.md#crons) has completed. | +| `environment.cron` | A [cron job](/create-apps/image-properties/crons.md) has completed. | | `environment.deactivate` | An environment has been made [inactive](/glossary/_index.md#inactive-environment). | | `environment.delete` | An environment's code was deleted through Git. | | `environment.domain.create` | A new [domain](administration/web/configure-project.md#domains) has been associated with the environment. | @@ -330,7 +330,7 @@ To test responses, [set up a webhook](/integrations/activity/webhooks.md#setup). ### Cron -When a cron job is triggered, the activity contains all the [job's information](/create-apps/app-reference/single-runtime-image.md#crons). +When a cron job is triggered, the activity contains all the [job's information](/create-apps/image-properties/crons.md). The following example response was triggered by a setting where the cron is scheduled to run every five minutes (`5 * * * *`) with the command `sleep 60 && echo sleep-60-finished && date` and times out after 86,400 seconds. diff --git a/sites/platform/src/languages/php/_index.md b/sites/platform/src/languages/php/_index.md index 760dc5ca24..435475a644 100644 --- a/sites/platform/src/languages/php/_index.md +++ b/sites/platform/src/languages/php/_index.md @@ -482,7 +482,7 @@ Common functions to disable include: PHP has two execution modes you can choose from: - The command line interface mode (PHP-CLI) is the mode used for command line scripts and standalone apps. - This is the mode used when you're logged into your container via SSH, for [crons](/create-apps/app-reference/single-runtime-image.md#crons), + This is the mode used when you're logged into your container via SSH, for [crons](/create-apps/image-properties/crons.md), and usually also for [alternate start commands](#alternate-start-commands). To use PHP-CLI, run your script with `php {{}}`, where {{}} is a file path relative to the [app root](/create-apps/app-reference/single-runtime-image.md#root-directory). diff --git a/sites/platform/src/projects/change-project-timezone.md b/sites/platform/src/projects/change-project-timezone.md index 4e7dfd8445..a8716061a3 100644 --- a/sites/platform/src/projects/change-project-timezone.md +++ b/sites/platform/src/projects/change-project-timezone.md @@ -8,7 +8,7 @@ The project timezone affects [automated backups](/environments/backup.md). The project timezone doesn't affect: - [App runtime](/create-apps/timezone.md). -- [Cron jobs](/create-apps/app-reference/single-runtime-image.md#crons). +- [Cron jobs](/create-apps/image-properties/crons.md). - [System logs](/increase-observability/logs/_index.md). UTC is the default timezone for all logs. To change the timezone for a project, follow these steps: diff --git a/sites/upsun/src/administration/users.md b/sites/upsun/src/administration/users.md index a965faf161..3a6ee73d18 100644 --- a/sites/upsun/src/administration/users.md +++ b/sites/upsun/src/administration/users.md @@ -48,7 +48,7 @@ A user can have one of the following roles on an environment type which grants t | Contributor | Yes | No | Yes | Yes | Yes | No | No | | Viewer | Yes | No | No | Yes | No | No | No | -To customize which roles can use SSH, set [`access` in your app configuration](/create-apps/app-reference/single-runtime-image.md#access). +To customize which roles can use SSH, set [`access` in your app configuration](/create-apps/image-properties/access.md). ### View a user's permissions across all of the projects in your organization diff --git a/sites/upsun/src/create-apps/app-reference/_index.md b/sites/upsun/src/create-apps/app-reference/_index.md index c76a52b910..d9c83c6e3f 100644 --- a/sites/upsun/src/create-apps/app-reference/_index.md +++ b/sites/upsun/src/create-apps/app-reference/_index.md @@ -1,32 +1,59 @@ --- -title: "App reference" -weight: 4 +title: "Choose an image type" +weight: -19 description: Configure your app and control how it's built and deployed on {{% vendor/name %}}. layout: single --- -To define your app, you can either use one of {{% vendor/name %}}'s [single-runtime image](/create-apps/app-reference/single-runtime-image.md) -or its [composable image (BETA)](/create-apps/app-reference/composable-image.md). +An _image_ represents the configuration of the container that contains the application (or service) that you want to deploy. -## Single-runtime image +Choosing the image type for the container that best suits your application is the first and most important decision in configuring how your application is deployed. -{{% vendor/name %}} provides and maintains a list of single-runtime images you can use for each of your application containers.
-See [all of the options you can use](/create-apps/app-reference/single-runtime-image.md) to define your app using a single-runtime image. +You can choose either {{% vendor/name %}}'s [single-runtime image](/create-apps/app-reference/single-runtime-image.md) +or its [composable image (BETA)](/create-apps/app-reference/composable-image.md). **The key difference between them is the type of flexibility that they offer**. -## Composable image (BETA) +## Which image type should you choose? {#which-image-type} -The {{% vendor/name %}} composable image provides more flexibility than single-runtime images. -When using a composable image, you can define a stack (or group of packages) for your application container to use. +**Single-runtime image**: This image type offers the flexibility to specify single runtime package versions, however, this typically requires more manual configuration. -There are over 80,000 packages available from the [Nix Packages collection](https://search.nixos.org/) that you can add to your stack. -You can add as many packages to your application container as you need. +Consider using a single-runtime image when these factors are important: +- Your application requires a single runtime only. +- You want the ability to choose specific package versions, including patches. +- You want {{% vendor/name %}} to update the image (perform package upgrades and apply security patches) rather do this maintenance yourself +- Your team has the time and knowledge to manually configure package versions and manage dependencies: For example, writing scripts to cache binaries after they're downloaded, or understanding upgrade paths for complicated node binary dependencies. -{{% note %}} +If you initially choose a single-runtime image and your application needs change, you can move the app to a composable image if your app needs change. -{{% vendor/name %}} guarantees optimal user experience with the specific [set of packages](/create-apps/app-reference/composable-image.md#supported-nix-packages) it supports. -You can use any other package available from the [Nix Packages collection](https://search.nixos.org/), including unstable ones, -but NixOs is responsible for their support. +**Composable image** (BETA): This image type offers the flexibility to define or "compose" the stack (group of packages) to include in the container that runs your application. Developers spend less time manually configuring stacks and dependencies because stacks are already defined in the supported Nix channels. + +Consider using a composable image when these factors are important: +- Your application requires multiple runtimes and tools, or even different versions of the same package +- You want the ability to install _all_ the packages you need in your application container, ensuring consistency across environments and machines +- You or your teams have the time and skills to upgrade packages and apply security patches. +- You or your teams understand how to update a configured image when package versions change in supported stacks (for example, if a package version in Nix channel X.Y changes, you might need to update the versions of additonal packages defined in the stack) +- Consistency: Nix channels ensure that what works on your local machine works on any other machine. This consistency also streamlines development and testing. + + +| Criteria | Single-runtime image | Composable image | +|-----------------------------|----------------------|------------------| +| # of runtimes per container | one | one or more | +| Manual configuration | Typically required for downloads, dependencies | Typically needed only when Nix channel versions and other versions listed in the `stack` are incompatible | +| Maintenance (upgrades and patches) | Maintained by {{% vendor/name %}} | Maintained by you | +| Support | XXX | Stable Nix channels only, but any NixOs package can be installed, including `unstable` | +| config file | `{{< vendor/configfile "app" >}}` | `{{< vendor/configfile "app" >}}` | +| XXX | |Supports applications only, not services | +| Performance | XXXX | Initial builds and rebuilds take some time; automatic caching improves containe startup time | +| `type` | Indicates the base container image used to run the application (`major.minor`). Cannot select a patch version. | Indicates the Nix channel version | +| build and deploy `hooks` | Build flavor is run if applicable and any dependencies are installed | Managed by the Nix channel | + + +## Differences in defining the keys + +Only the single-runtime image supports the [``build``](/create-apps/app-reference/single-runtime-image.md#build), [``dependencies``](/create-apps/app-reference/single-runtime-image.md#dependencies), and [``runtime``](/create-apps/app-reference/single-runtime-image.md#druntime) keys. In a composable image, the equivalent is the [`stack`](/create-apps/app-reference/composable-image.html#stack) key. + +Otherwise, the same keys are available for both image types. Differences in syntax or meaning are noted in the details for that key. + +## Multi-app projects +In a multiple application context, you can use a mix of single-runtime images and composable images. See the examples in the [single-runtime image](/create-apps/app-reference/single-runtime-image.md#mix-of-images) topic and [composable](/create-apps/app-reference/composable-image.md#combine-single-runtime-and-composable-images) image topic. -{{% /note %}} -See [all of the options you can use](/create-apps/app-reference/composable-image.md) to define your app using the composable image. diff --git a/sites/upsun/src/create-apps/app-reference/composable-image.md b/sites/upsun/src/create-apps/app-reference/composable-image.md index d1522d9798..fa890a2913 100644 --- a/sites/upsun/src/create-apps/app-reference/composable-image.md +++ b/sites/upsun/src/create-apps/app-reference/composable-image.md @@ -58,24 +58,27 @@ above). The column _Set in instance?_ defines whether the given property can be overridden within a `web` or `workers` instance. To override any part of a property, you have to provide the entire property. +- **Note:** Except for the `stack` key, the keys listed below are available in **both** the single-runtime and composable image types. Clicking the link for their details leads you to a separate topic for that property. Descriptions for keys that are **unique** to this image type are provided later in this topic. + + | Name | Type | Required | Set in instance? | Description | |----------------------|------------------------------------------------------------------------------------------|----------|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `type` | A type | Yes | No | [Defines the version of the Nix channel](#supported-nix-channels). Example: `type: "composable:25.05"` | -| `stack` | An array of [Nix packages](#stack) | Yes | No | A list of packages from the {{% vendor/name %}} collection of [supported runtimes](#supported-nix-packages) and/or from [NixPkgs](https://search.nixos.org/packages). | -| `container_profile` | A [container profile](/manage-resources/adjust-resources.md#advanced-container-profiles) | | Yes | Container profile of the application. | -| `relationships` | A dictionary of [relationships](#relationships) | | Yes | Connections to other services and apps. | -| `mounts` | A dictionary of [mounts](#mounts) | | Yes | Directories that are writable even after the app is built. Allocated disk for mounts is defined with a separate resource configuration call using `{{% vendor/cli %}} resources:set`. | -| `web` | A [web instance](#web) | | N/A | How the web application is served. | -| `workers` | A [worker instance](#workers) | | N/A | Alternate copies of the application to run as background processes. | +| `type` | A type | Yes | No | [Defines the version of the Nix channel](#supported-nix-channels). Example: `type: "composable:25.05"`. If not present, defaults to last stable version. | +| [`stack`](#stack) | An array of Nix packages | Yes | No | A list of packages from the {{% vendor/name %}} collection of [supported runtimes](#supported-nix-packages) and/or from [NixPkgs](https://search.nixos.org/packages). | +| [`container_profile`](/create-apps/image-properties/container_profile.md) | A container profile | | Yes | Container profile of the application. | +| [`relationships`](/create-apps/image-properties/relationships.md) | A dictionary of relationships | | Yes | Connections to other services and apps. | +| [`mounts`](/create-apps/image-properties/mounts.md) | A dictionary of mounts | | Yes | Directories that are writable even after the app is built. Allocated disk for mounts is defined with a separate resource configuration call using `{{% vendor/cli %}} resources:set`. | +|[`web`](/create-apps/image-properties/web.md) | A web instance | | N/A | How the web application is served. | +| [`workers`](/create-apps/image-properties/workers.md) | A worker instance | | N/A | Alternate copies of the application to run as background processes. | | `timezone` | `string` | | No | The timezone for crons to run. Format: a [TZ database name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Defaults to `UTC`, which is the timezone used for all logs no matter the value here. See also [app runtime timezones](../timezone.md). | -| `access` | An [access dictionary](#access) | | Yes | Access control for roles accessing app environments. | -| `variables` | A [variables dictionary](#variables) | | Yes | Variables to control the environment. | -| `firewall` | A [firewall dictionary](#firewall) | | Yes | Outbound firewall rules for the application. | -| `hooks` | A [hooks dictionary](#hooks) | | No | What commands run at different stages in the build and deploy process. | -| `crons` | A [cron dictionary](#crons) | | No | Scheduled tasks for the app. | -| `source` | A [source dictionary](#source) | | No | Information on the app's source code and operations that can be run on it. | -| `additional_hosts` | An [additional hosts dictionary](#additional-hosts) | | Yes | Maps of hostnames to IP addresses. | -| `operations` | A [dictionary of Runtime operations](/create-apps/runtime-operations.md) | | No | Runtime operations for the application. | +| [`access`](/create-apps/image-properties/access.md) | An access dictionary | | Yes | Access control for roles accessing app environments. | +| [`variables`](/create-apps/image-properties/variables.md) | A variables dictionary | | Yes | Variables to control the environment. | +| [`firewall`](/create-apps/image-properties/firewall.md) | A firewall dictionary | | Yes | Outbound firewall rules for the application. | +| [`hooks`](/create-apps/image-properties/hooks.md) | A hooks dictionary | | No | What commands run at different stages in the build and deploy process. | +| [`crons`](/create-apps/image-properties/crons.md) | A cron dictionary | | No | Scheduled tasks for the app. | +| [`source`](/create-apps/image-properties/source.md) | A source dictionary | | No | Information on the app's source code and operations that can be run on it. | +| [`additional_hosts`](/create-apps/image-properties/additional_hosts.md) | An additional hosts dictionary | | Yes | Maps of hostnames to IP addresses. | +| [`operations`](/create-apps/runtime-operations.md) | A dictionary of runtime operations | | No | Runtime operations for the application. | {{% note %}} @@ -85,7 +88,7 @@ They are replaced by the `stack` key. {{% /note %}} -## Stack +## `stack` {#stack} Use the ``stack`` key to define which runtimes and binaries you want to install in your application container. Define them as a YAML array as follows: @@ -109,7 +112,7 @@ When using the {{% vendor/name %}} composable image, you don't need `nix` comman Everything you install using the `stack` key is readily available to you as the binaries are linked and included in `$PATH`. For instance, to [start a secondary runtime](#primary-runtime), -just issue the command (e.g. in the [`start` command](/create-apps/app-reference/composable-image.md#web-commands)) instead of the `nix run` command. +just issue the command (e.g. in the [`start` command](/create-apps/image-properties/web.md#web-commands)) instead of the `nix run` command. {{% /note %}} #### Primary runtime @@ -118,7 +121,7 @@ If you add multiple runtimes to your application container, the first declared runtime becomes the primary runtime. The primary runtime is the one that is automatically started. -To start other declared runtimes, you need to start them manually, using [web commands](#web-commands). +To start other declared runtimes, you need to start them manually, using [web commands](/create-apps/image-properties/web.md#web-commands). To find out which start command to use, go to the [Languages](/languages/_index.md) section, and visit the documentation page dedicated to your runtime. @@ -303,7 +306,7 @@ If you add multiple runtimes to your application container, the first declared runtime becomes the primary runtime. The primary runtime is the one that is automatically started. -To start other declared runtimes, you need to start them manually, using [web commands](#web-commands). +To start other declared runtimes, you need to start them manually, using [web commands](/create-apps/image-properties/web.md#web-commands). To find out which start command to use, go to the [Languages](/languages/_index.md) section, and visit the documentation page dedicated to your language. @@ -331,215 +334,6 @@ commands: {{% /note %}} -## Relationships - -To allow containers in your project to communicate with one another, -you need to define relationships between them. -You can define a relationship between an app and a service, or [between two apps](/create-apps/multi-app/relationships.md). - -The quickest way to define a relationship between your app and a service -is to use the service's default endpoint.
-However, some services allow you to define multiple databases, cores, and/or permissions. -In these cases, you can't rely on default endpoints. -Instead, you can explicitly define multiple endpoints when setting up your relationships. - -{{< note >}} -App containers don't have a default endpoint like services. -To connect your app to another app in your project, -you need to explicitly define the `http` endpoint as the endpoint to connect both apps.
-For more information, see how to [define relationships between your apps](/create-apps/multi-app/relationships.md). -{{< /note >}} - -{{< note title="Availability" theme="info">}} - -New syntax (default and explicit endpoints) described below is supported by most, but not all, image types -(`Relationship 'SERVICE_NAME' of application 'myapp' ... targets a service without a valid default endpoint configuration.`). -This syntax is currently being rolled out for all images. -If you encounter this error, use the "legacy" {{% vendor/name %}} configuration noted at the bottom of this section. - -{{< /note >}} - -To define a relationship between your app and a service: - -{{< codetabs >}} - -+++ -title=Using default endpoints -+++ - -Use the following configuration: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - {{% variable "SERVICE_NAME" %}}: -``` - -The `SERVICE_NAME` is the name of the service as defined in its [configuration](/add-services/_index.md). -It is used as the relationship name, and associated with a `null` value. -This instructs {{% vendor/name %}} to use the service's default endpoint to connect your app to the service. - -For example, if you define the following configuration: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - mariadb: -``` - -{{% vendor/name %}} looks for a service named `mariadb` in your `{{% vendor/configfile "services" %}}` file, -and connects your app to it through the service's default endpoint. - -For reference, the equivalent configuration using explicit endpoints would be the following: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - mariadb: - service: mariadb - endpoint: mysql -``` - -You can define any number of relationships in this way: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - mariadb: - redis: - elasticsearch: -``` - -{{< note title="Tip" theme="info" >}} - -An even quicker way to define many relationships is to use the following single-line configuration: - -```yaml {configFile="services"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: {{{< variable "SERVICE_NAME_A" >}}, {{< variable "SERVICE_NAME_B" >}}, {{< variable "SERVICE_NAME_C" >}}} - -services: - {{< variable "SERVICE_NAME_A" >}}: - type: mariadb:{{% latest "mariadb" %}} - {{< variable "SERVICE_NAME_B" >}}: - type: redis:{{% latest "redis" %}} - {{< variable "SERVICE_NAME_C" >}}: - type: elasticsearch:{{% latest "elasticsearch" %}} -``` - -{{< /note >}} - -<---> - -+++ -title=Using explicit endpoints -+++ - -Use the following configuration: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - {{% variable "RELATIONSHIP_NAME" %}}: - service: {{% variable "SERVICE_NAME" %}} - endpoint: {{% variable "ENDPOINT_NAME" %}} -``` - -- `RELATIONSHIP_NAME` is the name you want to give to the relationship. -- `SERVICE_NAME` is the name of the service as defined in its [configuration](/add-services/_index.md). -- `ENDPOINT_NAME` is the endpoint your app will use to connect to the service (refer to the service reference to know which value to use). - -For example, to define a relationship named `database` that connects your app to a service called `mariadb` through the `db1` endpoint, -use the following configuration: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - database: # The name of the relationship. - service: mariadb - endpoint: db1 -``` - -For more information on how to handle multiple databases, multiple cores, -and/or different permissions with services that support such features, -see each service's dedicated page: - - - [MariaDB/MySQL](/add-services/mysql/_index.md#multiple-databases) (multiple databases and permissions) - - [PostgreSQL](/add-services/postgresql/_index.md#multiple-databases) (multiple databases and permissions) - - [Redis](/add-services/redis/_index.md#multiple-databases) (multiple databases) - - [Solr](add-services/solr/_index.md#solr-6-and-later) (multiple cores) - - [Vault KMS](add-services/vault.md#multiple-endpoints-example) (multiple permissions) - - You can add as many relationships as you want to your app configuration, - using both default and explicit endpoints according to your needs: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - database1: - service: mariadb - endpoint: admin - database2: - service: mariadb - endpoint: legacy - cache: - service: redis - search: - service: elasticsearch -``` - -{{< /codetabs >}} - -{{< note theme="info" title="Legacy" >}} - -The following legacy syntax for specifying relationships is still supported by {{% vendor/name %}}: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - : ":" - -services: - SERVICE_NAME_A: - type: mariadb:{{% latest "mariadb" %}} -``` - -For example: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - database: "db:mysql" - -services: - db: - type: mariadb:{{% latest "mariadb" %}} -``` - -Feel free to use this until the default and explicit endpoint syntax is supported on all images. - -{{< /note >}} - ## Available disk space Disk for application containers are not committed to YAML files, but instead managed over the API using either the @@ -554,980 +348,3 @@ You can decrease the size of an existing disk for an app. If you do so, be aware - Backups from before the downsize are incompatible and can no longer be used. You need to [create new backups](/environments/backup.md). - The downsize fails if there’s more data on the disk than the desired size. -## Mounts - -After your app is built, its file system is read-only. -To make changes to your app's code, you need to use Git. - -For enhanced flexibility, {{% vendor/name %}} allows you to define and use writable directories called "mounts". -Mounts give you write access to files generated by your app (such as cache and log files) -and uploaded files without going through Git. - -When you define a mount, you are mounting an external directory to your app container, -much like you would plug a hard drive into your computer to transfer data. - -{{% note %}} - -- Mounts aren't available during the build -- When you [back up an environment](/environments/backup.md), the mounts on that environment are backed up too - -{{% /note %}} - -### Define a mount - -To define a mount, use the following configuration: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "nodejs@{{% latest nodejs %}}" ] - mounts: - '{{< variable "MOUNT_PATH" >}}': - source: {{< variable "MOUNT_TYPE" >}} - source_path: {{< variable "SOURCE_PATH_LOCATION" >}} -``` - -{{< variable "MOUNT_PATH" >}} is the path to your mount **within the app container** (relative to the app's root). -If you already have a directory with that name, you get a warning that it isn't accessible after the build. -See how to [troubleshoot the warning](../troubleshoot-mounts.md#overlapping-folders). - -| Name | Type | Required | Description | -|---------------|--------------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `source` | `storage`, `tmp`, or `service` | Yes | Specifies the type of the mount:

- By design, `storage` mounts can be shared between instances of the same app. You can also configure them so they are [shared between different apps](#share-a-mount-between-several-apps).

-`instance` mounts are local mounts. Unique to your app, they are useful to store files that remain local to the app instance, such as application logs.

- `tmp` mounts are local ephemeral mounts, where an external directory is mounted to the `/tmp` directory of your app.
The content of a `tmp` mount **may be removed during infrastructure maintenance operations**. Therefore, `tmp` mounts allow you to **store files that you’re not afraid to lose**, such as your application cache that can be seamlessly rebuilt.
Note that the `/tmp` directory has **a maximum allocation of 8 GB**.

- `service` mounts can be useful if you want to explicitly define and use a [Network Storage](/add-services/network-storage.md) service to share data between different apps (instead of using a `storage` mount). | -| `source_path` | `string` | No | Specifies where the mount points **inside the [external directory](#mounts)**.

- If you explicitly set a `source_path`, your mount points to a specific subdirectory in the external directory.

- If the `source_path` is an empty string (`""`), your mount points to the entire external directory.

- If you don't define a `source_path`, {{% vendor/name %}} uses the {{< variable "MOUNT_PATH" >}} as default value, without leading or trailing slashes.
For example, if your mount lives in the `/web/uploads/` directory in your app container, it will point to a directory named `web/uploads` in the external directory.

**WARNING:** Changing the name of your mount affects the `source_path` when it's undefined. See [how to ensure continuity](#ensure-continuity-when-changing-the-name-of-your-mount) and maintain access to your files. | -| `service` | `string` | | The purpose of the `service` key depends on your use case.

In a multi-app context where a `storage` mount is shared between apps, `service` is required. Its value is the name of the app whose mount you want to share. See how to [share a mount between several apps](#share-a-mount-between-several-apps).

In a multi-app context where a [Network Storage service](/add-services/network-storage.md) (`service` mount) is shared between apps, `service` is required and specifies the name of that Network Storage. | - -The accessibility to the web of a mounted directory depends on the [`web.locations` configuration](#web). -Files can be all public, all private, or with different rules for different paths and file types. - -Note that when you remove a `tmp` mount from your `{{< vendor/configfile "app" >}}` file, -the mounted directory isn't deleted. -The files still exist on disk until manually removed, -or until the app container is moved to another host during a maintenance operation. - -### Example configuration - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "nodejs@{{% latest nodejs %}}" ] - mounts: - 'web/uploads': - source: storage - source_path: uploads - '/.tmp_platformsh': - source: tmp - source_path: files/.tmp_platformsh - '/build': - source: storage - source_path: files/build - '/.cache': - source: tmp - source_path: files/.cache - '/node_modules/.cache': - source: tmp - source_path: files/node_modules/.cache -``` - -### Ensure continuity when changing the name of your mount - -Changing the name of your mount affects the default `source_path`. - -Say you have a `/my/cache/` mount with an undefined `source_path`: - -```yaml {configFile="app"} -mounts: - '/my/cache/': - source: tmp -``` - -If you rename the mount to `/cache/files/`, it will point to a new, empty `/cache/files/` directory. - -To ensure continuity, you need to explicitly define the `source_path` as the previous name of the mount, without leading -or trailing slashes: - - ```yaml {configFile="app"} -mounts: - '/cache/files/': - source: tmp - source_path: my/cache -``` - -The `/cache/files/` mount will point to the original `/my/cache/` directory, maintaining access to all your existing -files in that directory. - -### Share a mount between several apps - -By design, [`storage` mounts](#mounts) are shared **between different instances of the same app**, -which enables [horizontal scaling](/manage-resources/_index.md). - -In a [multi-application context](/create-apps/multi-app/_index.md), -you can even share a `storage` mount **between different applications** in the same project. - -To do so, you need to define a `storage` mount in each of your app containers, -and point each of those mounts to the same shared external network directory. - -Use the following configuration: - -```yaml {configFile="app"} -applications: - app1: - mounts: - '{{< variable "MOUNT_PATH_1" >}}': - source: storage - source_path: {{< variable "SOURCE_PATH_LOCATION" >}} - - app2: - mounts: - '{{< variable "MOUNT_PATH_2" >}}': - source: storage - service: app1 - source_path: {{< variable "SOURCE_PATH_LOCATION" >}} -``` - -- {{< variable "MOUNT_PATH_1" >}} and {{< variable "MOUNT_PATH_2" >}} are the paths to each mount **within their - respective app container** (relative to the app's root). -- When configuring the first `storage` mount, you don't need to include the `service` key. - The first mount implicitly points to an external network directory. - The `service` key is required for subsequent mounts, to ensure they use the same external network directory as the - first mount. -- The `source_path` allows you to point each mount to the same subdirectory **within the shared external network - directory**. - -{{% note title = "Example" %}} - -You have a `backend` app and a `frontend` app. -You want both apps to share data from the same mount.
-Follow these steps: - -1. In your `backend` app configuration, define a `storage` mount: - - ```yaml {configFile="app"} - applications: - backend: - mounts: - var/uploads: #The path to your mount within the backend app container. - source: storage - source_path: backend/uploads #The path to the source of the mount within the external network directory. - ``` - - This creates a `storage` mount named `var/uploads` in the `backend` app container. - The mount points to the `backend/uploads` directory within an external network directory. - -2. In your `frontend` app configuration, define another `storage` mount: - - ```yaml {configFile="app"} - applications: - backend: - mounts: - var/uploads: - source: storage - source_path: backend/uploads - - frontend: - mounts: - web/uploads: #The path to your mount within the frontend app container. - source: storage - service: backend #The name of the other app, so the mount can point to the same external network directory as that other app's mount. - source_path: backend/uploads #The path to the source of the mount within the shared external network directory. - ``` - - This creates another `storage` mount named `web/uploads` in the `frontend` app container. - - The `service` key allows you to specify that the `web/uploads` mount should use the same external network directory - as the mount previously defined in the `backend` app container. - - The `source_path` key specifies which subdirectory within the external network directory both mounts should share ( - here, the `backend/uploads` directory). - -{{% /note %}} - -Note that another way to share data between apps through a mount is by -explicitly [defining a Network Storage service](/add-services/network-storage.md). - -### Local mounts - -If you need a local mount (i.e. unique per container), -{{% vendor/name %}} allows you to mount a directory within the `/tmp` directory of your app. -However, the following limitations apply: - -- Content from `tmp` mounts is removed when your app container is moved to another host during an infrastructure - maintenance operation -- The `/tmp` directory has a [maximum allocation of 8 GB](/create-apps/troubleshoot-disks.md#no-space-left-on-device) - -Therefore, `tmp` mounts are ideal to store non-critical data, such as your application cache which can be seamlessly -rebuilt, -but aren't suitable for storing files that are necessary for your app to run smoothly. - -Note that {{% vendor/name %}} will provide new local mounts in the near future. - -### Overlapping mounts - -The locations of mounts as they are visible to application containers can overlap somewhat. -For example: - -```yaml {configFile="app"} -applications: - myapp: - # ... - mounts: - 'var/cache_a': - source: storage - source_path: cacheA - 'var/cache_b': - source: tmp - source_path: cacheB - 'var/cache_c': - source: instance - source_path: cacheC -``` - -In this case, it does not matter that each mount is of a different `source` type. -Each mount is restricted to a subfolder within `var`, and all is well. - -The following, however, is not allowed and will result in a failure: - -```yaml {configFile="app"} -applications: - myapp: - # ... - mounts: - 'var/': - source: storage - source_path: cacheA - 'var/cache_b': - source: tmp - source_path: cacheB - 'var/cache_c': - source: instance - source_path: cacheC -``` - -The `storage` mount type specifically exists to share data between instances of the same application, whereas `tmp` and `instance` are meant to restrict data to build time and runtime of a single application instance, respectively. -These allowances are not compatible, and will result in an error if pushed. - -## Web - -Use the `web` key to configure the web server running in front of your app. - -| Name | Type | Required | Description | -|-------------|--------------------------------------------|-------------------------------|------------------------------------------------------| -| `commands` | A [web commands dictionary](#web-commands) | See [note](#required-command) | The command to launch your app. | -| `upstream` | An [upstream dictionary](#upstream) | | How the front server connects to your app. | -| `locations` | A [locations dictionary](#locations) | | How the app container responds to incoming requests. | - -See some [examples of how to configure what's served](../web/_index.md). - -### Web commands - -| Name | Type | Required | Description | -|--------------|----------|-------------------------------|-----------------------------------------------------------------------------------------------------| -| `pre_start` | `string` | | Command run just prior to `start`, which can be useful when you need to run _per-instance_ actions. | -| `start` | `string` | See [note](#required-command) | The command to launch your app. If it terminates, it's restarted immediately. | -| `post_start` | `string` | | Command runs **before** adding the container to the router and **after** the `start` command. | - -{{< note theme="info" >}} -The `post_start` feature is _experimental_ and may change. Please share your feedback in the -[{{% vendor/name %}} discord](https://discord.gg/platformsh). -{{< /note >}} - - -Example: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "python@{{% latest python %}}" ] - web: - commands: - start: 'uwsgi --ini conf/server.ini' -``` - -This command runs every time your app is restarted, regardless of whether or not new code is deployed. - -{{< note >}} - -Never "background" a start process using `&`. -That's interpreted as the command terminating and the supervisor process starts a second copy, -creating an infinite loop until the container crashes. -Just run it as normal and allow the {{% vendor/name %}} supervisor to manage it. - -{{< /note >}} - -#### Required command - -On all containers other than PHP, the value for `start` should be treated as required. - -On PHP containers, it's optional and defaults to starting PHP-FPM (`/usr/bin/start-php-app`). -It can also be set explicitly on a PHP container to run a dedicated process, -such as [React PHP](https://github.com/platformsh-examples/platformsh-example-reactphp) -or [Amp](https://github.com/platformsh-examples/platformsh-example-amphp). -See how to set up [alternate start commands on PHP](/languages/php/_index.md#alternate-start-commands). - -### Upstream - -| Name | Type | Required | Description | Default | -|-----------------|---------------------|----------|-------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------| -| `socket_family` | `tcp` or `unix` | | Whether your app listens on a Unix or TCP socket. | Defaults to `tcp` for all [primary runtimes](#primary-runtime) except PHP; for PHP the default is `unix`. | -| `protocol` | `http` or `fastcgi` | | Whether your app receives incoming requests over HTTP or FastCGI. | Default varies based on the [primary runtimes](#primary-runtime). | - -For PHP, the defaults are configured for PHP-FPM and shouldn't need adjustment. -For all other containers, the default for `protocol` is `http`. - -The following example is the default on non-PHP containers: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "python@{{% latest python %}}" ] - web: - upstream: - socket_family: tcp - protocol: http -``` - -#### Where to listen - -Where to listen depends on your setting for `web.upstream.socket_family` (defaults to `tcp`). - -| `socket_family` | Where to listen | -|-----------------|---------------------------------------------------------------------------------------------------------------------------------------| -| `tcp` | The port specified by the [`PORT` environment variable](/development/variables/use-variables.md#use-provided-variables) | -| `unix` | The Unix socket file specified by the [`SOCKET` environment variable](/development/variables/use-variables.md#use-provided-variables) | - -If your application isn't listening at the same place that the runtime is sending requests, -you see `502 Bad Gateway` errors when you try to connect to your website. - -### Locations - -Each key in the `locations` dictionary is a path on your site with a leading `/`. -For `example.com`, a `/` matches `example.com/` and `/admin` matches `example.com/admin`. -When multiple keys match an incoming request, the most-specific applies. - -The following table presents possible properties for each location: - -| Name | Type | Default | Description | -|---------------------|------------------------------------------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `root` | `string` | | The directory to serve static assets for this location relative to the app's root directory ([see `source.root`](#source)). Must be an actual directory inside the root directory. | -| `passthru` | `boolean` or `string` | `false` | Whether to forward disallowed and missing resources from this location to the app. A string is a path with a leading `/` to the controller, such as `/index.php`.

If your app is in PHP, when setting `passthru` to `true`, you might want to set `scripts` to `false` for enhanced security. This prevents PHP scripts from being executed from the specified location. You might also want to set `allow` to `false` so that not only PHP scripts can't be executed, but their source code also can't be delivered. | -| `index` | Array of `string`s or `null` | | Files to consider when serving a request for a directory. When set, requires access to the files through the `allow` or `rules` keys. | -| `expires` | `string` | `-1` | How long static assets are cached. The default means no caching. Setting it to a value enables the `Cache-Control` and `Expires` headers. Times can be suffixed with `ms` = milliseconds, `s` = seconds, `m` = minutes, `h` = hours, `d` = days, `w` = weeks, `M` = months/30d, or `y` = years/365d. | -| `allow` | `boolean` | `true` | Whether to allow serving files which don't match a rule. | -| `scripts` | `boolean` | | Whether to allow scripts to run. Doesn't apply to paths specified in `passthru`. Meaningful only on PHP containers. | -| `headers` | A headers dictionary | | Any additional headers to apply to static assets, mapping header names to values (see [Set custom headers on static content](/create-apps/web/custom-headers.html)). Responses from the app aren't affected. | -| `request_buffering` | A [request buffering dictionary](#request-buffering) | See below | Handling for chunked requests. | -| `rules` | A [rules dictionary](#rules) | | Specific overrides for specific locations. | - -#### Rules - -The rules dictionary can override most other keys according to a regular expression. -The key of each item is a regular expression to match paths exactly. -If an incoming request matches the rule, it's handled by the properties under the rule, -overriding any conflicting rules from the rest of the `locations` dictionary. - -Under `rules`, you can set all the other possible [`locations` properties](#locations) -except `root`, `index`, `rules` and `request_buffering`. - -In the following example, the `allow` key disallows requests for static files anywhere in the site. -This is overridden by a rule that explicitly allows common image file formats. - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "python@{{% latest python %}}" ] - web: - locations: - '/': - # Handle dynamic requests - root: 'public' - passthru: '/index.php' - # Disallow static files - allow: false - rules: - # Allow common image files only. - '\.(jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff2?|otf|ttf)$': - allow: true -``` - -#### Request buffering - -Request buffering is enabled by default to handle chunked requests as most app servers don't support them. -The following table shows the keys in the `request_buffering` dictionary: - -| Name | Type | Required | Default | Description | -|--------------------|-----------|----------|---------|-------------------------------------------| -| `enabled` | `boolean` | Yes | `true` | Whether request buffering is enabled. | -| `max_request_size` | `string` | | `250m` | The maximum size to allow in one request. | - -The default configuration would look like this: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "python@{{% latest python %}}" ] - web: - locations: - '/': - passthru: true - request_buffering: - enabled: true - max_request_size: 250m -``` - -## Workers - -Workers are exact copies of the code and compilation output as a `web` instance after a [`build` hook](#hooks). -They use the same container image. - -Workers can't accept public requests and so are suitable only for background tasks. -If they exit, they're automatically restarted. - -The keys of the `workers` definition are the names of the workers. -You can then define how each worker differs from the `web` instance using -the [top-level properties](#primary-application-properties). - -Each worker can differ from the `web` instance in all properties _except_ for: - -- `crons` as cron jobs don't run on workers -- `hooks` as the `build` hook must be the same - and the `deploy` and `post_deploy` hooks don't run on workers. - -A worker named `queue` that was small and had a different start command could look like this: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "python@{{% latest python %}}" ] - workers: - queue: - commands: - start: | - ./worker.sh -``` - -Workers require resource definition using `{{% vendor/cli %}} resources:set`, same as application containers. -For more information, see how to [manage resources](/manage-resources.md). - -## Access - -The `access` dictionary has one allowed key: - -| Name | Allowed values | Default | Description | -|-------|-------------------------------------|---------------|-----------------------------------------------------------------------| -| `ssh` | `admin`, `contributor`, or `viewer` | `contributor` | Defines the minimum role required to access app environments via SSH. | - -In the following example, only users with `admin` permissions for the -given [environment type](/administration/users.md#environment-type-roles) -can access the deployed environment via SSH: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "python@{{% latest python %}}" ] - access: - ssh: admin -``` - -## Variables - -{{% vendor/name %}} provides a number of ways to set [variables](/development/variables/_index.md). -Variables set in your app configuration have the lowest precedence, -meaning they're overridden by any conflicting values provided elsewhere. - -All variables set in your app configuration must have a prefix. -Some [prefixes have specific meanings](/development/variables/_index.md#variable-prefixes). - -Variables with the prefix `env` are available as a separate environment variable. -All other variables are available in -the [`PLATFORM_VARIABLES` environment variable](/development/variables/use-variables.md#use-provided-variables). - -The following example sets two variables: - -- A variable named `env:AUTHOR` with the value `Juan` that's available in the environment as `AUTHOR` -- A variable named `d8config:system.site:name` with the value `My site rocks` - that's available in the `PLATFORM_VARIABLES` environment variable - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "python@{{% latest python %}}" ] - variables: - env: - AUTHOR: 'Juan' - d8config: - "system.site:name": 'My site rocks' -``` - -You can also define and access more [complex values](/development/variables/use-variables.md#access-complex-values). - -## Firewall - -{{< premium-features/tiered "Elite and Enterprise" >}} - -Set limits in outbound traffic from your app with no impact on inbound requests. - -The `outbound` key is required and contains one or more rules. -The rules define what traffic is allowed; anything unspecified is blocked. - -Each rule has the following properties where at least one is required and `ips` and `domains` can't be specified -together: - -| Name | Type | Default | Description | -|-----------|---------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `ips` | Array of `string`s | `["0.0.0.0/0"]` | IP addresses in [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing). See a [CIDR format converter](https://www.ipaddressguide.com/cidr). | -| `domains` | Array of `string`s | | [Fully qualified domain names](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) to specify specific destinations by hostname. | -| `ports` | Array of `integer`s | | Ports from 1 to 65535 that are allowed. If any ports are specified, all unspecified ports are blocked. If no ports are specified, all ports are allowed. Port `25`, the SMTP port for sending email, is always blocked. | - -The default settings would look like this: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "python@{{% latest python %}}" ] - firewall: - outbound: - - ips: [ "0.0.0.0/0" ] -``` - -### Support for rules - -Where outbound rules for firewalls are supported in all environments. - -### Multiple rules - -Multiple firewall rules can be specified. -In such cases, a given outbound request is allowed if it matches _any_ of the defined rules. - -So in the following example requests to any IP on port 80 are allowed -and requests to 1.2.3.4 on either port 80 or 443 are allowed: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "python@{{% latest python %}}" ] - firewall: - outbound: - - ips: [ "1.2.3.4/32" ] - ports: [ 443 ] - - ports: [ 80 ] -``` - -### Outbound traffic to CDNs - -Be aware that many services are behind a content delivery network (CDN). -For most CDNs, routing is done via domain name, not IP address, -so thousands of domain names may share the same public IP addresses at the CDN. -If you allow the IP address of a CDN, you are usually allowing many or all of the other customers hosted behind that -CDN. - -### Outbound traffic by domain - -You can filter outbound traffic by domain. -Using domains in your rules rather than IP addresses is generally more specific and secure. -For example, if you use an IP address for a service with a CDN, -you have to allow the IP address for the CDN. -This means that you allow potentially hundreds or thousands of other servers also using the CDN. - -An example rule filtering by domain: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "python@{{% latest python %}}" ] - firewall: - outbound: - - protocol: tcp - domains: [ "api.stripe.com", "api.twilio.com" ] - ports: [ 80, 443 ] - - protocol: tcp - ips: [ "1.2.3.4/29","2.3.4.5" ] - ports: [ 22 ] -``` - -#### Determine which domains to allow - -To determine which domains to include in your filtering rules, -find the domains your site has requested the DNS to resolve. -Run the following command to parse your server’s `dns.log` file -and display all Fully Qualified Domain Names that have been requested: - -```bash -awk '/query\[[^P]\]/ { print $6 | "sort -u" }' /var/log/dns.log -``` - -The output includes all DNS requests that were made, including those blocked by your filtering rules. -It doesn't include any requests made using an IP address. - -Example output: - -```bash -facebook.com -fastly.com -upsun.com -www.google.com -www.upsun.com -``` -## Hooks - -There are three different hooks that run as part of the process of building and deploying your app. -These are places where you can run custom scripts. -They are: the `build` hook, the `deploy` hook, and the `post_deploy` hook. -Only the `build` hook is run for [worker instances](#workers), while [web instances](#web) run all three. - -The process is ordered as: - -1. Variables accessible at build time become available. -1. The `build` hook is run. -1. The file system is changed to read only (except for any [mounts](#mounts)). -1. The app container starts. Variables accessible at runtime and services become available. -1. The `deploy` hook is run. -1. The app container begins accepting requests. -1. The `post_deploy` hook is run. - -Note that if an environment changes by no code changes, only the last step is run. -If you want the entire process to run, see how -to [manually trigger builds](/development/troubleshoot.md#manually-trigger-builds). - -### Writable directories during build - -During the `build` hook, there are three writeable directories: - -- `PLATFORM_APP_DIR`: - Where your code is checked out and the working directory when the `build` hook starts. - Becomes the app that gets deployed. -- `PLATFORM_CACHE_DIR`: - Persists between builds, but isn't deployed. - Shared by all builds on all branches. -- `/tmp`: - Isn't deployed and is wiped between each build. - Note that `PLATFORM_CACHE_DIR` is mapped to `/tmp` - and together they offer about 8GB of free space. - -### Hook failure - -Each hook is executed as a single script, so they're considered to have failed only if the final command in them fails. -To cause them to fail on the first failed command, add `set -e` to the beginning of the hook. - -If a `build` hook fails for any reason, the build is aborted and the deploy doesn't happen. -Note that this only works for `build` hooks -- -if other hooks fail, the app is still deployed. - -#### Automated testing - -It’s preferable that you set up and run automated tests in a dedicated CI/CD tool. -Relying on {{% vendor/name %}} hooks for such tasks can prove difficult. - -During the `build` hook, you can halt the deployment on a test failure but the following limitations apply: - -- Access to services such as databases, Redis, Vault KMS, and even writable mounts is disabled. - So any testing that relies on it is sure to fail. -- If you haven’t made changes to your app, an existing build image is reused and the build hook isn’t run. -- Test results are written into your app container, so they might get exposed to a third party. - -During the `deploy` hook, you can access services but **you can’t halt the deployment based on a test failure**. -Note that there are other downsides: - -- Your app container is read-only during the deploy hook, - so if your tests need to write reports and other information, you need to create a file mount for them. -- Your app can only be deployed once the deploy hook has been completed. - Therefore, running automated testing via the deploy hook generates slower deployments. -- Your environment isn’t available externally during the deploy hook. - Unit and integration testing might work without the environment being available, - but you can’t typically perform end-to-end testing until after the environment is up and available. - -## Crons - -The keys of the `crons` definition are the names of the cron jobs. -The names must be unique. - -If an application defines both a `web` instance and `worker` instances, cron jobs run only on the `web` instance. - -See how to [get cron logs](/increase-observability/logs/access-logs.md#container-logs). - -The following table shows the properties for each job: - -| Name | Type | Required | Description | -|--------------------|----------------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `spec` | `string` | Yes | The [cron specification](https://en.wikipedia.org/wiki/Cron#Cron_expression). To prevent competition for resources that might hurt performance, use `H` in definitions to indicate an unspecified but invariant time. For example, instead of using `0 * * * *` to indicate the cron job runs at the start of every hour, you can use `H * * * *` to indicate it runs every hour, but not necessarily at the start. This prevents multiple cron jobs from trying to start at the same time. | -| `commands` | A [cron commands dictionary](#cron-commands) | Yes | A definition of what commands to run when starting and stopping the cron job. | -| `shutdown_timeout` | `integer` | No | When a cron is canceled, this represents the number of seconds after which a `SIGKILL` signal is sent to the process to force terminate it. The default is `10` seconds. | -| `timeout` | `integer` | No | The maximum amount of time a cron can run before it's terminated. Defaults to the maximum allowed value of `86400` seconds (24 hours). | - -Note that you can [cancel pending or running crons](/environments/cancel-activity.md). - - -### Cron commands - -| Name | Type | Required | Description | -|---------|----------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `start` | `string` | Yes | The command that's run. It's run in [Dash](https://en.wikipedia.org/wiki/Almquist_shell). | -| `stop` | `string` | No | The command that's issued to give the cron command a chance to shutdown gracefully, such as to finish an active item in a list of tasks. Issued when a cron task is interrupted by a user through the CLI or Console. If not specified, a `SIGTERM` signal is sent to the process. | - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "nodejs@{{% latest nodejs %}}" ] - crons: - mycommand: - spec: 'H * * * *' - commands: - start: sleep 60 && echo sleep-60-finished && date - stop: killall sleep - shutdown_timeout: 18 -``` - -In this example configuration, the [cron specification](#crons) uses the `H` syntax. - -### Example cron jobs - - -{{< codetabs >}} - -+++ -title=Drupal -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -stack: [ "php@{{% latest php %}}" ] -crons: - # Run Drupal's cron tasks every 19 minutes. - drupal: - spec: '*/19 * * * *' - commands: - start: 'cd web ; drush core-cron' - # But also run pending queue tasks every 7 minutes. - # Use an odd number to avoid running at the same time as the `drupal` cron. - drush-queue: - spec: '*/7 * * * *' - commands: - start: 'cd web ; drush queue-run aggregator_feeds' -{{< /snippet >}} -``` - -<---> - -+++ -title=Ruby on Rails -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -stack: [ "ruby@{{% latest ruby %}}" ] -crons: - # Execute a rake script every 19 minutes. - ruby: - spec: '*/19 * * * *' - commands: - start: 'bundle exec rake some:task' -{{< /snippet >}} -``` - -<---> - -+++ -title=Laravel -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -stack: [ "php@{{% latest php %}}" ] -crons: - # Run Laravel's scheduler every 5 minutes. - scheduler: - spec: '*/5 * * * *' - commands: - start: 'php artisan schedule:run' -{{< /snippet >}} -``` - -<---> - -+++ -title=Symfony -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -stack: [ "php@{{% latest php %}}" ] -crons: - # Take a backup of the environment every day at 5:00 AM. - snapshot: - spec: 0 5 * * * - commands: - start: | - # Only run for the production environment, aka main branch - if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then - croncape symfony ... - fi -{{< /snippet >}} -``` - -{{< /codetabs >}} - - -### Conditional crons - -If you want to set up customized cron schedules depending on the environment type, -define conditional crons. -To do so, use a configuration similar to the following: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "php@{{% latest php %}}" ] - crons: - update: - spec: '0 0 * * *' - commands: - start: | - if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then - {{% vendor/cli %}} backup:create --yes --no-wait - {{% vendor/cli %}} source-operation:run update --no-wait --yes - fi -``` - -### Cron job timing - -The minimum time between cron jobs being triggered is 5 minutes. - -For each app container, only one cron job can run at a time. -If a new job is triggered while another is running, the new job is paused until the other completes. - -To minimize conflicts, a random offset is applied to all triggers. -The offset is a random number of seconds up to 20 minutes or the cron frequency, whichever is smaller. - -Crons are also paused while activities such as [backups](/environments/backup.md) are running. -The crons are queued to run after the other activity finishes. - -To run cron jobs in a timezone other than UTC, set the [timezone property](#primary-application-properties). - -### Paused crons - -[Preview environments](/glossary.md#preview-environment) are often used for a limited time and then abandoned. -While it's useful for environments under active development to have scheduled tasks, -unused environments don't need to run cron jobs. -To minimize unnecessary resource use, -crons on environments with no deployments are paused. - -This affects all preview environments, _and_ production environment that do not yet have a domain attached to them. - -Such environments with deployments within 14 days have crons with the status `running`. -If there haven't been any deployments within 14 days, the status is `paused`. - -You can see the status in the Console -or using the CLI by running `{{% vendor/cli %}} environment:info` and looking under `deployment_state`. - -#### Restarting paused crons - -If the crons on your preview environment are paused but you're still using them, -you can push changes to the environment or redeploy it. - -To restart crons without changing anything: - -{{< codetabs >}} - -+++ -title=In the Console -+++ - -1. In the Console, navigate to your project. -1. Open the environment where you'd like the crons to run. -1. Click `Redeploy` next to the cron status of `Paused`. - -<---> - -+++ -title=Using the CLI -+++ - -Run the following command: - -```bash -{{% vendor/cli %}} redeploy -``` - -{{< /codetabs >}} - -### Sizing hints - -The following table shows the properties that can be set in `sizing_hints`: - -| Name | Type | Default | Minimum | Description | -|-------------------|-----------|---------|---------|------------------------------------------------| -| `request_memory` | `integer` | 45 | 10 | The average memory consumed per request in MB. | -| `reserved_memory` | `integer` | 70 | 70 | The amount of memory reserved in MB. | - -See more about [PHP-FPM workers and sizing](/languages/php/fpm.md). - -## Source - -The following table shows the properties that can be set in `source`: - -| Name | Type | Required | Description | -|--------------|--------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------| -| `operations` | An operations dictionary | | Operations that can be applied to the source code. See [source operations](../source-operations.md) | -| `root` | `string` | | The path where the app code lives. Defaults to the root project directory. Useful for [multi-app setups](../multi-app/_index.md). | - -## Container profile - -By default, {{% vendor/name %}} allocates a container profile to each app and service depending on the range of resources it’s -expected to need. - -Each container profile gives you access to a specific list of CPU and RAM combinations. -Using the {{% vendor/name %}} CLI or Console, you can then pick a CPU and RAM combination for each of your apps and services. - -- [Container profile types and resources](/manage-resources/adjust-resources.md#advanced-container-profiles) -- [Default container profiles](/manage-resources/adjust-resources.md#default-container-profiles) for runtime and service - containers -- [Customize resources using the `container_profile` key](/manage-resources/adjust-resources.md#adjust-a-container-profile) - -## Additional hosts - -If you're using a private network with specific IP addresses you need to connect to, -you might want to map those addresses to hostnames to better remember and organize them. -In such cases, you can add a map of those IP addresses to whatever hostnames you like. -Then when your app tries to access the hostname, it's sent to the proper IP address. - -So in the following example, if your app tries to access `api.example.com`, it's sent to `192.0.2.23`. - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - stack: [ "php@{{% latest php %}}" ] - additional_hosts: - api.example.com: "192.0.2.23" - web.example.com: "203.0.113.42" -``` - -This is equivalent to adding the mapping to the `/etc/hosts` file for the container. diff --git a/sites/upsun/src/create-apps/app-reference/single-runtime-image.md b/sites/upsun/src/create-apps/app-reference/single-runtime-image.md index 752d9c424b..b72b473dea 100644 --- a/sites/upsun/src/create-apps/app-reference/single-runtime-image.md +++ b/sites/upsun/src/create-apps/app-reference/single-runtime-image.md @@ -37,26 +37,29 @@ and `backend` above). The column _Set in instance?_ defines whether the given property can be overridden within a `web` or `workers` instance. To override any part of a property, you have to provide the entire property. +- **Note:** Except for the `build`, `dependencies`, and `runtime` keys, the keys listed below are available in **both** the single-runtime and composable image types. Clicking the link for their details leads you to a separate topic for that property. Descriptions for properties that are **unique** to this image type are provided later in this topic. + + | Name | Type | Required | Set in instance? | Description | |---------------------|--------------------------------------------------------------------------------------------|----------|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `type` | A [type](#types) | Yes | No | The base image to use with a specific app language. Format: `runtime:version`. | -| `container_profile` | A [container profile](/manage-resources/adjust-resources.md#advanced-container-profiles) | | Yes | Container profile of the application. | -| `relationships` | A dictionary of [relationships](#relationships) | | Yes | Connections to other services and apps. | -| `mounts` | A dictionary of [mounts](#mounts) | | Yes | Directories that are writable even after the app is built. Allocated disk for mounts is defined with a separate resource configuration call using `{{% vendor/cli %}} resources:set`. | -| `web` | A [web instance](#web) | | N/A | How the web application is served. | -| `workers` | A [worker instance](#workers) | | N/A | Alternate copies of the application to run as background processes. | +| [`type`](#types) | A type | Yes | No | The base image to use with a specific app language. Format: `runtime:version`. | +| [`container_profile`](/create-apps/image-properties/container_profile.md) | A container profile | | Yes | Container profile of the application. | +| [`relationships`](/create-apps/image-properties/relationships.md) | A dictionary of relationships | | Yes | Connections to other services and apps. | +| [`mounts`](/create-apps/image-properties/mounts.md) | A dictionary of mounts | | Yes | Directories that are writable even after the app is built. Allocated disk for mounts is defined with a separate resource configuration call using `{{% vendor/cli %}} resources:set`. | +| [`web`](/create-apps/image-properties/web.md) | A web instance | | N/A | How the web application is served. | +| [`workers`](/create-apps/image-properties/workers.md) | A worker instance | | N/A | Alternate copies of the application to run as background processes. | | `timezone` | `string` | | No | The timezone for crons to run. Format: a [TZ database name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Defaults to `UTC`, which is the timezone used for all logs no matter the value here. See also [app runtime timezones](../timezone.md) | -| `access` | An [access dictionary](#access) | | Yes | Access control for roles accessing app environments. | -| `variables` | A [variables dictionary](#variables) | | Yes | Variables to control the environment. | -| `firewall` | A [firewall dictionary](#firewall) | | Yes | Outbound firewall rules for the application. | -| `build` | A [build dictionary](#build) | | No | What happens when the app is built. | -| `dependencies` | A [dependencies dictionary](#dependencies) | | No | What global dependencies to install before the `build` hook is run. | -| `hooks` | A [hooks dictionary](#hooks) | | No | What commands run at different stages in the build and deploy process. | -| `crons` | A [cron dictionary](#crons) | | No | Scheduled tasks for the app. | -| `source` | A [source dictionary](#source) | | No | Information on the app's source code and operations that can be run on it. | -| `runtime` | A [runtime dictionary](#runtime) | | No | Customizations to your PHP runtime. | -| `additional_hosts` | An [additional hosts dictionary](#additional-hosts) | | Yes | Maps of hostnames to IP addresses. | -| `operations` | A [dictionary of Runtime operations](/create-apps/runtime-operations.md) | | No | Runtime operations for the application. | +| [`access`](/create-apps/image-properties/access.md) | An access dictionary | | Yes | Access control for roles accessing app environments. | +| [`variables`](/create-apps/image-properties/variables.md) | A variables dictionary | | Yes | Variables to control the environment. | +| [`firewall`](/create-apps/image-properties/firewall.md) | A firewall dictionary | | Yes | Outbound firewall rules for the application. | +| [`build`](#build) | A build dictionary | | No | What happens when the app is built. | +| [`dependencies`](#dependencies) | A dependencies dictionary | | No | What global dependencies to install before the `build` hook is run. | +| [`hooks`](/create-apps/image-properties/hooks.md) | A hooks dictionary | | No | What commands run at different stages in the build and deploy process. | +| [`crons`](/create-apps/image-properties/crons.md) | A cron dictionary | | No | Scheduled tasks for the app. | +| [`source`](/create-apps/image-properties/source.md) | A source dictionary | | No | Information on the app's source code and operations that can be run on it. | +| [`runtime`](#runtime) | A runtime dictionary | | No | Customizations to your PHP runtime. | +| [`additional_hosts`](/create-apps/image-properties/additional_hosts.md) | An additional hosts dictionary | | Yes | Maps of hostnames to IP addresses. | +| [`operations`](/create-apps/runtime-operations.md) | A dictionary of runtime operations | | No | Runtime operations for the application. | ## Root directory @@ -78,7 +81,7 @@ to the above. To specify another directory, for example for a [multi-app project](../multi-app/_index.md), use the [`source.root` property](#source). -## Types +## `type` {#types} {{% note theme="info" %}} You can now use the {{% vendor/name %}} composable image (BETA) to install runtimes and tools in your application container. @@ -134,215 +137,6 @@ Console or the `{{% vendor/cli %}} resources:set` command. For more information, see how to [manage resources](/manage-resources.md). -## Relationships - -To allow containers in your project to communicate with one another, -you need to define relationships between them. -You can define a relationship between an app and a service, or [between two apps](/create-apps/multi-app/relationships.md). - -The quickest way to define a relationship between your app and a service -is to use the service's default endpoint.
-However, some services allow you to define multiple databases, cores, and/or permissions. -In these cases, you can't rely on default endpoints. -Instead, you can explicitly define multiple endpoints when setting up your relationships. - -{{< note >}} -App containers don't have a default endpoint like services. -To connect your app to another app in your project, -you need to explicitly define the `http` endpoint as the endpoint to connect both apps.
-For more information, see how to [define relationships between your apps](/create-apps/multi-app/relationships.md). -{{< /note >}} - -{{< note title="Availability" theme="info">}} - -New syntax (default and explicit endpoints) described below is supported by most, but not all, image types -(`Relationship 'SERVICE_NAME' of application 'app' ... targets a service without a valid default endpoint configuration.`). -This syntax is currently being rolled out for all images. -If you encounter this error, use the "legacy" {{% vendor/name %}} configuration noted at the bottom of this section. - -{{< /note >}} - -To define a relationship between your app and a service: - -{{< codetabs >}} - -+++ -title=Using default endpoints -+++ - -Use the following configuration: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - {{% variable "SERVICE_NAME" %}}: -``` - -The `SERVICE_NAME` is the name of the service as defined in its [configuration](/add-services/_index.md). -It is used as the relationship name, and associated with a `null` value. -This instructs {{% vendor/name %}} to use the service's default endpoint to connect your app to the service. - -For example, if you define the following configuration: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - mariadb: -``` - -{{% vendor/name %}} looks for a service named `mariadb` in your `{{% vendor/configfile "services" %}}` file, -and connects your app to it through the service's default endpoint. - -For reference, the equivalent configuration using explicit endpoints would be the following: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - mariadb: - service: mariadb - endpoint: mysql -``` - -You can define any number of relationships in this way: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - mariadb: - redis: - elasticsearch: -``` - -{{< note title="Tip" theme="info" >}} - -An even quicker way to define many relationships is to use the following single-line configuration: - -```yaml {configFile="services"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: {{{< variable "SERVICE_NAME_A" >}}, {{< variable "SERVICE_NAME_B" >}}, {{< variable "SERVICE_NAME_C" >}}} - -services: - {{< variable "SERVICE_NAME_A" >}}: - type: mariadb:{{% latest "mariadb" %}} - {{< variable "SERVICE_NAME_B" >}}: - type: redis:{{% latest "redis" %}} - {{< variable "SERVICE_NAME_C" >}}: - type: elasticsearch:{{% latest "elasticsearch" %}} -``` - -{{< /note >}} - -<---> - -+++ -title=Using explicit endpoints -+++ - -Use the following configuration: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - {{% variable "RELATIONSHIP_NAME" %}}: - service: {{% variable "SERVICE_NAME" %}} - endpoint: {{% variable "ENDPOINT_NAME" %}} -``` - -- `RELATIONSHIP_NAME` is the name you want to give to the relationship. -- `SERVICE_NAME` is the name of the service as defined in its [configuration](/add-services/_index.md). -- `ENDPOINT_NAME` is the endpoint your app will use to connect to the service (refer to the service reference to know which value to use). - -For example, to define a relationship named `database` that connects your app to a service called `mariadb` through the `db1` endpoint, -use the following configuration: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - database: # The name of the relationship. - service: mariadb - endpoint: db1 -``` - -For more information on how to handle multiple databases, multiple cores, -and/or different permissions with services that support such features, -see each service's dedicated page: - - - [MariaDB/MySQL](/add-services/mysql/_index.md#multiple-databases) (multiple databases and permissions) - - [PostgreSQL](/add-services/postgresql/_index.md#multiple-databases) (multiple databases and permissions) - - [Redis](/add-services/redis/_index.md#multiple-databases) (multiple databases) - - [Solr](add-services/solr/_index.md#solr-6-and-later) (multiple cores) - - [Vault KMS](add-services/vault.md#multiple-endpoints-example) (multiple permissions) - - You can add as many relationships as you want to your app configuration, - using both default and explicit endpoints according to your needs: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - database1: - service: mariadb - endpoint: admin - database2: - service: mariadb - endpoint: legacy - cache: - service: redis - search: - service: elasticsearch -``` - -{{< /codetabs >}} - -{{< note theme="info" title="Legacy" >}} - -The following legacy syntax for specifying relationships is still supported by {{% vendor/name %}}: - -```yaml {configFile="app"} -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - : ":" - -services: - SERVICE_NAME_A: - type: mariadb:{{% latest "mariadb" %}} -``` - -For example: - -```yaml -applications: - {{% variable "APP_NAME" %}}: - # ... - relationships: - database: "db:mysql" - -services: - db: - type: mariadb:{{% latest "mariadb" %}} -``` - -Feel free to use this until the default and explicit endpoint syntax is supported on all images. - -{{< /note >}} - ## Available disk space Disk for application containers are not committed to YAML files, but instead managed over the API using either the @@ -357,635 +151,7 @@ You can decrease the size of an existing disk for an app. If you do so, be aware - Backups from before the downsize are incompatible and can no longer be used. You need to [create new backups](/environments/backup.md). - The downsize fails if there’s more data on the disk than the desired size. -## Mounts - -After your app is built, its file system is read-only. -To make changes to your app's code, you need to use Git. - -For enhanced flexibility, {{% vendor/name %}} allows you to define and use writable directories called "mounts". -Mounts give you write access to files generated by your app (such as cache and log files) -and uploaded files without going through Git. - -When you define a mount, you are mounting an external directory to your app container, -much like you would plug a hard drive into your computer to transfer data. - -{{% note %}} - -- Mounts aren't available during the build -- When you [back up an environment](/environments/backup.md), the mounts on that environment are backed up too - -{{% /note %}} - -### Define a mount - -To define a mount, use the following configuration: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: nodejs:{{% latest "nodejs" %}} - mounts: - '{{< variable "MOUNT_PATH" >}}': - source: {{< variable "MOUNT_TYPE" >}} - source_path: {{< variable "SOURCE_PATH_LOCATION" >}} -``` - -{{< variable "MOUNT_PATH" >}} is the path to your mount **within the app container** (relative to the app's root). -If you already have a directory with that name, you get a warning that it isn't accessible after the build. -See how to [troubleshoot the warning](../troubleshoot-mounts.md#overlapping-folders). - -| Name | Type | Required | Description | -| ------------- | -------------------- | -------- | ----------- | -| `source` | `storage`, `instance`, `tmp` (also called `temporary`), or `service` | Yes | Specifies the type of the mount:

- By design, `storage` mounts can be shared between instances of the same app. You can also configure them so they are [shared between different apps](#share-a-mount-between-several-apps).

-`instance` mounts are local mounts. Unique to your app, they are useful to store files that remain local to the app instance, such as application logs.

- `tmp` (or `temporary`) mounts are local ephemeral mounts, where an external directory is mounted to the `/tmp` directory of your app.
The content of a `tmp` mount **may be removed during infrastructure maintenance operations**. Therefore, `tmp` mounts allow you to **store files that you’re not afraid to lose**, such as your application cache that can be seamlessly rebuilt.
Note that the `/tmp` directory has **a maximum allocation of 8 GB**.

- `service` mounts can be useful if you want to explicitly define and use a [Network Storage](/add-services/network-storage.md) service to share data between different apps (instead of using a `storage` mount).| -| `source_path` | `string` | No | Specifies where the mount points **inside the [external directory](#mounts)**.

- If you explicitly set a `source_path`, your mount points to a specific subdirectory in the external directory.

- If the `source_path` is an empty string (`""`), your mount points to the entire external directory.

- If you don't define a `source_path`, {{% vendor/name %}} uses the {{< variable "MOUNT_PATH" >}} as default value, without leading or trailing slashes.
For example, if your mount lives in the `/web/uploads/` directory in your app container, it will point to a directory named `web/uploads` in the external directory.

**WARNING:** Changing the name of your mount affects the `source_path` when it's undefined. See [how to ensure continuity](#ensure-continuity-when-changing-the-name-of-your-mount) and maintain access to your files. | -| `service` | `string` | | The purpose of the `service` key depends on your use case.

In a multi-app context where a `storage` mount is shared between apps, `service` is required. Its value is the name of the app whose mount you want to share. See how to [share a mount between several apps](#share-a-mount-between-several-apps).

In a multi-app context where a [Network Storage service](/add-services/network-storage.md) (`service` mount) is shared between apps, `service` is required and specifies the name of that Network Storage. | - -The accessibility to the web of a mounted directory depends on the [`web.locations` configuration](#web). -Files can be all public, all private, or with different rules for different paths and file types. - -Note that when you remove a `tmp` mount from your `{{< vendor/configfile "app" >}}` file, -the mounted directory isn't deleted. -The files still exist on disk until manually removed, -or until the app container is moved to another host during a maintenance operation. - -### Example configuration - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: nodejs:20 - mounts: - 'web/uploads': - source: storage - source_path: uploads - '/.tmp_platformsh': - source: tmp - source_path: files/.tmp_platformsh - '/build': - source: storage - source_path: files/build - '/.cache': - source: tmp - source_path: files/.cache - '/node_modules/.cache': - source: tmp - source_path: files/node_modules/.cache -``` - -### Ensure continuity when changing the name of your mount - -Changing the name of your mount affects the default `source_path`. - -Say you have a `/my/cache/` mount with an undefined `source_path`: - -```yaml {configFile="app"} -applications: - myapp: - mounts: - '/my/cache/': - source: tmp -``` - -If you rename the mount to `/cache/files/`, it will point to a new, empty `/cache/files/` directory. - -To ensure continuity, you need to explicitly define the `source_path` as the previous name of the mount, without leading -or trailing slashes: - - ```yaml {configFile="app"} -applications: - myapp: - mounts: - '/cache/files/': - source: tmp - source_path: my/cache -``` - -The `/cache/files/` mount will point to the original `/my/cache/` directory, maintaining access to all your existing -files in that directory. - -### Share a mount between several apps - -By design, [`storage` mounts](#mounts) are shared **between different instances of the same app**, -which enables [horizontal scaling](/manage-resources/_index.md). - -In a [multi-application context](/create-apps/multi-app/_index.md), -you can even share a `storage` mount **between different applications** in the same project. - -To do so, you need to define a `storage` mount in each of your app containers, -and point each of those mounts to the same shared external network directory. - -Use the following configuration: - -```yaml {configFile="app"} -applications: - app1: - mounts: - '{{< variable "MOUNT_PATH_1" >}}': - source: storage - source_path: {{< variable "SOURCE_PATH_LOCATION" >}} - - app2: - mounts: - '{{< variable "MOUNT_PATH_2" >}}': - source: storage - service: app1 - source_path: {{< variable "SOURCE_PATH_LOCATION" >}} -``` - -- {{< variable "MOUNT_PATH_1" >}} and {{< variable "MOUNT_PATH_2" >}} are the paths to each mount **within their - respective app container** (relative to the app's root). -- When configuring the first `storage` mount, you don't need to include the `service` key. - The first mount implicitly points to an external network directory. - The `service` key is required for subsequent mounts, to ensure they use the same external network directory as the - first mount. -- The `source_path` allows you to point each mount to the same subdirectory **within the shared external network - directory**. - -{{% note title = "Example" %}} - -You have a `backend` app and a `frontend` app. -You want both apps to share data from the same mount.
-Follow these steps: - -1. In your `backend` app configuration, define a `storage` mount: - - ```yaml {configFile="app"} - applications: - backend: - mounts: - var/uploads: #The path to your mount within the backend app container. - source: storage - source_path: backend/uploads #The path to the source of the mount within the external network directory. - ``` - - This creates a `storage` mount named `var/uploads` in the `backend` app container. - The mount points to the `backend/uploads` directory within an external network directory. - -2. In your `frontend` app configuration, define another `storage` mount: - - ```yaml {configFile="app"} - applications: - applications: - backend: - mounts: - var/uploads: - source: storage - source_path: backend/uploads - - frontend: - mounts: - web/uploads: #The path to your mount within the frontend app container. - source: storage - service: backend #The name of the other app, so the mount can point to the same external network directory as that other app's mount. - source_path: backend/uploads #The path to the source of the mount within the shared external network directory. - ``` - - This creates another `storage` mount named `web/uploads` in the `frontend` app container. - - The `service` key allows you to specify that the `web/uploads` mount should use the same external network directory - as the mount previously defined in the `backend` app container. - - The `source_path` key specifies which subdirectory within the external network directory both mounts should share ( - here, the `backend/uploads` directory). - -{{% /note %}} - -Note that another way to share data between apps through a mount is by -explicitly [defining a Network Storage service](/add-services/network-storage.md). - -### Overlapping mounts - -The locations of mounts as they are visible to application containers can overlap somewhat. -For example: - -```yaml {configFile="app"} -applications: - myapp: - # ... - mounts: - 'var/cache_a': - source: storage - source_path: cacheA - 'var/cache_b': - source: tmp - source_path: cacheB - 'var/cache_c': - source: instance - source_path: cacheC -``` - -In this case, it does not matter that each mount is of a different `source` type. -Each mount is restricted to a subfolder within `var`, and all is well. - -The following, however, is not allowed and will result in a failure: - -```yaml {configFile="app"} -applications: - myapp: - # ... - mounts: - 'var/': - source: storage - source_path: cacheA - 'var/cache_b': - source: tmp - source_path: cacheB - 'var/cache_c': - source: instance - source_path: cacheC -``` - -The `storage` mount type specifically exists to share data between instances of the same application, whereas `tmp` and `instance` are meant to restrict data to build time and runtime of a single application instance, respectively. -These allowances are not compatible, and will result in an error if pushed. - -## Web - -Use the `web` key to configure the web server running in front of your app. -Defaults may vary with a different [image `type`](#types). - -| Name | Type | Required | Description | -|-------------|--------------------------------------------|-------------------------------|------------------------------------------------------| -| `commands` | A [web commands dictionary](#web-commands) | See [note](#required-command) | The command to launch your app. | -| `upstream` | An [upstream dictionary](#upstream) | | How the front server connects to your app. | -| `locations` | A [locations dictionary](#locations) | | How the app container responds to incoming requests. | - -See some [examples of how to configure what's served](../web/_index.md). - -### Web commands - -| Name | Type | Required | Description | -|--------------|----------|-------------------------------|-----------------------------------------------------------------------------------------------------| -| `pre_start` | `string` | | Command run just prior to `start`, which can be useful when you need to run _per-instance_ actions. | -| `start` | `string` | See [note](#required-command) | The command to launch your app. If it terminates, it's restarted immediately. | -| `post_start` | `string` | | Command runs **before** adding the container to the router and **after** the `start` command. | - -{{< note theme="info" >}} -The `post_start` feature is _experimental_ and may change. Please share your feedback in the -[{{% vendor/name %}} discord](https://discord.gg/platformsh). -{{< /note >}} - -Example: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: 'python:{{% latest "python" %}}' - web: - commands: - start: 'uwsgi --ini conf/server.ini' -``` - -This command runs every time your app is restarted, regardless of whether or not new code is deployed. - -{{< note >}} - -Never "background" a start process using `&`. -That's interpreted as the command terminating and the supervisor process starts a second copy, -creating an infinite loop until the container crashes. -Just run it as normal and allow the {{% vendor/name %}} supervisor to manage it. - -{{< /note >}} - -#### Required command - -On all containers other than PHP, the value for `start` should be treated as required. - -On PHP containers, it's optional and defaults to starting PHP-FPM (`/usr/bin/start-php-app`). -It can also be set explicitly on a PHP container to run a dedicated process, -such as [React PHP](https://github.com/platformsh-examples/platformsh-example-reactphp) -or [Amp](https://github.com/platformsh-examples/platformsh-example-amphp). -See how to set up [alternate start commands on PHP](/languages/php/_index.md#alternate-start-commands). - -### Upstream - -| Name | Type | Required | Description | Default | -|-----------------|---------------------|----------|-------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------| -| `socket_family` | `tcp` or `unix` | | Whether your app listens on a Unix or TCP socket. | Defaults to `tcp` for all [image types](#types) except PHP; for PHP image types the default is `unix`. | -| `protocol` | `http` or `fastcgi` | | Whether your app receives incoming requests over HTTP or FastCGI. | Default varies based on [image `type`](#types). | - -For PHP, the defaults are configured for PHP-FPM and shouldn't need adjustment. -For all other containers, the default for `protocol` is `http`. - -The following example is the default on non-PHP containers: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: 'python:{{% latest "python" %}}' - web: - upstream: - socket_family: tcp - protocol: http -``` - -#### Where to listen - -Where to listen depends on your setting for `web.upstream.socket_family` (defaults to `tcp`). - -| `socket_family` | Where to listen | -|-----------------|---------------------------------------------------------------------------------------------------------------------------------------| -| `tcp` | The port specified by the [`PORT` environment variable](/development/variables/use-variables.md#use-provided-variables) | -| `unix` | The Unix socket file specified by the [`SOCKET` environment variable](/development/variables/use-variables.md#use-provided-variables) | - -If your application isn't listening at the same place that the runtime is sending requests, -you see `502 Bad Gateway` errors when you try to connect to your website. - -### Locations - -Each key in the `locations` dictionary is a path on your site with a leading `/`. -For `example.com`, a `/` matches `example.com/` and `/admin` matches `example.com/admin`. -When multiple keys match an incoming request, the most-specific applies. - -The following table presents possible properties for each location: - -| Name | Type | Default | Description | -|---------------------|------------------------------------------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `root` | `string` | | The directory to serve static assets for this location relative to the [app's root directory](#root-directory). Must be an actual directory inside the root directory. | -| `passthru` | `boolean` or `string` | `false` | Whether to forward disallowed and missing resources from this location to the app. A string is a path with a leading `/` to the controller, such as `/index.php`.

If your app is in PHP, when setting `passthru` to `true`, you might want to set `scripts` to `false` for enhanced security. This prevents PHP scripts from being executed from the specified location. You might also want to set `allow` to `false` so that not only PHP scripts can't be executed, but their source code also can't be delivered. | -| `index` | Array of `string`s or `null` | | Files to consider when serving a request for a directory. When set, requires access to the files through the `allow` or `rules` keys. | -| `expires` | `string` | `-1` | How long static assets are cached. The default means no caching. Setting it to a value enables the `Cache-Control` and `Expires` headers. Times can be suffixed with `ms` = milliseconds, `s` = seconds, `m` = minutes, `h` = hours, `d` = days, `w` = weeks, `M` = months/30d, or `y` = years/365d. If a `Cache-Control` appears on the `headers` configuration, `expires`, if set, will be ignored. Thus, make sure to set the `Cache-Control`'s `max-age` value when specifying a the header. | -| `allow` | `boolean` | `true` | Whether to allow serving files which don't match a rule. | -| `scripts` | `boolean` | | Whether to allow scripts to run. Doesn't apply to paths specified in `passthru`. Meaningful only on PHP containers. | -| `headers` | A headers dictionary | | Any additional headers to apply to static assets, mapping header names to values (see [Set custom headers on static content](/create-apps/web/custom-headers.html)). Responses from the app aren't affected. | -| `request_buffering` | A [request buffering dictionary](#request-buffering) | See below | Handling for chunked requests. | -| `rules` | A [rules dictionary](#rules) | | Specific overrides for specific locations. | - -#### Rules - -The rules dictionary can override most other keys according to a regular expression. -The key of each item is a regular expression to match paths exactly. -If an incoming request matches the rule, it's handled by the properties under the rule, -overriding any conflicting rules from the rest of the `locations` dictionary. - -Under `rules`, you can set all the other possible [`locations` properties](#locations) -except `root`, `index`, `rules` and `request_buffering`. - -In the following example, the `allow` key disallows requests for static files anywhere in the site. -This is overridden by a rule that explicitly allows common image file formats. - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: 'python:{{% latest "python" %}}' - web: - locations: - '/': - # Handle dynamic requests - root: 'public' - passthru: '/index.php' - # Disallow static files - allow: false - rules: - # Allow common image files only. - '\.(jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff2?|otf|ttf)$': - allow: true -``` - -#### Request buffering - -Request buffering is enabled by default to handle chunked requests as most app servers don't support them. -The following table shows the keys in the `request_buffering` dictionary: - -| Name | Type | Required | Default | Description | -|--------------------|-----------|----------|---------|-------------------------------------------| -| `enabled` | `boolean` | Yes | `true` | Whether request buffering is enabled. | -| `max_request_size` | `string` | | `250m` | The maximum size to allow in one request. | - -The default configuration would look like this: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: 'python:{{% latest "python" %}}' - web: - locations: - '/': - passthru: true - request_buffering: - enabled: true - max_request_size: 250m -``` - -## Workers - -Workers are exact copies of the code and compilation output as a `web` instance after a [`build` hook](#hooks). -They use the same container image. - -Workers can't accept public requests and so are suitable only for background tasks. -If they exit, they're automatically restarted. - -The keys of the `workers` definition are the names of the workers. -You can then define how each worker differs from the `web` instance using -the [top-level properties](#primary-application-properties). - -Each worker can differ from the `web` instance in all properties _except_ for: - -- `build` and `dependencies` properties, which must be the same -- `crons` as cron jobs don't run on workers -- `hooks` as the `build` hook must be the same - and the `deploy` and `post_deploy` hooks don't run on workers. - -A worker named `queue` that was small and had a different start command could look like this: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: 'python:{{% latest "python" %}}' - workers: - queue: - commands: - start: | - ./worker.sh -``` - -Workers require resource definition using `{{% vendor/cli %}} resources:set`, same as application containers. -For more information, see how to [manage resources](/manage-resources.md). - -## Access - -The `access` dictionary has one allowed key: - -| Name | Allowed values | Default | Description | -|-------|-------------------------------------|---------------|-----------------------------------------------------------------------| -| `ssh` | `admin`, `contributor`, or `viewer` | `contributor` | Defines the minimum role required to access app environments via SSH. | - -In the following example, only users with `admin` permissions for the -given [environment type](/administration/users.md#environment-type-roles) -can access the deployed environment via SSH: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: 'python:{{% latest "python" %}}' - access: - ssh: admin -``` - -## Variables - -{{% vendor/name %}} provides a number of ways to set [variables](/development/variables/_index.md). -Variables set in your app configuration have the lowest precedence, -meaning they're overridden by any conflicting values provided elsewhere. - -All variables set in your app configuration must have a prefix. -Some [prefixes have specific meanings](/development/variables/_index.md#variable-prefixes). - -Variables with the prefix `env` are available as a separate environment variable. -All other variables are available in -the [`PLATFORM_VARIABLES` environment variable](/development/variables/use-variables.md#use-provided-variables). - -The following example sets two variables: - -- A variable named `env:AUTHOR` with the value `Juan` that's available in the environment as `AUTHOR` -- A variable named `d8config:system.site:name` with the value `My site rocks` - that's available in the `PLATFORM_VARIABLES` environment variable - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: 'python:{{% latest "python" %}}' - variables: - env: - AUTHOR: 'Juan' - d8config: - "system.site:name": 'My site rocks' -``` - -You can also define and access more [complex values](/development/variables/use-variables.md#access-complex-values). - -## Firewall - -{{< premium-features/tiered "Elite and Enterprise" >}} - -Set limits in outbound traffic from your app with no impact on inbound requests. - -The `outbound` key is required and contains one or more rules. -The rules define what traffic is allowed; anything unspecified is blocked. - -Each rule has the following properties where at least one is required and `ips` and `domains` can't be specified -together: - -| Name | Type | Default | Description | -|-----------|---------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `ips` | Array of `string`s | `["0.0.0.0/0"]` | IP addresses in [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing). See a [CIDR format converter](https://www.ipaddressguide.com/cidr). | -| `domains` | Array of `string`s | | [Fully qualified domain names](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) to specify specific destinations by hostname. | -| `ports` | Array of `integer`s | | Ports from 1 to 65535 that are allowed. If any ports are specified, all unspecified ports are blocked. If no ports are specified, all ports are allowed. Port `25`, the SMTP port for sending email, is always blocked. | - -The default settings would look like this: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: 'python:{{% latest "python" %}}' - firewall: - outbound: - - ips: [ "0.0.0.0/0" ] -``` - -### Support for rules - -Where outbound rules for firewalls are supported in all environments. - -### Multiple rules - -Multiple firewall rules can be specified. -In such cases, a given outbound request is allowed if it matches _any_ of the defined rules. - -So in the following example requests to any IP on port 80 are allowed -and requests to 1.2.3.4 on either port 80 or 443 are allowed: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: 'python:{{% latest "python" %}}' - firewall: - outbound: - - ips: [ "1.2.3.4/32" ] - ports: [ 443 ] - - ports: [ 80 ] -``` - -### Outbound traffic to CDNs - -Be aware that many services are behind a content delivery network (CDN). -For most CDNs, routing is done via domain name, not IP address, -so thousands of domain names may share the same public IP addresses at the CDN. -If you allow the IP address of a CDN, you are usually allowing many or all of the other customers hosted behind that -CDN. - -### Outbound traffic by domain - -You can filter outbound traffic by domain. -Using domains in your rules rather than IP addresses is generally more specific and secure. -For example, if you use an IP address for a service with a CDN, -you have to allow the IP address for the CDN. -This means that you allow potentially hundreds or thousands of other servers also using the CDN. - -An example rule filtering by domain: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: 'python:{{% latest "python" %}}' - firewall: - outbound: - - protocol: tcp - domains: [ "api.stripe.com", "api.twilio.com" ] - ports: [ 80, 443 ] - - protocol: tcp - ips: [ "1.2.3.4/29","2.3.4.5" ] - ports: [ 22 ] -``` - -#### Determine which domains to allow - -To determine which domains to include in your filtering rules, -find the domains your site has requested the DNS to resolve. -Run the following command to parse your server’s `dns.log` file -and display all Fully Qualified Domain Names that have been requested: - -```bash -awk '/query\[[^P]\]/ { print $6 | "sort -u" }' /var/log/dns.log -``` - -The output includes all DNS requests that were made, including those blocked by your filtering rules. -It doesn't include any requests made using an IP address. - -Example output: - -```bash -facebook.com -fastly.com -upsun.com -www.google.com -www.upsun.com -``` - -## Build +## `build` {#build} The only property of the `build` dictionary is `flavor`, which specifies a default set of build tasks to run. Flavors are language-specific. @@ -1008,7 +174,7 @@ applications: flavor: none ``` -## Dependencies +## `dependencies` {#dependencies} Installs global dependencies as part of the build process. They're independent of your app's dependencies @@ -1048,294 +214,7 @@ applications: pm2: '^4.5.0' ``` -## Hooks - -There are three different hooks that run as part of the process of building and deploying your app. -These are places where you can run custom scripts. -They are: the `build` hook, the `deploy` hook, and the `post_deploy` hook. -Only the `build` hook is run for [worker instances](#workers), while [web instances](#web) run all three. - -The process is ordered as: - -1. Variables accessible at build time become available. -1. [Build flavor](#build) runs if applicable. -1. Any [dependencies](#dependencies) are installed. -1. The `build` hook is run. -1. The file system is changed to read only (except for any [mounts](#mounts)). -1. The app container starts. Variables accessible at runtime and services become available. -1. The `deploy` hook is run. -1. The app container begins accepting requests. -1. The `post_deploy` hook is run. - -Note that if an environment changes by no code changes, only the last step is run. -If you want the entire process to run, see how -to [manually trigger builds](/development/troubleshoot.md#manually-trigger-builds). - -### Writable directories during build - -During the `build` hook, there are three writeable directories: - -- `PLATFORM_APP_DIR`: - Where your code is checked out and the working directory when the `build` hook starts. - Becomes the app that gets deployed. -- `PLATFORM_CACHE_DIR`: - Persists between builds, but isn't deployed. - Shared by all builds on all branches. -- `/tmp`: - Isn't deployed and is wiped between each build. - Note that `PLATFORM_CACHE_DIR` is mapped to `/tmp` - and together they offer about 8GB of free space. - -### Hook failure - -Each hook is executed as a single script, so they're considered to have failed only if the final command in them fails. -To cause them to fail on the first failed command, add `set -e` to the beginning of the hook. - -If a `build` hook fails for any reason, the build is aborted and the deploy doesn't happen. -Note that this only works for `build` hooks -- -if other hooks fail, the app is still deployed. - -#### Automated testing - -It’s preferable that you set up and run automated tests in a dedicated CI/CD tool. -Relying on {{% vendor/name %}} hooks for such tasks can prove difficult. - -During the `build` hook, you can halt the deployment on a test failure but the following limitations apply: - -- Access to services such as databases, Redis, Vault KMS, and even writable mounts is disabled. - So any testing that relies on it is sure to fail. -- If you haven’t made changes to your app, an existing build image is reused and the build hook isn’t run. -- Test results are written into your app container, so they might get exposed to a third party. - -During the `deploy` hook, you can access services but **you can’t halt the deployment based on a test failure**. -Note that there are other downsides: - -- Your app container is read-only during the deploy hook, - so if your tests need to write reports and other information, you need to create a file mount for them. -- Your app can only be deployed once the deploy hook has been completed. - Therefore, running automated testing via the deploy hook generates slower deployments. -- Your environment isn’t available externally during the deploy hook. - Unit and integration testing might work without the environment being available, - but you can’t typically perform end-to-end testing until after the environment is up and available. - -## Crons - -The keys of the `crons` definition are the names of the cron jobs. -The names must be unique. - -If an application defines both a `web` instance and `worker` instances, cron jobs run only on the `web` instance. - -See how to [get cron logs](/increase-observability/logs/access-logs.md#container-logs). - -The following table shows the properties for each job: - -| Name | Type | Required | Description | -|--------------------|----------------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `spec` | `string` | Yes | The [cron specification](https://en.wikipedia.org/wiki/Cron#Cron_expression). To prevent competition for resources that might hurt performance, use `H` in definitions to indicate an unspecified but invariant time. For example, instead of using `0 * * * *` to indicate the cron job runs at the start of every hour, you can use `H * * * *` to indicate it runs every hour, but not necessarily at the start. This prevents multiple cron jobs from trying to start at the same time. | -| `commands` | A [cron commands dictionary](#cron-commands) | Yes | A definition of what commands to run when starting and stopping the cron job. | -| `shutdown_timeout` | `integer` | No | When a cron is canceled, this represents the number of seconds after which a `SIGKILL` signal is sent to the process to force terminate it. The default is `10` seconds. | -| `timeout` | `integer` | No | The maximum amount of time a cron can run before it's terminated. Defaults to the maximum allowed value of `86400` seconds (24 hours). | - -Note that you can [cancel pending or running crons](/environments/cancel-activity.md). - -### Cron commands - -| Name | Type | Required | Description | -|---------|----------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `start` | `string` | Yes | The command that's run. It's run in [Dash](https://en.wikipedia.org/wiki/Almquist_shell). | -| `stop` | `string` | No | The command that's issued to give the cron command a chance to shutdown gracefully, such as to finish an active item in a list of tasks. Issued when a cron task is interrupted by a user through the CLI or Console. If not specified, a `SIGTERM` signal is sent to the process. | - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: 'nodejs:{{% latest "nodejs" %}}' - crons: - mycommand: - spec: 'H * * * *' - commands: - start: sleep 60 && echo sleep-60-finished && date - stop: killall sleep - shutdown_timeout: 18 -``` - -In this example configuration, the [cron specification](#crons) uses the `H` syntax. - -### Example cron jobs - - -{{< codetabs >}} - -+++ -title=Drupal -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -type: 'php:{{% latest "php" %}}' -crons: - # Run Drupal's cron tasks every 19 minutes. - drupal: - spec: '*/19 * * * *' - commands: - start: 'cd web ; drush core-cron' - # But also run pending queue tasks every 7 minutes. - # Use an odd number to avoid running at the same time as the `drupal` cron. - drush-queue: - spec: '*/7 * * * *' - commands: - start: 'cd web ; drush queue-run aggregator_feeds' - {{< /snippet >}} -``` - -<---> - -+++ -title=Ruby on Rails -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -type: 'ruby:{{% latest "ruby" %}}' -crons: - # Execute a rake script every 19 minutes. - ruby: - spec: '*/19 * * * *' - commands: - start: 'bundle exec rake some:task' - {{< /snippet >}} -``` - -<---> - -+++ -title=Laravel -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -type: 'php:{{% latest "php" %}}' -crons: - # Run Laravel's scheduler every 5 minutes. - scheduler: - spec: '*/5 * * * *' - commands: - start: 'php artisan schedule:run' - {{< /snippet >}} -``` - -<---> - -+++ -title=Symfony -+++ - -```yaml {configFile="app"} -{{< snippet name="myapp" config="app" root="/" >}} -type: 'php:{{% latest "php" %}}' -crons: - # Take a backup of the environment every day at 5:00 AM. - snapshot: - spec: 0 5 * * * - commands: - start: | - # Only run for the production environment, aka main branch - if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then - croncape symfony ... - fi - {{< /snippet >}} -``` - -{{< /codetabs >}} - - -### Conditional crons - -If you want to set up customized cron schedules depending on the environment type, -define conditional crons. -To do so, use a configuration similar to the following: - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: 'php:{{% latest "php" %}}' - crons: - update: - spec: '0 0 * * *' - commands: - start: | - if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then - {{% vendor/cli %}} backup:create --yes --no-wait - {{% vendor/cli %}} source-operation:run update --no-wait --yes - fi -``` - -### Cron job timing - -The minimum time between cron jobs being triggered is 5 minutes. - -For each app container, only one cron job can run at a time. -If a new job is triggered while another is running, the new job is paused until the other completes. - -To minimize conflicts, a random offset is applied to all triggers. -The offset is a random number of seconds up to 20 minutes or the cron frequency, whichever is smaller. - -Crons are also paused while activities such as [backups](/environments/backup.md) are running. -The crons are queued to run after the other activity finishes. - -To run cron jobs in a timezone other than UTC, set the [timezone property](#primary-application-properties). - -### Paused crons - -[Preview environments](/glossary.md#preview-environment) are often used for a limited time and then abandoned. -While it's useful for environments under active development to have scheduled tasks, -unused environments don't need to run cron jobs. -To minimize unnecessary resource use, -crons on environments with no deployments are paused. - -This affects all preview environments, _and_ production environment that do not yet have a domain attached to them. - -Such environments with deployments within 14 days have crons with the status `running`. -If there haven't been any deployments within 14 days, the status is `paused`. - -You can see the status in the Console -or using the CLI by running `{{% vendor/cli %}} environment:info` and looking under `deployment_state`. - -#### Restarting paused crons - -If the crons on your preview environment are paused but you're still using them, -you can push changes to the environment or redeploy it. - -To restart crons without changing anything: - -{{< codetabs >}} - -+++ -title=In the Console -+++ - -1. In the Console, navigate to your project. -1. Open the environment where you'd like the crons to run. -1. Click `Redeploy` next to the cron status of `Paused`. - -<---> - -+++ -title=Using the CLI -+++ - -Run the following command: - -```bash -{{% vendor/cli %}} redeploy -``` - -{{< /codetabs >}} - -## Runtime +## `runtime` {#runtime} The following table presents the various possible modifications to your PHP runtime: @@ -1401,46 +280,3 @@ The following table shows the properties that can be set in `sizing_hints`: See more about [PHP-FPM workers and sizing](/languages/php/fpm.md). -## Source - -The following table shows the properties that can be set in `source`: - -| Name | Type | Required | Description | -|--------------|--------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------| -| `operations` | An operations dictionary | | Operations that can be applied to the source code. See [source operations](../source-operations.md) | -| `root` | `string` | | The path where the app code lives. Defaults to the root project directory. Useful for [multi-app setups](../multi-app/_index.md). | - -## Container profile - -By default, {{% vendor/name %}} allocates a container profile to each app and service depending on the range of resources it’s -expected to need. - -Each container profile gives you access to a specific list of CPU and RAM combinations. -Using the {{% vendor/name %}} CLI or Console, you can then pick a CPU and RAM combination for each of your apps and services. - -- [Container profile types and resources](/manage-resources/adjust-resources.md#advanced-container-profiles) -- [Default container profiles](/manage-resources/adjust-resources.md#default-container-profiles) for runtime and service - containers -- [Customize resources using the `container_profile` key](/manage-resources/adjust-resources.md#adjust-a-container-profile) - -## Additional hosts - -If you're using a private network with specific IP addresses you need to connect to, -you might want to map those addresses to hostnames to better remember and organize them. -In such cases, you can add a map of those IP addresses to whatever hostnames you like. -Then when your app tries to access the hostname, it's sent to the proper IP address. - -So in the following example, if your app tries to access `api.example.com`, it's sent to `192.0.2.23`. - -```yaml {configFile="app"} -applications: - myapp: - source: - root: "/" - type: 'php:{{% latest "php" %}}' - additional_hosts: - api.example.com: "192.0.2.23" - web.example.com: "203.0.113.42" -``` - -This is equivalent to adding the mapping to the `/etc/hosts` file for the container. diff --git a/sites/upsun/src/create-apps/image-properties/_index.md b/sites/upsun/src/create-apps/image-properties/_index.md new file mode 100644 index 0000000000..6c07b1cece --- /dev/null +++ b/sites/upsun/src/create-apps/image-properties/_index.md @@ -0,0 +1,12 @@ +--- +title: "Image properties" +sidebarTitle: "Image properties" +weight: 4 +description: Details about image properties in the {{% vendor/name %}} config.yaml file +--- + +**Note:** The properties below are available in **both** [single-runtime image](/create-apps/app-reference/single-runtime-image.md#) and [composable image](/create-apps/app-reference/composable-image.md#) types. + +For most of these properties, the syntax and details are the same for both image types. Differences in meaning and syntax are noted as needed for each property. + +To learn about the properties that are **unique to each image type**, refer to the top-level properties described in the [single-runtime image](/create-apps/app-reference/single-runtime-image.md#) topic or the primary application properties described in the [composable image](/create-apps/app-reference/composable-image.md#) topic. diff --git a/sites/upsun/src/create-apps/image-properties/access.md b/sites/upsun/src/create-apps/image-properties/access.md new file mode 100644 index 0000000000..d91de2e62f --- /dev/null +++ b/sites/upsun/src/create-apps/image-properties/access.md @@ -0,0 +1,54 @@ +--- +title: "`access`" +weight: 4 +description: An access dictionary that defines the access control for roles accessing app environments. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](/create-apps/app-reference/composable-image.md#primary-application-properties) images. + +The `access` dictionary has one allowed key: + +| Name | Allowed values | Default | Description | +|-------|-------------------------------------|---------------|-----------------------------------------------------------------------| +| `ssh` | `admin`, `contributor`, or `viewer` | `contributor` | Defines the minimum role required to access app environments via SSH. | + +In the following example, only users with `admin` permissions for the +given [environment type](/administration/users.md#environment-type-roles) +can access the deployed environment via SSH: + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: 'python:{{% latest "python" %}}' + access: + ssh: admin +``` + +<---> + ++++ +title=Composable image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + stack: [ "python@{{% latest python %}}" ] + access: + ssh: admin +``` + +{{< /codetabs >}} + diff --git a/sites/upsun/src/create-apps/image-properties/additional_hosts.md b/sites/upsun/src/create-apps/image-properties/additional_hosts.md new file mode 100644 index 0000000000..6e3b629686 --- /dev/null +++ b/sites/upsun/src/create-apps/image-properties/additional_hosts.md @@ -0,0 +1,46 @@ +--- +title: "`additional_hosts`" +weight: 4 +description: An additional hosts dictionary that maps hostnames to IP addresses. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](/create-apps/app-reference/composable-image.md#primary-application-properties) images. + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: 'php:{{% latest "php" %}}' + additional_hosts: + api.example.com: "192.0.2.23" + web.example.com: "203.0.113.42" +``` +<---> + ++++ +title=Composable image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + stack: [ "php@{{% latest php %}}" ] + additional_hosts: + api.example.com: "192.0.2.23" + web.example.com: "203.0.113.42" +``` + +{{< /codetabs >}} + +This is equivalent to adding the mapping to the `/etc/hosts` file for the container. diff --git a/sites/upsun/src/create-apps/image-properties/container_profile.md b/sites/upsun/src/create-apps/image-properties/container_profile.md new file mode 100644 index 0000000000..0f83f826c8 --- /dev/null +++ b/sites/upsun/src/create-apps/image-properties/container_profile.md @@ -0,0 +1,19 @@ +--- +title: "`container_profile`" +weight: 4 +description: Defines the container profile of the application. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](/create-apps/app-reference/composable-image.md#primary-application-properties) images. + +By default, {{% vendor/name %}} allocates a container profile to each app and service depending on the range of resources it’s +expected to need. + +Each container profile gives you access to a specific list of CPU and RAM combinations. +Using the {{% vendor/name %}} CLI or Console, you can then pick a CPU and RAM combination for each of your apps and services. + +- [Default container profiles](/manage-resources/adjust-resources.md#default-container-profiles) for runtime and service containers +- [Advanced: Container profile types and resources](/manage-resources/adjust-resources.md#advanced-container-profiles) +- [Customize resources using the `container_profile` key](/manage-resources/adjust-resources.md#adjust-a-container-profile) \ No newline at end of file diff --git a/sites/upsun/src/create-apps/image-properties/crons.md b/sites/upsun/src/create-apps/image-properties/crons.md new file mode 100644 index 0000000000..dffc2a0fdc --- /dev/null +++ b/sites/upsun/src/create-apps/image-properties/crons.md @@ -0,0 +1,358 @@ +--- +title: "`crons`" +weight: 4 +description: A cron dictionary that defines scheduled tasks for the app. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](/create-apps/app-reference/composable-image.md#primary-application-properties) images. + +The keys of the `crons` definition are the names of the cron jobs. +The names must be unique. + +If an application defines both a `web` instance and `worker` instances, cron jobs run only on the `web` instance. + +See how to [get cron logs](/increase-observability/logs/access-logs.md#container-logs). + +The following table shows the properties for each job: + +| Name | Type | Required | Description | +|--------------------|----------------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `spec` | `string` | Yes | The [cron specification](https://en.wikipedia.org/wiki/Cron#Cron_expression). To prevent competition for resources that might hurt performance, use `H` in definitions to indicate an unspecified but invariant time. For example, instead of using `0 * * * *` to indicate the cron job runs at the start of every hour, you can use `H * * * *` to indicate it runs every hour, but not necessarily at the start. This prevents multiple cron jobs from trying to start at the same time. | +| `commands` | A [cron commands dictionary](#cron-commands) | Yes | A definition of what commands to run when starting and stopping the cron job. | +| `shutdown_timeout` | `integer` | No | When a cron is canceled, this represents the number of seconds after which a `SIGKILL` signal is sent to the process to force terminate it. The default is `10` seconds. | +| `timeout` | `integer` | No | The maximum amount of time a cron can run before it's terminated. Defaults to the maximum allowed value of `86400` seconds (24 hours). | + +Note that you can [cancel pending or running crons](/environments/cancel-activity.md). + +### Cron commands + +| Name | Type | Required | Description | +|---------|----------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `start` | `string` | Yes | The command that's run. It's run in [Dash](https://en.wikipedia.org/wiki/Almquist_shell). | +| `stop` | `string` | No | The command that's issued to give the cron command a chance to shutdown gracefully, such as to finish an active item in a list of tasks. Issued when a cron task is interrupted by a user through the CLI or Console. If not specified, a `SIGTERM` signal is sent to the process. | + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: 'nodejs:{{% latest "nodejs" %}}' + crons: + mycommand: + spec: 'H * * * *' + commands: + start: sleep 60 && echo sleep-60-finished && date + stop: killall sleep + shutdown_timeout: 18 +``` + +In this example configuration, the [cron specification](#crons) uses the `H` syntax. + +### Single-runtime image: Example cron jobs + + +{{< codetabs >}} + ++++ +title=Drupal ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +type: 'php:{{% latest "php" %}}' +crons: + # Run Drupal's cron tasks every 19 minutes. + drupal: + spec: '*/19 * * * *' + commands: + start: 'cd web ; drush core-cron' + # But also run pending queue tasks every 7 minutes. + # Use an odd number to avoid running at the same time as the `drupal` cron. + drush-queue: + spec: '*/7 * * * *' + commands: + start: 'cd web ; drush queue-run aggregator_feeds' + {{< /snippet >}} +``` + +<---> + ++++ +title=Ruby on Rails ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +type: 'ruby:{{% latest "ruby" %}}' +crons: + # Execute a rake script every 19 minutes. + ruby: + spec: '*/19 * * * *' + commands: + start: 'bundle exec rake some:task' + {{< /snippet >}} +``` + +<---> + ++++ +title=Laravel ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +type: 'php:{{% latest "php" %}}' +crons: + # Run Laravel's scheduler every 5 minutes. + scheduler: + spec: '*/5 * * * *' + commands: + start: 'php artisan schedule:run' + {{< /snippet >}} +``` + +<---> + ++++ +title=Symfony ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +type: 'php:{{% latest "php" %}}' +crons: + # Take a backup of the environment every day at 5:00 AM. + snapshot: + spec: 0 5 * * * + commands: + start: | + # Only run for the production environment, aka main branch + if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then + croncape symfony ... + fi + {{< /snippet >}} +``` + +{{< /codetabs >}} + + +### Composable image: Example cron jobs + + +{{< codetabs >}} + ++++ +title=Drupal ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +stack: [ "php@{{% latest php %}}" ] +crons: + # Run Drupal's cron tasks every 19 minutes. + drupal: + spec: '*/19 * * * *' + commands: + start: 'cd web ; drush core-cron' + # But also run pending queue tasks every 7 minutes. + # Use an odd number to avoid running at the same time as the `drupal` cron. + drush-queue: + spec: '*/7 * * * *' + commands: + start: 'cd web ; drush queue-run aggregator_feeds' +{{< /snippet >}} +``` + +<---> + ++++ +title=Ruby on Rails ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +stack: [ "ruby@{{% latest ruby %}}" ] +crons: + # Execute a rake script every 19 minutes. + ruby: + spec: '*/19 * * * *' + commands: + start: 'bundle exec rake some:task' +{{< /snippet >}} +``` + +<---> + ++++ +title=Laravel ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +stack: [ "php@{{% latest php %}}" ] +crons: + # Run Laravel's scheduler every 5 minutes. + scheduler: + spec: '*/5 * * * *' + commands: + start: 'php artisan schedule:run' +{{< /snippet >}} +``` + +<---> + ++++ +title=Symfony ++++ + +```yaml {configFile="app"} +{{< snippet name="myapp" config="app" root="/" >}} +stack: [ "php@{{% latest php %}}" ] +crons: + # Take a backup of the environment every day at 5:00 AM. + snapshot: + spec: 0 5 * * * + commands: + start: | + # Only run for the production environment, aka main branch + if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then + croncape symfony ... + fi +{{< /snippet >}} +``` + +{{< /codetabs >}} + + +### Conditional crons + +If you want to set up customized cron schedules depending on the environment type, +define conditional crons. +To do so, use a configuration similar to the following: + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: 'php:{{% latest "php" %}}' + crons: + update: + spec: '0 0 * * *' + commands: + start: | + if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then + {{% vendor/cli %}} backup:create --yes --no-wait + {{% vendor/cli %}} source-operation:run update --no-wait --yes + fi +``` +<---> + ++++ +title=Composable image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + stack: [ "php@{{% latest php %}}" ] + crons: + update: + spec: '0 0 * * *' + commands: + start: | + if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then + {{% vendor/cli %}} backup:create --yes --no-wait + {{% vendor/cli %}} source-operation:run update --no-wait --yes + fi +``` + +{{< /codetabs >}} + + + +### Cron job timing + +The minimum time between cron jobs being triggered is 5 minutes. + +For each app container, only one cron job can run at a time. +If a new job is triggered while another is running, the new job is paused until the other completes. + +To minimize conflicts, a random offset is applied to all triggers. +The offset is a random number of seconds up to 20 minutes or the cron frequency, whichever is smaller. + +Crons are also paused while activities such as [backups](/environments/backup.md) are running. +The crons are queued to run after the other activity finishes. + +To run cron jobs in a timezone other than UTC, set the `timezone` property property as described for the image type ([single-runtime image](/create-apps/app-reference/single-runtime-image.md#primary-application-properties) or +[composable image](/create-apps/app-reference/composable-image.md#primary-application-properties)). + +To run cron jobs in a timezone other than UTC, set the [timezone property](#primary-application-properties). + +### Paused crons + +[Preview environments](/glossary.md#preview-environment) are often used for a limited time and then abandoned. +While it's useful for environments under active development to have scheduled tasks, +unused environments don't need to run cron jobs. +To minimize unnecessary resource use, +crons on environments with no deployments are paused. + +This affects all preview environments _and_ production environments that do not yet have a domain attached to them. + +Such environments with deployments within 14 days have crons with the status `running`. +If there haven't been any deployments within 14 days, the status is `paused`. + +You can see the status in the Console +or using the CLI by running `{{% vendor/cli %}} environment:info` and looking under `deployment_state`. + +#### Restarting paused crons + +If the crons on your preview environment are paused but you're still using them, +you can push changes to the environment or redeploy it. + +To restart crons without changing anything: + +{{< codetabs >}} + ++++ +title=In the Console ++++ + +1. In the Console, navigate to your project. +1. Open the environment where you'd like the crons to run. +1. Click `Redeploy` next to the cron status of `Paused`. + +<---> + ++++ +title=Using the CLI ++++ + +Run the following command: + +```bash +{{% vendor/cli %}} redeploy +``` + +{{< /codetabs >}} + +### Composable image only: Sizing hints + +The following table shows the properties that can be set in `sizing_hints`: + +| Name | Type | Default | Minimum | Description | +|-------------------|-----------|---------|---------|------------------------------------------------| +| `request_memory` | `integer` | 45 | 10 | The average memory consumed per request in MB. | +| `reserved_memory` | `integer` | 70 | 70 | The amount of memory reserved in MB. | + +See more about [PHP-FPM workers and sizing](/languages/php/fpm.md). diff --git a/sites/upsun/src/create-apps/image-properties/firewall.md b/sites/upsun/src/create-apps/image-properties/firewall.md new file mode 100644 index 0000000000..f9e0be361b --- /dev/null +++ b/sites/upsun/src/create-apps/image-properties/firewall.md @@ -0,0 +1,208 @@ +--- +title: "`firewall`" +weight: 4 +description: A firewall dictionary that defines the outbound firewall rules for the application. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](/create-apps/app-reference/composable-image.md#primary-application-properties) images. + +This property enables you to set limits in outbound traffic from your app with no impact on inbound requests. + +The `outbound` key is required and contains one or more rules. +The rules define what traffic is allowed; anything unspecified is blocked. + +Each rule has the following properties where at least one is required and `ips` and `domains` can't be specified +together: + +| Name | Type | Default | Description | +|-----------|---------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `ips` | Array of `string`s | `["0.0.0.0/0"]` | IP addresses in [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing). See a [CIDR format converter](https://www.ipaddressguide.com/cidr). | +| `domains` | Array of `string`s | | [Fully qualified domain names](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) to specify specific destinations by hostname. | +| `ports` | Array of `integer`s | | Ports from 1 to 65535 that are allowed. If any ports are specified, all unspecified ports are blocked. If no ports are specified, all ports are allowed. Port `25`, the SMTP port for sending email, is always blocked. | + +The default settings would look like this: + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: 'python:{{% latest "python" %}}' + firewall: + outbound: + - ips: [ "0.0.0.0/0" ] +``` + +<---> + ++++ +title=Composable image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + stack: [ "python@{{% latest python %}}" ] + firewall: + outbound: + - ips: [ "0.0.0.0/0" ] +``` + +{{< /codetabs >}} + + + +### Support for rules + +Where outbound rules for firewalls are supported in all environments. + +### Multiple rules + +Multiple firewall rules can be specified. +In such cases, a given outbound request is allowed if it matches _any_ of the defined rules. + +So in the following example requests to any IP on port 80 are allowed +and requests to 1.2.3.4 on either port 80 or 443 are allowed: + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: 'python:{{% latest "python" %}}' + firewall: + outbound: + - ips: [ "1.2.3.4/32" ] + ports: [ 443 ] + - ports: [ 80 ] +``` + +<---> + ++++ +title=Composable image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + stack: [ "python@{{% latest python %}}" ] + firewall: + outbound: + - ips: [ "1.2.3.4/32" ] + ports: [ 443 ] + - ports: [ 80 ] +``` + +{{< /codetabs >}} + + +### Outbound traffic to CDNs + +Be aware that many services are behind a content delivery network (CDN). +For most CDNs, routing is done via domain name, not IP address, +so thousands of domain names may share the same public IP addresses at the CDN. +If you allow the IP address of a CDN, you are usually allowing many or all of the other customers hosted behind that +CDN. + +### Outbound traffic by domain + +You can filter outbound traffic by domain. +Using domains in your rules rather than IP addresses is generally more specific and secure. +For example, if you use an IP address for a service with a CDN, +you have to allow the IP address for the CDN. +This means that you allow potentially hundreds or thousands of other servers also using the CDN. + +An example rule filtering by domain: + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: 'python:{{% latest "python" %}}' + firewall: + outbound: + - protocol: tcp + domains: [ "api.stripe.com", "api.twilio.com" ] + ports: [ 80, 443 ] + - protocol: tcp + ips: [ "1.2.3.4/29","2.3.4.5" ] + ports: [ 22 ] +``` + +<---> + ++++ +title=Composable image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + stack: [ "python@{{% latest python %}}" ] + firewall: + outbound: + - protocol: tcp + domains: [ "api.stripe.com", "api.twilio.com" ] + ports: [ 80, 443 ] + - protocol: tcp + ips: [ "1.2.3.4/29","2.3.4.5" ] + ports: [ 22 ] +``` + +{{< /codetabs >}} + + +#### Determine which domains to allow + +To determine which domains to include in your filtering rules, +find the domains your site has requested the DNS to resolve. +Run the following command to parse your server’s `dns.log` file +and display all Fully Qualified Domain Names that have been requested: + +```bash +awk '/query\[[^P]\]/ { print $6 | "sort -u" }' /var/log/dns.log +``` + +The output includes all DNS requests that were made, including those blocked by your filtering rules. +It doesn't include any requests made using an IP address. + +Example output: + +```bash +facebook.com +fastly.com +upsun.com +www.google.com +www.upsun.com +``` + + + diff --git a/sites/upsun/src/create-apps/image-properties/hooks.md b/sites/upsun/src/create-apps/image-properties/hooks.md new file mode 100644 index 0000000000..cc933b438a --- /dev/null +++ b/sites/upsun/src/create-apps/image-properties/hooks.md @@ -0,0 +1,103 @@ +--- +title: "`hooks`" +weight: 4 +description: A hooks dictionary that defines which commands run at different stages in the build and deploy process. +keywords: + - hooks + - hooks +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](/create-apps/app-reference/composable-image.md#primary-application-properties) images. + +There are three different hooks that run as part of the process of building and deploying your app. +These are places where you can run custom scripts. +They are: the `build` hook, the `deploy` hook, and the `post_deploy` hook. +Only the `build` hook is run for [worker instances](/create-apps/image-properties/workers.md), while [web instances](/create-apps/image-properties/web.md) run all three. + +The process is ordered as: + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +1. Variables accessible at build time become available. +1. [Build flavor](/create-apps/app-reference/single-runtime-image.md#build) runs if applicable. +1. Any [dependencies](/create-apps/app-reference/single-runtime-image.md##dependencies) are installed. +1. The `build` hook is run. +1. The file system is changed to read only, except for any [mounts](/create-apps/image-properties/mounts.md). +1. The app container starts. Variables accessible at runtime and services become available. +1. The `deploy` hook is run. +1. The app container begins accepting requests. +1. The `post_deploy` hook is run. + +<---> + ++++ +title=Composable image ++++ + +1. Variables accessible at build time become available. +1. The `build` hook is run. +1. The file system is changed to read only, except for any [mounts](/create-apps/image-properties/mounts.md). +1. The app container starts. Variables accessible at runtime and services become available. +1. The `deploy` hook is run. +1. The app container begins accepting requests. +1. The `post_deploy` hook is run. + +{{< /codetabs >}} + +Note that if an environment changes by no code changes, only the last step is run. +If you want the entire process to run, see how +to [manually trigger builds](/development/troubleshoot.md#manually-trigger-builds). + +### Writable directories during build + +During the `build` hook, there are three writeable directories: + +- `PLATFORM_APP_DIR`: + Where your code is checked out and the working directory when the `build` hook starts. + Becomes the app that gets deployed. +- `PLATFORM_CACHE_DIR`: + Persists between builds, but isn't deployed. + Shared by all builds on all branches. +- `/tmp`: + Isn't deployed and is wiped between each build. + Note that `PLATFORM_CACHE_DIR` is mapped to `/tmp` + and together they offer about 8GB of free space. + +### Hook failure + +Each hook is executed as a single script, so they're considered to have failed only if the final command in them fails. +To cause them to fail on the first failed command, add `set -e` to the beginning of the hook. + +If a `build` hook fails for any reason, the build is aborted and the deploy doesn't happen. +Note that this only works for `build` hooks -- +if other hooks fail, the app is still deployed. + +#### Automated testing + +It’s preferable that you set up and run automated tests in a dedicated CI/CD tool. +Relying on {{% vendor/name %}} hooks for such tasks can prove difficult. + +During the `build` hook, you can halt the deployment on a test failure but the following limitations apply: + +- Access to services such as databases, Redis, Vault KMS, and even writable mounts is disabled. + So any testing that relies on it is sure to fail. +- If you haven’t made changes to your app, an existing build image is reused and the build hook isn’t run. +- Test results are written into your app container, so they might get exposed to a third party. + +During the `deploy` hook, you can access services but **you can’t halt the deployment based on a test failure**. +Note that there are other downsides: + +- Your app container is read-only during the deploy hook, + so if your tests need to write reports and other information, you need to create a file mount for them. +- Your app can only be deployed once the deploy hook has been completed. + Therefore, running automated testing via the deploy hook generates slower deployments. +- Your environment isn’t available externally during the deploy hook. + Unit and integration testing might work without the environment being available, + but you can’t typically perform end-to-end testing until after the environment is up and available. + diff --git a/sites/upsun/src/create-apps/image-properties/mounts.md b/sites/upsun/src/create-apps/image-properties/mounts.md new file mode 100644 index 0000000000..1184a8895d --- /dev/null +++ b/sites/upsun/src/create-apps/image-properties/mounts.md @@ -0,0 +1,446 @@ +--- +title: "`mounts`" +weight: 4 +description: Directories that are writable even after the app is built. +--- + +Directories that are writable even after the app is built. Allocated disk for mounts is defined with a separate resource configuration call using `{{% vendor/cli %}} resources:set`. + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](/create-apps/app-reference/composable-image.md#primary-application-properties) images. + +After your app is built, its file system is read-only. +To make changes to your app's code, you need to use Git. + +For enhanced flexibility, {{% vendor/name %}} allows you to define and use writable directories called "mounts". +Mounts give you write access to files generated by your app (such as cache and log files) +and uploaded files without going through Git. + +When you define a mount, you are mounting an external directory to your app container, +much like you would plug a hard drive into your computer to transfer data. + +{{% note %}} + +- Mounts aren't available during the build +- When you [back up an environment](/environments/backup.md), the mounts on that environment are backed up too + +{{% /note %}} + +### Define a mount + +To define a mount, use the following configuration: + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: nodejs:{{% latest "nodejs" %}} + mounts: + '{{< variable "MOUNT_PATH" >}}': + source: {{< variable "MOUNT_TYPE" >}} + source_path: {{< variable "SOURCE_PATH_LOCATION" >}} +``` + +{{< variable "MOUNT_PATH" >}} is the path to your mount **within the app container** (relative to the app's root). +If you already have a directory with that name, you get a warning that it isn't accessible after the build. +See how to [troubleshoot the warning](../troubleshoot-mounts.md#overlapping-folders). + +| Name | Type | Required | Description | +| ------------- | -------------------- | -------- | ----------- | +| `source` | `storage`, `instance`, `tmp` (also called `temporary`), or `service` | Yes | Specifies the type of the mount:

- By design, `storage` mounts can be shared between instances of the same app. You can also configure them so they are [shared between different apps](#share-a-mount-between-several-apps).

-`instance` mounts are local mounts. Unique to your app, they are useful to store files that remain local to the app instance, such as application logs.

- `tmp` (or `temporary`) mounts are local ephemeral mounts, where an external directory is mounted to the `/tmp` directory of your app.
The content of a `tmp` mount **may be removed during infrastructure maintenance operations**. Therefore, `tmp` mounts allow you to **store files that you’re not afraid to lose**, such as your application cache that can be seamlessly rebuilt.
Note that the `/tmp` directory has **a maximum allocation of 8 GB**.

- `service` mounts can be useful if you want to explicitly define and use a [Network Storage](/add-services/network-storage.md) service to share data between different apps (instead of using a `storage` mount).| +| `source_path` | `string` | No | Specifies where the mount points **inside the [external directory](#mounts)**.

- If you explicitly set a `source_path`, your mount points to a specific subdirectory in the external directory.

- If the `source_path` is an empty string (`""`), your mount points to the entire external directory.

- If you don't define a `source_path`, {{% vendor/name %}} uses the {{< variable "MOUNT_PATH" >}} as default value, without leading or trailing slashes.
For example, if your mount lives in the `/web/uploads/` directory in your app container, it will point to a directory named `web/uploads` in the external directory.

**WARNING:** Changing the name of your mount affects the `source_path` when it's undefined. See [how to ensure continuity](#ensure-continuity-when-changing-the-name-of-your-mount) and maintain access to your files. | +| `service` | `string` | | The purpose of the `service` key depends on your use case.

In a multi-app context where a `storage` mount is shared between apps, `service` is required. Its value is the name of the app whose mount you want to share. See how to [share a mount between several apps](#share-a-mount-between-several-apps).

In a multi-app context where a [Network Storage service](/add-services/network-storage.md) (`service` mount) is shared between apps, `service` is required and specifies the name of that Network Storage. | +<---> + ++++ +title=Composable image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + stack: [ "nodejs@{{% latest nodejs %}}" ] + mounts: + '{{< variable "MOUNT_PATH" >}}': + source: {{< variable "MOUNT_TYPE" >}} + source_path: {{< variable "SOURCE_PATH_LOCATION" >}} +``` + +{{< variable "MOUNT_PATH" >}} is the path to your mount **within the app container** (relative to the app's root). +If you already have a directory with that name, you get a warning that it isn't accessible after the build. +See how to [troubleshoot the warning](../troubleshoot-mounts.md#overlapping-folders). + +| Name | Type | Required | Description | +|---------------|--------------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `source` | `storage`, `tmp`, or `service` | Yes | Specifies the type of the mount:

- By design, `storage` mounts can be shared between instances of the same app. You can also configure them so they are [shared between different apps](#share-a-mount-between-several-apps).

-`instance` mounts are local mounts. Unique to your app, they are useful to store files that remain local to the app instance, such as application logs.

- `tmp` mounts are local ephemeral mounts, where an external directory is mounted to the `/tmp` directory of your app.
The content of a `tmp` mount **may be removed during infrastructure maintenance operations**. Therefore, `tmp` mounts allow you to **store files that you’re not afraid to lose**, such as your application cache that can be seamlessly rebuilt.
Note that the `/tmp` directory has **a maximum allocation of 8 GB**.

- `service` mounts can be useful if you want to explicitly define and use a [Network Storage](/add-services/network-storage.md) service to share data between different apps (instead of using a `storage` mount). | +| `source_path` | `string` | No | Specifies where the mount points **inside the [external directory](#mounts)**.

- If you explicitly set a `source_path`, your mount points to a specific subdirectory in the external directory.

- If the `source_path` is an empty string (`""`), your mount points to the entire external directory.

- If you don't define a `source_path`, {{% vendor/name %}} uses the {{< variable "MOUNT_PATH" >}} as default value, without leading or trailing slashes.
For example, if your mount lives in the `/web/uploads/` directory in your app container, it will point to a directory named `web/uploads` in the external directory.

**WARNING:** Changing the name of your mount affects the `source_path` when it's undefined. See [how to ensure continuity](#ensure-continuity-when-changing-the-name-of-your-mount) and maintain access to your files. | +| `service` | `string` | | The purpose of the `service` key depends on your use case.

In a multi-app context where a `storage` mount is shared between apps, `service` is required. Its value is the name of the app whose mount you want to share. See how to [share a mount between several apps](#share-a-mount-between-several-apps).

In a multi-app context where a [Network Storage service](/add-services/network-storage.md) (`service` mount) is shared between apps, `service` is required and specifies the name of that Network Storage. | + +{{< /codetabs >}} + +The accessibility to the web of a mounted directory depends on the [`web.locations` configuration](#web). +Files can be all public, all private, or with different rules for different paths and file types. + +Note that when you remove a `tmp` mount from your `{{< vendor/configfile "app" >}}` file, +the mounted directory isn't deleted. +The files still exist on disk until manually removed, +or until the app container is moved to another host during a maintenance operation. + +### Example configuration + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: nodejs:20 + mounts: + 'web/uploads': + source: storage + source_path: uploads + '/.tmp_platformsh': + source: tmp + source_path: files/.tmp_platformsh + '/build': + source: storage + source_path: files/build + '/.cache': + source: tmp + source_path: files/.cache + '/node_modules/.cache': + source: tmp + source_path: files/node_modules/.cache +``` + +<---> + ++++ +title=Composable image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + stack: [ "nodejs@{{% latest nodejs %}}" ] + mounts: + 'web/uploads': + source: storage + source_path: uploads + '/.tmp_platformsh': + source: tmp + source_path: files/.tmp_platformsh + '/build': + source: storage + source_path: files/build + '/.cache': + source: tmp + source_path: files/.cache + '/node_modules/.cache': + source: tmp + source_path: files/node_modules/.cache +``` + +{{< /codetabs >}} + +### Ensure continuity when changing the name of your mount + +Changing the name of your mount affects the default `source_path`. + +Say you have a `/my/cache/` mount with an undefined `source_path`: + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +```yaml {configFile="app"} +applications: + myapp: + mounts: + '/my/cache/': + source: tmp +``` + +<---> + ++++ +title=Composable image ++++ + +```yaml {configFile="app"} +mounts: + '/my/cache/': + source: tmp +``` + +{{< /codetabs >}} + +If you rename the mount to `/cache/files/`, it will point to a new, empty `/cache/files/` directory. + +To ensure continuity, you need to explicitly define the `source_path` as the previous name of the mount, without leading +or trailing slashes: + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +```yaml {configFile="app"} +applications: + myapp: + mounts: + '/cache/files/': + source: tmp + source_path: my/cache +``` + +<---> + ++++ +title=Composable image ++++ + +```yaml {configFile="app"} +mounts: + '/cache/files/': + source: tmp + source_path: my/cache +``` + +{{< /codetabs >}} + +The `/cache/files/` mount will point to the original `/my/cache/` directory, maintaining access to all your existing +files in that directory. + +### Share a mount between several apps + +By design, [`storage` mounts](#mounts) are shared **between different instances of the same app**, +which enables [horizontal scaling](/manage-resources/_index.md). + +In a [multi-application context](/create-apps/multi-app/_index.md), +you can even share a `storage` mount **between different applications** in the same project. + +To do so, you need to define a `storage` mount in each of your app containers, +and point each of those mounts to the same shared external network directory. + +Use the following configuration: + +```yaml {configFile="app"} +applications: + app1: + mounts: + '{{< variable "MOUNT_PATH_1" >}}': + source: storage + source_path: {{< variable "SOURCE_PATH_LOCATION" >}} + + app2: + mounts: + '{{< variable "MOUNT_PATH_2" >}}': + source: storage + service: app1 + source_path: {{< variable "SOURCE_PATH_LOCATION" >}} +``` + +- {{< variable "MOUNT_PATH_1" >}} and {{< variable "MOUNT_PATH_2" >}} are the paths to each mount **within their + respective app container** (relative to the app's root). +- When configuring the first `storage` mount, you don't need to include the `service` key. + The first mount implicitly points to an external network directory. + The `service` key is required for subsequent mounts, to ensure they use the same external network directory as the + first mount. +- The `source_path` allows you to point each mount to the same subdirectory **within the shared external network + directory**. + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +{{% note title = "Single-runtime image: Example" %}} + +You have a `backend` app and a `frontend` app. +You want both apps to share data from the same mount.
+Follow these steps: + +1. In your `backend` app configuration, define a `storage` mount: + + ```yaml {configFile="app"} + applications: + backend: + mounts: + var/uploads: #The path to your mount within the backend app container. + source: storage + source_path: backend/uploads #The path to the source of the mount within the external network directory. + ``` + + This creates a `storage` mount named `var/uploads` in the `backend` app container. + The mount points to the `backend/uploads` directory within an external network directory. + +2. In your `frontend` app configuration, define another `storage` mount: + + ```yaml {configFile="app"} + applications: + applications: + backend: + mounts: + var/uploads: + source: storage + source_path: backend/uploads + + frontend: + mounts: + web/uploads: #The path to your mount within the frontend app container. + source: storage + service: backend #The name of the other app, so the mount can point to the same external network directory as that other app's mount. + source_path: backend/uploads #The path to the source of the mount within the shared external network directory. + ``` + + This creates another `storage` mount named `web/uploads` in the `frontend` app container. + + The `service` key allows you to specify that the `web/uploads` mount should use the same external network directory + as the mount previously defined in the `backend` app container. + + The `source_path` key specifies which subdirectory within the external network directory both mounts should share ( + here, the `backend/uploads` directory). + +{{% /note %}} + +<---> + ++++ +title=Composable image ++++ + +{{% note title = "Composable image: Example" %}} + +You have a `backend` app and a `frontend` app. +You want both apps to share data from the same mount.
+Follow these steps: + +1. In your `backend` app configuration, define a `storage` mount: + + ```yaml {configFile="app"} + applications: + backend: + mounts: + var/uploads: #The path to your mount within the backend app container. + source: storage + source_path: backend/uploads #The path to the source of the mount within the external network directory. + ``` + + This creates a `storage` mount named `var/uploads` in the `backend` app container. + The mount points to the `backend/uploads` directory within an external network directory. + +2. In your `frontend` app configuration, define another `storage` mount: + + ```yaml {configFile="app"} + applications: + backend: + mounts: + var/uploads: + source: storage + source_path: backend/uploads + + frontend: + mounts: + web/uploads: #The path to your mount within the frontend app container. + source: storage + service: backend #The name of the other app, so the mount can point to the same external network directory as that other app's mount. + source_path: backend/uploads #The path to the source of the mount within the shared external network directory. + ``` + + This creates another `storage` mount named `web/uploads` in the `frontend` app container. + + The `service` key allows you to specify that the `web/uploads` mount should use the same external network directory + as the mount previously defined in the `backend` app container. + + The `source_path` key specifies which subdirectory within the external network directory both mounts should share ( + here, the `backend/uploads` directory). + +{{% /note %}} + + +Note that another way to share data between apps through a mount is by +explicitly [defining a Network Storage service](/add-services/network-storage.md). + +{{< /codetabs >}} + + +### Composable image only: Local mounts + +If you need a local mount (i.e. unique per container), +{{% vendor/name %}} allows you to mount a directory within the `/tmp` directory of your app. +However, the following limitations apply: + +- Content from `tmp` mounts is removed when your app container is moved to another host during an infrastructure + maintenance operation +- The `/tmp` directory has a [maximum allocation of 8 GB](/create-apps/troubleshoot-disks.md#no-space-left-on-device) + +Therefore, `tmp` mounts are ideal to store non-critical data, such as your application cache which can be seamlessly +rebuilt, +but aren't suitable for storing files that are necessary for your app to run smoothly. + +Note that {{% vendor/name %}} will provide new local mounts in the near future. + +### Overlapping mounts + +The locations of mounts as they are visible to application containers can overlap somewhat. +For example: + +```yaml {configFile="app"} +applications: + myapp: + # ... + mounts: + 'var/cache_a': + source: storage + source_path: cacheA + 'var/cache_b': + source: tmp + source_path: cacheB + 'var/cache_c': + source: instance + source_path: cacheC +``` + +In this case, it does not matter that each mount is of a different `source` type. +Each mount is restricted to a subfolder within `var`, and all is well. + +The following, however, is not allowed and will result in a failure: + +```yaml {configFile="app"} +applications: + myapp: + # ... + mounts: + 'var/': + source: storage + source_path: cacheA + 'var/cache_b': + source: tmp + source_path: cacheB + 'var/cache_c': + source: instance + source_path: cacheC +``` + +The `storage` mount type specifically exists to share data between instances of the same application, whereas `tmp` and `instance` are meant to restrict data to build time and runtime of a single application instance, respectively. +These allowances are not compatible, and will result in an error if pushed. \ No newline at end of file diff --git a/sites/upsun/src/create-apps/image-properties/relationships.md b/sites/upsun/src/create-apps/image-properties/relationships.md new file mode 100644 index 0000000000..fd6f9e68b5 --- /dev/null +++ b/sites/upsun/src/create-apps/image-properties/relationships.md @@ -0,0 +1,216 @@ +--- +title: "`relationships`" +weight: 4 +description: A dictionary of relationships that defines the connections to other services and apps. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](/create-apps/app-reference/composable-image.md#primary-application-properties) images. + +To allow containers in your project to communicate with one another, +you need to define relationships between them. +You can define a relationship between an app and a service, or [between two apps](/create-apps/multi-app/relationships.md). + +The quickest way to define a relationship between your app and a service +is to use the service's default endpoint.
+However, some services allow you to define multiple databases, cores, and/or permissions. +In these cases, you can't rely on default endpoints. +Instead, you can explicitly define multiple endpoints when setting up your relationships. + +{{< note >}} +App containers don't have a default endpoint like services. +To connect your app to another app in your project, +you need to explicitly define the `http` endpoint as the endpoint to connect both apps.
+For more information, see how to [define relationships between your apps](/create-apps/multi-app/relationships.md). +{{< /note >}} + +{{< note title="Availability" theme="info">}} + +New syntax (default and explicit endpoints) described below is supported by most, but not all, image types +(`Relationship 'SERVICE_NAME' of application 'app' ... targets a service without a valid default endpoint configuration.`). +This syntax is currently being rolled out for all images. +If you encounter this error, use the "legacy" {{% vendor/name %}} configuration noted at the bottom of this section. + +{{< /note >}} + +To define a relationship between your app and a service: + +{{< codetabs >}} + ++++ +title=Using default endpoints ++++ + +Use the following configuration: + +```yaml {configFile="app"} +applications: + {{% variable "APP_NAME" %}}: + # ... + relationships: + {{% variable "SERVICE_NAME" %}}: +``` + +The `SERVICE_NAME` is the name of the service as defined in its [configuration](/add-services/_index.md). +It is used as the relationship name, and associated with a `null` value. +This instructs {{% vendor/name %}} to use the service's default endpoint to connect your app to the service. + +For example, if you define the following configuration: + +```yaml {configFile="app"} +applications: + {{% variable "APP_NAME" %}}: + # ... + relationships: + mariadb: +``` + +{{% vendor/name %}} looks for a service named `mariadb` in your `{{% vendor/configfile "services" %}}` file, +and connects your app to it through the service's default endpoint. + +For reference, the equivalent configuration using explicit endpoints would be the following: + +```yaml {configFile="app"} +applications: + {{% variable "APP_NAME" %}}: + # ... + relationships: + mariadb: + service: mariadb + endpoint: mysql +``` + +You can define any number of relationships in this way: + +```yaml {configFile="app"} +applications: + {{% variable "APP_NAME" %}}: + # ... + relationships: + mariadb: + redis: + elasticsearch: +``` + +{{< note title="Tip" theme="info" >}} + +An even quicker way to define many relationships is to use the following single-line configuration: + +```yaml {configFile="services"} +applications: + {{% variable "APP_NAME" %}}: + # ... + relationships: {{{< variable "SERVICE_NAME_A" >}}, {{< variable "SERVICE_NAME_B" >}}, {{< variable "SERVICE_NAME_C" >}}} + +services: + {{< variable "SERVICE_NAME_A" >}}: + type: mariadb:{{% latest "mariadb" %}} + {{< variable "SERVICE_NAME_B" >}}: + type: redis:{{% latest "redis" %}} + {{< variable "SERVICE_NAME_C" >}}: + type: elasticsearch:{{% latest "elasticsearch" %}} +``` + +{{< /note >}} + +<---> + ++++ +title=Using explicit endpoints ++++ + +Use the following configuration: + +```yaml {configFile="app"} +applications: + {{% variable "APP_NAME" %}}: + # ... + relationships: + {{% variable "RELATIONSHIP_NAME" %}}: + service: {{% variable "SERVICE_NAME" %}} + endpoint: {{% variable "ENDPOINT_NAME" %}} +``` + +- `RELATIONSHIP_NAME` is the name you want to give to the relationship. +- `SERVICE_NAME` is the name of the service as defined in its [configuration](/add-services/_index.md). +- `ENDPOINT_NAME` is the endpoint your app will use to connect to the service (refer to the service reference to know which value to use). + +For example, to define a relationship named `database` that connects your app to a service called `mariadb` through the `db1` endpoint, +use the following configuration: + +```yaml {configFile="app"} +applications: + {{% variable "APP_NAME" %}}: + # ... + relationships: + database: # The name of the relationship. + service: mariadb + endpoint: db1 +``` + +For more information on how to handle multiple databases, multiple cores, +and/or different permissions with services that support such features, +see each service's dedicated page: + + - [MariaDB/MySQL](/add-services/mysql/_index.md#multiple-databases) (multiple databases and permissions) + - [PostgreSQL](/add-services/postgresql/_index.md#multiple-databases) (multiple databases and permissions) + - [Redis](/add-services/redis/_index.md#multiple-databases) (multiple databases) + - [Solr](add-services/solr/_index.md#solr-6-and-later) (multiple cores) + - [Vault KMS](add-services/vault.md#multiple-endpoints-example) (multiple permissions) + + You can add as many relationships as you want to your app configuration, + using both default and explicit endpoints according to your needs: + +```yaml {configFile="app"} +applications: + {{% variable "APP_NAME" %}}: + # ... + relationships: + database1: + service: mariadb + endpoint: admin + database2: + service: mariadb + endpoint: legacy + cache: + service: redis + search: + service: elasticsearch +``` + +{{< /codetabs >}} + +{{< note theme="info" title="Legacy" >}} + +The following legacy syntax for specifying relationships is still supported by {{% vendor/name %}}: + +```yaml {configFile="app"} +applications: + {{% variable "APP_NAME" %}}: + # ... + relationships: + : ":" + +services: + SERVICE_NAME_A: + type: mariadb:{{% latest "mariadb" %}} +``` + +For example: + +```yaml +applications: + {{% variable "APP_NAME" %}}: + # ... + relationships: + database: "db:mysql" + +services: + db: + type: mariadb:{{% latest "mariadb" %}} +``` + +Feel free to use this until the default and explicit endpoint syntax is supported on all images. + +{{< /note >}} diff --git a/sites/upsun/src/create-apps/image-properties/source.md b/sites/upsun/src/create-apps/image-properties/source.md new file mode 100644 index 0000000000..deb0e45fa1 --- /dev/null +++ b/sites/upsun/src/create-apps/image-properties/source.md @@ -0,0 +1,16 @@ +--- +title: "`source`" +weight: 4 +description: Contains information about the app’s source code and operations that can be run on it. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](/create-apps/app-reference/composable-image.md#primary-application-properties) images. + +The following table shows the properties that can be set in `source`: + +| Name | Type | Required | Description | +|--------------|--------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------| +| `operations` | An operations dictionary | | Operations that can be applied to the source code. See [source operations](../source-operations.md) | +| `root` | `string` | | The path where the app code lives. Defaults to the root project directory. Useful for [multi-app setups](../multi-app/_index.md). | \ No newline at end of file diff --git a/sites/upsun/src/create-apps/image-properties/variables.md b/sites/upsun/src/create-apps/image-properties/variables.md new file mode 100644 index 0000000000..5f41ce33b4 --- /dev/null +++ b/sites/upsun/src/create-apps/image-properties/variables.md @@ -0,0 +1,70 @@ +--- +title: "`variables`" +weight: 4 +description: A variables dictionary that defines variables to control the environment. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](/create-apps/app-reference/composable-image.md#primary-application-properties) images. + +{{% vendor/name %}} provides a number of ways to set [variables](/development/variables/_index.md). +Variables set in your app configuration have the lowest precedence, +meaning they're overridden by any conflicting values provided elsewhere. + +All variables set in your app configuration must have a prefix. +Some [prefixes have specific meanings](/development/variables/_index.md#variable-prefixes). + +Variables with the prefix `env` are available as a separate environment variable. +All other variables are available in +the [`PLATFORM_VARIABLES` environment variable](/development/variables/use-variables.md#use-provided-variables). + +The following example sets two variables: + +- A variable named `env:AUTHOR` with the value `Juan` that's available in the environment as `AUTHOR` +- A variable named `d8config:system.site:name` with the value `My site rocks` + that's available in the `PLATFORM_VARIABLES` environment variable + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: 'python:{{% latest "python" %}}' + variables: + env: + AUTHOR: 'Juan' + d8config: + "system.site:name": 'My site rocks' +``` + +<---> + ++++ +title=Composable image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + stack: [ "python@{{% latest python %}}" ] + variables: + env: + AUTHOR: 'Juan' + d8config: + "system.site:name": 'My site rocks' +``` + +{{< /codetabs >}} + + +You can also define and access more [complex values](/development/variables/use-variables.md#access-complex-values). + diff --git a/sites/upsun/src/create-apps/image-properties/web.md b/sites/upsun/src/create-apps/image-properties/web.md new file mode 100644 index 0000000000..9e5c3333a7 --- /dev/null +++ b/sites/upsun/src/create-apps/image-properties/web.md @@ -0,0 +1,354 @@ +--- +title: "`web`" +weight: 4 +description: A web instance that defines how the web application is served. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](/create-apps/app-reference/composable-image.md#primary-application-properties) images. + +Use the `web` key to configure the web server running in front of your app. + +In **single-runtime images**, defaults may vary with a different [image `type`](/create-apps/app-reference/single-runtime-image.md#types). + +| Name | Type | Required | Description | +|-------------|--------------------------------------------|-------------------------------|------------------------------------------------------| +| `commands` | A [web commands dictionary](#web-commands) | See [note](#required-command) | The command to launch your app. | +| `upstream` | An [upstream dictionary](#upstream) | | How the front server connects to your app. | +| `locations` | A [locations dictionary](#locations) | | How the app container responds to incoming requests. | + +See some [examples of how to configure what's served](../web/_index.md). + +### Web commands + +| Name | Type | Required | Description | +|--------------|----------|-------------------------------|-----------------------------------------------------------------------------------------------------| +| `pre_start` | `string` | | Command run just prior to `start`, which can be useful when you need to run _per-instance_ actions. | +| `start` | `string` | See [note](#required-command) | The command to launch your app. If it terminates, it's restarted immediately. | +| `post_start` | `string` | | Command runs **before** adding the container to the router and **after** the `start` command. | + +{{< note theme="info" >}} +The `post_start` feature is _experimental_ and may change. Please share your feedback in the +[{{% vendor/name %}} discord](https://discord.gg/platformsh). +{{< /note >}} + +Example: + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: 'python:{{% latest "python" %}}' + web: + commands: + start: 'uwsgi --ini conf/server.ini' +``` + +<---> + ++++ +title=Composable image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + stack: [ "python@{{% latest python %}}" ] + web: + commands: + start: 'uwsgi --ini conf/server.ini' +``` + +{{< /codetabs >}} + + +This command runs every time your app is restarted, regardless of whether or not new code is deployed. + +{{< note >}} + +Never "background" a start process using `&`. +That's interpreted as the command terminating and the supervisor process starts a second copy, +creating an infinite loop until the container crashes. +Just run it as normal and allow the {{% vendor/name %}} supervisor to manage it. + +{{< /note >}} + +#### Required command + +On all containers other than PHP, the value for `start` should be treated as required. + +On PHP containers, it's optional and defaults to starting PHP-FPM (`/usr/bin/start-php-app`). +It can also be set explicitly on a PHP container to run a dedicated process, +such as [React PHP](https://github.com/platformsh-examples/platformsh-example-reactphp) +or [Amp](https://github.com/platformsh-examples/platformsh-example-amphp). +See how to set up [alternate start commands on PHP](/languages/php/_index.md#alternate-start-commands). + +### Upstream + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + + +| Name | Type | Required | Description | Default | +|-----------------|---------------------|----------|-------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------| +| `socket_family` | `tcp` or `unix` | | Whether your app listens on a Unix or TCP socket. | Defaults to `tcp` for all [image types](/create-apps/app-reference/single-runtime-image.html#types) except PHP; for PHP image types the default is `unix`. | +| `protocol` | `http` or `fastcgi` | | Whether your app receives incoming requests over HTTP or FastCGI. | Default varies based on [image `type`](/create-apps/app-reference/single-runtime-image.html#types). | + +For PHP, the defaults are configured for PHP-FPM and shouldn't need adjustment. +For all other containers, the default for `protocol` is `http`. + +The following example is the default on non-PHP containers: + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: 'python:{{% latest "python" %}}' + web: + upstream: + socket_family: tcp + protocol: http +``` + +<---> + ++++ +title=Composable image ++++ + +| Name | Type | Required | Description | Default | +|-----------------|---------------------|----------|-------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------| +| `socket_family` | `tcp` or `unix` | | Whether your app listens on a Unix or TCP socket. | Defaults to `tcp` for all [primary runtimes](/create-apps/app-reference/composable-image.html#primary-runtime) except PHP; for PHP the default is `unix`. | +| `protocol` | `http` or `fastcgi` | | Whether your app receives incoming requests over HTTP or FastCGI. | Default varies based on the [primary runtimes](/create-apps/app-reference/composable-image.html#primary-runtime). | + +For PHP, the defaults are configured for PHP-FPM and shouldn't need adjustment. +For all other containers, the default for `protocol` is `http`. + +The following example is the default on non-PHP containers: + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + stack: [ "python@{{% latest python %}}" ] + web: + upstream: + socket_family: tcp + protocol: http +``` + +{{< /codetabs >}} + + + + +#### Where to listen + +Where to listen depends on your setting for `web.upstream.socket_family` (defaults to `tcp`). + +| `socket_family` | Where to listen | +|-----------------|---------------------------------------------------------------------------------------------------------------------------------------| +| `tcp` | The port specified by the [`PORT` environment variable](/development/variables/use-variables.md#use-provided-variables) | +| `unix` | The Unix socket file specified by the [`SOCKET` environment variable](/development/variables/use-variables.md#use-provided-variables) | + +If your application isn't listening at the same place that the runtime is sending requests, +you see `502 Bad Gateway` errors when you try to connect to your website. + +### Locations + +Each key in the `locations` dictionary is a path on your site with a leading `/`. +For `example.com`, a `/` matches `example.com/` and `/admin` matches `example.com/admin`. +When multiple keys match an incoming request, the most-specific applies. + +The following table presents possible properties for each location: + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +| Name | Type | Default | Description | +|---------------------|------------------------------------------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `root` | `string` | | The directory to serve static assets for this location relative to the [app's root directory](/create-apps/app-reference/single-runtime-image.md#root-directory). Must be an actual directory inside the root directory. | +| `passthru` | `boolean` or `string` | `false` | Whether to forward disallowed and missing resources from this location to the app. A string is a path with a leading `/` to the controller, such as `/index.php`.

If your app is in PHP, when setting `passthru` to `true`, you might want to set `scripts` to `false` for enhanced security. This prevents PHP scripts from being executed from the specified location. You might also want to set `allow` to `false` so that not only PHP scripts can't be executed, but their source code also can't be delivered. | +| `index` | Array of `string`s or `null` | | Files to consider when serving a request for a directory. When set, requires access to the files through the `allow` or `rules` keys. | +| `expires` | `string` | `-1` | How long static assets are cached. The default means no caching. Setting it to a value enables the `Cache-Control` and `Expires` headers. Times can be suffixed with `ms` = milliseconds, `s` = seconds, `m` = minutes, `h` = hours, `d` = days, `w` = weeks, `M` = months/30d, or `y` = years/365d. If a `Cache-Control` appears on the `headers` configuration, `expires`, if set, will be ignored. Thus, make sure to set the `Cache-Control`'s `max-age` value when specifying a header. | +| `allow` | `boolean` | `true` | Whether to allow serving files which don't match a rule. | +| `scripts` | `boolean` | | Whether to allow scripts to run. Doesn't apply to paths specified in `passthru`. Meaningful only on PHP containers. | +| `headers` | A headers dictionary | | Any additional headers to apply to static assets, mapping header names to values (see [Set custom headers on static content](/create-apps/web/custom-headers.html)). Responses from the app aren't affected. | +| `request_buffering` | A [request buffering dictionary](#request-buffering) | See below | Handling for chunked requests. | +| `rules` | A [rules dictionary](#rules) | | Specific overrides for specific locations. | + +<---> + ++++ +title=Composable image ++++ + +| Name | Type | Default | Description | +|---------------------|------------------------------------------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `root` | `string` | | The directory to serve static assets for this location relative to the app's root directory ([see `source.root`](/create-apps/image-properties/source.md)). Must be an actual directory inside the root directory. | +| `passthru` | `boolean` or `string` | `false` | Whether to forward disallowed and missing resources from this location to the app. A string is a path with a leading `/` to the controller, such as `/index.php`.

If your app is in PHP, when setting `passthru` to `true`, you might want to set `scripts` to `false` for enhanced security. This prevents PHP scripts from being executed from the specified location. You might also want to set `allow` to `false` so that not only PHP scripts can't be executed, but their source code also can't be delivered. | +| `index` | Array of `string`s or `null` | | Files to consider when serving a request for a directory. When set, requires access to the files through the `allow` or `rules` keys. | +| `expires` | `string` | `-1` | How long static assets are cached. The default means no caching. Setting it to a value enables the `Cache-Control` and `Expires` headers. Times can be suffixed with `ms` = milliseconds, `s` = seconds, `m` = minutes, `h` = hours, `d` = days, `w` = weeks, `M` = months/30d, or `y` = years/365d. | +| `allow` | `boolean` | `true` | Whether to allow serving files which don't match a rule. | +| `scripts` | `boolean` | | Whether to allow scripts to run. Doesn't apply to paths specified in `passthru`. Meaningful only on PHP containers. | +| `headers` | A headers dictionary | | Any additional headers to apply to static assets, mapping header names to values (see [Set custom headers on static content](/create-apps/web/custom-headers.html)). Responses from the app aren't affected. | +| `request_buffering` | A [request buffering dictionary](#request-buffering) | See below | Handling for chunked requests. | +| `rules` | A [rules dictionary](#rules) | | Specific overrides for specific locations. | + +{{< /codetabs>}} + +#### Rules + +The rules dictionary can override most other keys according to a regular expression. +The key of each item is a regular expression to match paths exactly. +If an incoming request matches the rule, it's handled by the properties under the rule, +overriding any conflicting rules from the rest of the `locations` dictionary. + +Under `rules`, you can set all the other possible [`locations` properties](#locations) +except `root`, `index`, `rules` and `request_buffering`. + +In the following example, the `allow` key disallows requests for static files anywhere in the site. +This is overridden by a rule that explicitly allows common image file formats. + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: 'python:{{% latest "python" %}}' + web: + locations: + '/': + # Handle dynamic requests + root: 'public' + passthru: '/index.php' + # Disallow static files + allow: false + rules: + # Allow common image files only. + '\.(jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff2?|otf|ttf)$': + allow: true +``` + +<---> + ++++ +title=Composable image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + stack: [ "python@{{% latest python %}}" ] + web: + locations: + '/': + # Handle dynamic requests + root: 'public' + passthru: '/index.php' + # Disallow static files + allow: false + rules: + # Allow common image files only. + '\.(jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff2?|otf|ttf)$': + allow: true +``` + +{{< /codetabs >}} + + +#### Request buffering + +Request buffering is enabled by default to handle chunked requests as most app servers don't support them. +The following table shows the keys in the `request_buffering` dictionary: + +| Name | Type | Required | Default | Description | +|--------------------|-----------|----------|---------|-------------------------------------------| +| `enabled` | `boolean` | Yes | `true` | Whether request buffering is enabled. | +| `max_request_size` | `string` | | `250m` | The maximum size to allow in one request. | + +The default configuration would look like this: + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: 'python:{{% latest "python" %}}' + web: + locations: + '/': + passthru: true + request_buffering: + enabled: true + max_request_size: 250m +``` + +<---> + ++++ +title=Composable image ++++ + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + stack: [ "python@{{% latest python %}}" ] + web: + locations: + '/': + passthru: true + request_buffering: + enabled: true + max_request_size: 250m +``` + +{{< /codetabs >}} + diff --git a/sites/upsun/src/create-apps/image-properties/workers.md b/sites/upsun/src/create-apps/image-properties/workers.md new file mode 100644 index 0000000000..c4f98732a2 --- /dev/null +++ b/sites/upsun/src/create-apps/image-properties/workers.md @@ -0,0 +1,93 @@ +--- +title: "`workers`" +weight: 4 +description: Defines the list of worker names, which are alternate copies of the application to run as background processes. +--- + +{{% description %}} + +Optional in [single-runtime](/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](/create-apps/app-reference/composable-image.md#primary-application-properties) images. + +{{< codetabs >}} + ++++ +title=Single-runtime image ++++ + +Workers are exact copies of the code and compilation output as a `web` instance after a [`build` hook](/create-apps/image-properties/hooks.md). +They use the same container image. + +Workers can't accept public requests and so are suitable only for background tasks. +If they exit, they're automatically restarted. + +The keys of the `workers` definition are the names of the workers. +You can then define how each worker differs from the `web` instance using +the [top-level properties](/create-apps/app-reference/single-runtime-image.md#primary-application-properties). + +Each worker can differ from the `web` instance in all properties _except_ for: + +- `build` and `dependencies` properties, which must be the same +- `crons` as cron jobs don't run on workers +- `hooks` as the `build` hook must be the same + and the `deploy` and `post_deploy` hooks don't run on workers. + +A worker named `queue` that was small and had a different start command could look like this: + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + type: 'python:{{% latest "python" %}}' + workers: + queue: + commands: + start: | + ./worker.sh +``` + +Workers require resource definition using `{{% vendor/cli %}} resources:set`, same as application containers. +For more information, see how to [manage resources](/manage-resources.md). + + +<---> + ++++ +title=Composable image ++++ + +Workers are exact copies of the code and compilation output as a `web` instance after a [`build` hook](/create-apps/image-properties/hooks.md). +They use the same container image. + +Workers can't accept public requests and so are suitable only for background tasks. +If they exit, they're automatically restarted. + +The keys of the `workers` definition are the names of the workers. +You can then define how each worker differs from the `web` instance using +the [top-level properties](#primary-application-properties). + +Each worker can differ from the `web` instance in all properties _except_ for: + +- `crons` as cron jobs don't run on workers +- `hooks` as the `build` hook must be the same + and the `deploy` and `post_deploy` hooks don't run on workers. + +A worker named `queue` that was small and had a different start command could look like this: + +```yaml {configFile="app"} +applications: + myapp: + source: + root: "/" + stack: [ "python@{{% latest python %}}" ] + workers: + queue: + commands: + start: | + ./worker.sh +``` + +Workers require resource definition using `{{% vendor/cli %}} resources:set`, same as application containers. +For more information, see how to [manage resources](/manage-resources.md). + +{{< /codetabs >}} diff --git a/sites/upsun/src/create-apps/runtime-operations.md b/sites/upsun/src/create-apps/runtime-operations.md index 7dfacf8ddc..aaea6a2512 100644 --- a/sites/upsun/src/create-apps/runtime-operations.md +++ b/sites/upsun/src/create-apps/runtime-operations.md @@ -5,7 +5,7 @@ weight: 6 --- Runtime operations allow you to trigger one-off commands or scripts on your project. -Similar to [crons](/create-apps/app-reference/single-runtime-image.md#crons), they run in the app container but not on a specific schedule. +Similar to [crons](/create-apps/image-properties/crons.md), they run in the app container but not on a specific schedule. You can [define runtime operations](#define-a-runtime-operation) in your [app configuration](/create-apps/app-reference/single-runtime-image.md) and [trigger them](#run-a-runtime-operation) at any time through the {{% vendor/name %}} CLI. diff --git a/sites/upsun/src/create-apps/source-operations.md b/sites/upsun/src/create-apps/source-operations.md index aaf5f8ad99..db2eacd953 100644 --- a/sites/upsun/src/create-apps/source-operations.md +++ b/sites/upsun/src/create-apps/source-operations.md @@ -26,7 +26,7 @@ or [revert to the last commit](#revert-to-the-last-commit) pushed to your Git re To run your source operations, you can use the [{{% vendor/name %}} CLI](../administration/cli/_index.md) or the [Console](https://console.platform.sh). If you want to run your source operations and update your code automatically, -you can also define [cron jobs](/create-apps/app-reference/single-runtime-image.md#crons). +you can also define [cron jobs](/create-apps/image-properties/crons.md). ## How source operations work @@ -294,8 +294,6 @@ and then runs the `update-file` source operation defined [previously](#define-a- ## Source operation examples -{{< premium-features/tiered "Enterprise and Elite" >}} - ### Update your application dependencies You can set up a source operation and a cron job to [automate your dependency updates](/learn/tutorials/dependency-updates.md). diff --git a/sites/upsun/src/create-apps/workers.md b/sites/upsun/src/create-apps/workers.md index 6084d55ade..35647c65ae 100644 --- a/sites/upsun/src/create-apps/workers.md +++ b/sites/upsun/src/create-apps/workers.md @@ -70,13 +70,13 @@ The `start` key specifies the command to use to launch your worker application. It may be any valid shell command, although most often it runs a command in your application in the language of your application. If the command specified by the `start` key terminates, it's restarted automatically. -Note that [`deploy` and `post_deploy` hooks](/create-apps/hooks/_index.md) as well as [`cron` commands](/create-apps/app-reference/single-runtime-image.md#crons) +Note that [`deploy` and `post_deploy` hooks](/create-apps/hooks/_index.md) as well as [`cron` commands](/create-apps/image-properties/crons.md) run only on the [`web`](/create-apps/app-reference/single-runtime-image.md#web) container, not on workers. ## Inheritance -Any top-level definitions for [`relationships`](/create-apps/app-reference/single-runtime-image.md#relationships), -[`access`](/create-apps/app-reference/single-runtime-image.md#access), [`mount`](/create-apps/app-reference/single-runtime-image.md#mounts), and [`variables`](/create-apps/app-reference/single-runtime-image.md#variables) +Any top-level definitions for [`relationships`](/create-apps/image-properties/relationships.md), +[`access`](/create-apps/image-properties/access.md), [`mounts`](/create-apps/image-properties/mounts.md), and [`variables`](/create-apps/image-properties/variables.md) are inherited by every worker, unless overridden explicitly. Likewise [resources defined for the application container](/manage-resources/_index.md) are inherited by every worker, unless overridden explicitly. diff --git a/sites/upsun/src/development/troubleshoot.md b/sites/upsun/src/development/troubleshoot.md index a77b5075e1..4ce10cffbb 100644 --- a/sites/upsun/src/development/troubleshoot.md +++ b/sites/upsun/src/development/troubleshoot.md @@ -348,7 +348,7 @@ strace -T {{< variable "YOUR_HOOK_COMMAND" >}} # Print a system call report ### Cron jobs -Containers can't be shutdown while long-running [cron jobs and scheduled tasks](/create-apps/app-reference/single-runtime-image.md#crons) are active. +Containers can't be shutdown while long-running [cron jobs and scheduled tasks](/create-apps/image-properties/crons.md) are active. That means long-running cron jobs block a container from being shut down to make way for a new deploy. Make sure your custom cron jobs run quickly and properly. diff --git a/sites/upsun/src/environments/backup.md b/sites/upsun/src/environments/backup.md index c73ee1646e..5ea7f85aae 100644 --- a/sites/upsun/src/environments/backup.md +++ b/sites/upsun/src/environments/backup.md @@ -243,7 +243,7 @@ See more information on [backup policies](#backup-policy) and [data retention](# ### Automate manual backups -You can also automate the process of creating manual backups through [cron jobs](/create-apps/app-reference/single-runtime-image.md#crons). +You can also automate the process of creating manual backups through [cron jobs](/create-apps/image-properties/crons.md). The cron job uses the CLI command to back up the environment. It requires you to [set up the CLI on the environment with an API token](../administration/cli/api-tokens.md#authenticate-in-an-environment). diff --git a/sites/upsun/src/get-started/stacks/laravel/crons.md b/sites/upsun/src/get-started/stacks/laravel/crons.md index 2333d802f5..1ca3a06034 100644 --- a/sites/upsun/src/get-started/stacks/laravel/crons.md +++ b/sites/upsun/src/get-started/stacks/laravel/crons.md @@ -50,7 +50,7 @@ applications: ## Run the Laravel scheduler every minute Cron job execution on the default {{< vendor/name >}} offering are limited to once every 5 minutes. -For more information, see the [documentation on crons](/create-apps/app-reference/single-runtime-image.md#crons). +For more information, see the [documentation on crons](/create-apps/image-properties/crons.md). However, you can add a [worker](/create-apps/app-reference/single-runtime-image.md#workers) and specify a start command that [runs the scheduler every minute](https://laravel.com/docs/11.x/scheduling#running-the-scheduler-locally). diff --git a/sites/upsun/src/increase-observability/logs/access-logs.md b/sites/upsun/src/increase-observability/logs/access-logs.md index e63772b670..ed3649ee31 100644 --- a/sites/upsun/src/increase-observability/logs/access-logs.md +++ b/sites/upsun/src/increase-observability/logs/access-logs.md @@ -120,7 +120,7 @@ title=Using SSH directly {{< /codetabs >}} All log files are trimmed to 100 MB automatically. -If you need larger logs, set up a [cron job](/create-apps/app-reference/single-runtime-image.md#crons) to upload them to third-party storage. +If you need larger logs, set up a [cron job](/create-apps/image-properties/crons.md) to upload them to third-party storage. See an example of [uploading logs to Amazon S3](https://gitlab.com/contextualcode/platformsh-store-logs-at-s3) from Contextual Code. ### Types of container logs diff --git a/sites/upsun/src/integrations/activity/reference.md b/sites/upsun/src/integrations/activity/reference.md index 03159f97c3..52366a794c 100644 --- a/sites/upsun/src/integrations/activity/reference.md +++ b/sites/upsun/src/integrations/activity/reference.md @@ -123,7 +123,7 @@ The following table presents the possible activity types: | `environment.backup.delete` | A user deleted a [backup](/environments/backup.md). | | `environment.branch` | A [new branch](/environments.md#create-environments) has been created via the CLI, Console, or API. A branch created via Git shows up as `environment.push`. | | `environment.certificate.renewal` | An environment's SSL certificate has been [renewed](/define-routes/https.md#certificate-renewals). | -| `environment.cron` | A [cron job](/create-apps/app-reference/single-runtime-image.md#crons) has completed. | +| `environment.cron` | A [cron job](/create-apps/image-properties/crons.md) has completed. | | `environment.deactivate` | An environment has been made [inactive](/glossary.md#inactive-environment). | | `environment.delete` | An environment's code was deleted through Git. | | `environment.domain.create` | A new [domain](administration/web/configure-project.md#domains) has been associated with the environment. | @@ -330,7 +330,7 @@ To test responses, [set up a webhook](/integrations/activity/webhooks.md#setup). ### Cron -When a cron job is triggered, the activity contains all the [job's information](/create-apps/app-reference/single-runtime-image.md#crons). +When a cron job is triggered, the activity contains all the [job's information](/create-apps/image-properties/crons.md). The following example response was triggered by a setting where the cron is scheduled to run every five minutes (`5 * * * *`) with the command `sleep 60 && echo sleep-60-finished && date` and times out after 86,400 seconds. diff --git a/sites/upsun/src/languages/php/_index.md b/sites/upsun/src/languages/php/_index.md index c36b96b6a4..a281ec35d0 100644 --- a/sites/upsun/src/languages/php/_index.md +++ b/sites/upsun/src/languages/php/_index.md @@ -495,7 +495,7 @@ Common functions to disable include: PHP has two execution modes you can choose from: - The command line interface mode (PHP-CLI) is the mode used for command line scripts and standalone apps. - This is the mode used when you're logged into your container via SSH, for [crons](/create-apps/app-reference/single-runtime-image.md#crons), + This is the mode used when you're logged into your container via SSH, for [crons](/create-apps/image-properties/crons.md), and usually also for [alternate start commands](#alternate-start-commands). To use PHP-CLI, run your script with `php {{}}`, where {{}} is a file path relative to the [app root](/create-apps/app-reference/single-runtime-image.md#root-directory). diff --git a/sites/upsun/src/projects/change-project-timezone.md b/sites/upsun/src/projects/change-project-timezone.md index 0a05a4316b..d54a3d7cab 100644 --- a/sites/upsun/src/projects/change-project-timezone.md +++ b/sites/upsun/src/projects/change-project-timezone.md @@ -8,7 +8,7 @@ The project timezone affects [automated backups](../environments/backup.md). The project timezone doesn't affect: - [App runtime](/create-apps/timezone.md). -- [Cron jobs](/create-apps/app-reference/single-runtime-image.md#crons). +- [Cron jobs](/create-apps/image-properties/crons.md). - [System logs](/increase-observability/logs/_index.md). UTC is the default timezone for all logs. To change the timezone for a project, follow these steps: