# Platform Sh > Changes to your environments, such as deployments, cron jobs, and code or variable updates, --- # Source: https://docs.upsun.com/increase-observability/logs/access-logs.md # Access your logs ## Activity logs Changes to your environments, such as deployments, cron jobs, and code or variable updates, are each logged as activities. You can access the logs either in the Console or using the [CLI](https://docs.upsun.com../../administration/cli/_index.md): - Get a list of activities by running ```bash {} upsun activity:list -e ``` Pass the ``--start`` flag to get activities from a specific date in the past. - To see details about the activity’s state and timing, run ```bash {} upsun activity:get ``` Where comes from the list in step 1. - Get a log of any given activity by running ```bash {} upsun activity:log ``` If a running activity is stuck, you can [cancel the activity](https://docs.upsun.com../../environments/cancel-activity.md). ### Sharing activity logs When trying to identify and resolve failures, it can often help to have another person's perspective. Troubleshoot collaboratively by sharing the logs of specific activities. To share a log, open the log and click Share **Copy URL**. Share specific lines in the log on clicking the line number. To select multiple lines, hold Shift. After selecting multiple lines, hovering on the next unselected line gives you the amount of time that passed between the selected lines. ![An activity log with multiple lines selected showing the duration of part of the activity](https://docs.upsun.com/images/management-console/activity-lines.png "0.5") ## Container logs Events that occur within an app container are logged within that container. The logs can be written to, but you should do so only with standard logging mechanisms. If your app has its own logging mechanism, use it to write to a dedicated logs [mount](https://docs.upsun.com/create-apps/image-properties/mounts.md). To access the logs of various types of events: To get other logs, just replace ``access`` with the [type of log](#types-of-container-logs). To view more lines, use the ``--lines`` flag. - Access the container by running ```bash {} upsun ssh -e ``` - Change to the right directory by running ``cd /var/log``. - Read the desired log, such as by running ``tail access.log``. All log files are trimmed to 100 MB automatically. If you need larger logs, set up a [cron job](https://docs.upsun.com/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 | Type | Always present | Description | | ------------- | -------------- | ----------- | | `access` | Yes | The raw access log for the nginx instance running on the container. It doesn't include requests that are redirected or cached by the [router](https://docs.upsun.com../../define-routes.md). | | `app` | Yes | All log messages generated by the app including language errors and exceptions. | | `cron` | No | The output of cron jobs. Only exists after a cron job has run. | | `deploy` | No | The output of the [`deploy` hook](https://docs.upsun.com../../create-apps/hooks/hooks-comparison.md#deploy-hook). Only exists after a `deploy` hook has run. | | `dns` | Yes | All DNS queries made by processes in the container (such as the app and cron jobs). | | `error` | Yes | nginx-level errors that occur once nginx has fully started such as HTTP errors for missing directories and excluded file types. | | `nginx/error` | No | All nginx startup log messages. Only useful when debugging possible nginx configuration errors. Not currently available using the `upsun log` command. | | `php.access` | No | A record of all requests to the PHP service. See [PHP access record format](#php-access-record-format). | | `post-deploy` | No | The output of the [`post_deploy` hook](https://docs.upsun.com../../create-apps/hooks/hooks-comparison.md#post-deploy-hook). Only exists after a `post_deploy` hook has run. | | `syslog` | Yes | General system-wide logs. | #### PHP access record format The formatting of `php.access.log` is determined by the PHP settings. To determine the format, run the following: ```bash upsun ssh cat -n /etc/php/-zts/fpm/php-fpm.conf | grep "access.format" ``` You get a response such as the following: ```bash Connection to ssh.eu.platform.sh closed. access.format = "%{%FT%TZ}t %m %s %{mili}d ms %{kilo}M kB %C%% %{REQUEST_URI}e" ``` See what [each value in this string means](https://www.php.net/manual/en/install.fpm.configuration.php#access-format). ## Timezones UTC is the default timezone for all logs. --- # Source: https://docs.upsun.com/development/access-site.md # Access your site Once you have an environment running, you can view it in a web browser. To find which URLs you can use to access your site, follow these steps: - Run the following command: ```bash {} upsun url ``` - Select the URL to open in a browser. For more information about URLs in your project and how you can control access to your web applications, see how to [define routes](https://docs.upsun.com../define-routes/). --- # Source: https://docs.upsun.com/create-apps/image-properties/access.md # access An access dictionary that defines the access control for roles accessing app environments. Optional in [single-runtime](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](https://docs.upsun.com/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](https://docs.upsun.com/administration/users.md#environment-type-roles) can access the deployed environment via SSH: ```yaml {} applications: : type: "python:3.14" source: root: "/" access: ssh: admin ``` .upsun/config.yaml ```yaml {} applications: : type: "composable:25.11" stack: runtimes: [ "python@3.14" ] source: root: "/" access: ssh: admin ``` --- # Source: https://docs.upsun.com/integrations/activity.md # Activity scripts Upsun supports custom scripts that can fire in response to any activity. These scripts allow you to take arbitrary actions in response to actions in your project, such as when it deploys, when a new branch is created, etc. ## Installing Activity scripts are configured as integrations. That means they're at the *project level*, not at the level of an individual environment. While you can store the scripts in your Git repository for access, they have no effect there. To install a new activity script, use [`integration:add` command](https://docs.upsun.com/administration/cli/reference.md#integrationadd) from the [Upsun CLI](https://docs.upsun.com/administration/cli.md). ```bash upsun integration:add --type script --file ./my_script.js ``` That installs and enables the `my_script.js` file as an activity script on the current project. Don't run the `integration:add` command a second time, or it installs a second integration with the same code. ## Updating To update an existing activity script, follow these steps: 1. Get the activity script's ID by running the following command: ```bash upsun integrations ``` This returns something like the following: ```bash +---------------+--------------+--------------+ | ID | Type | Summary | +---------------+--------------+--------------+ | nadbowmhd67do | script | ... | | rcqf6b69jdcx6 | health.email | From: | | | | To: #admins | +---------------+--------------+--------------+ ``` 2. Update the integration by running the following command: ```bash upsun integration:update --file ./my_script.js ``` This [`integration:update` command](https://docs.upsun.com/administration/cli/reference.md#integrationupdate) updates the integration in place, permanently overwriting the previous version. 3. Test the activity script update by [triggering a redeployment](https://docs.upsun.com/administration/cli/reference.md#environmentredeploy) with the following command: ```bash upsun redeploy ``` ## Removing To disable an activity script, follow these steps: 1. Get the activity script's ID by running the following command: ```bash upsun integrations ``` This returns something like the following: ```bash +---------------+--------------+--------------+ | ID | Type | Summary | +---------------+--------------+--------------+ | nadbowmhd67do | script | ... | | rcqf6b69jdcx6 | health.email | From: | | | | To: #admins | +---------------+--------------+--------------+ ``` 2. [Delete the integration](https://docs.upsun.com/administration/cli/reference.md#integrationdelete) by running the following command: ```bash upsun integration:delete ``` ## Debugging Get activity logs by running the following command: ```bash upsun integration:activities ``` Every time your activity script runs it generates a new log entry, including the output from the script. Any output produced by `console.log` is available in the activity log, which is the recommended way to debug scripts. See the [activity log](https://docs.upsun.com../overview.md#debug-integrations) documentation for further details. To get a more readable output of a variable you're trying to debug, you can make `JSON.stringify` use human-friendly formatting. ```javascript console.log(JSON.stringify(project, null, 2)); ``` ## Configuring scripts There are many types of activity to which a script could respond. By default, it will activate only after a successful `git push` operation. That trigger is configurable via command line switches when adding or updating a script. For example, to have a script trigger any time an environment is activated or deactivated, run: ```bash upsun integration:update --events='environment.activate,environment.deactivate' ``` A complete list of possible events is available in the [Activity script type documentation](https://docs.upsun.com/integrations/activity/reference.md#type). Any of those Activity Script types can be added to the `--events=event1,event2,...` option. Scripts can also trigger only when an action reaches a [given state](https://docs.upsun.com/integrations/activity/reference.md#state), such as `pending`, `in_progress`, `complete`, `cancelled`, or `scheduled`. The default is only when they reach `complete`. To have a script execute when a synchronize action first starts, for example, you would run: ```bash upsun integration:update --events=environment.synchronize --states=in_progress ``` It's also possible to restrict scripts to certain environments by name. Most commonly, that's used to have them execute only for your production environment or for all other environments. The following example executes only for backup actions on the `production` environment: ```bash upsun integration:update --events=environment.backup --environments=production ``` As a general rule, it's better to have an activity script only execute on the specific events and branches you're interested in rather than firing on all activities and then filtering out undesired use cases in the script itself. ## Activity script variables Some activities don't have access to [project and environment variables](https://docs.upsun.com/development/variables.md#variable-types). In this case, to avoid hardcoding sensitive variables (such as API tokens) and therefore prevent security breaches, add a variable to your activity script. You can add activity script variables through the Upsun CLI. Activity script variables are only visible in the activity script itself, inside the `variables` variable. ### Add an activity script variable To add a variable to your activity script at the integration level, use the following `POST` request: ```bash POST /api/projects//integrations//variables ``` You get a payload similar to the following: ```json { "name": "string", "attributes": { "property1": "string", "property2": "string" }, "value": "string", "is_json": true, "is_sensitive": true } ``` ### Delete or patch an activity script variable To delete an activity script variable, use the following `DELETE` request: ``` DELETE /api/projects//integrations//variables ``` You can also patch your activity script variable. To do so, send the same request using the `PATCH` method instead of the `DELETE` one. ### List an activity script variable To list all your activity script variables at the integration level, use the following `GET` request: ``` GET /api/projects//integrations//variables ``` ## Available APIs Activity scripts can be written in ES2021 and don't support installing additional packages. There are a series of [utility functions you can reuse](https://docs.upsun.com/integrations/activity/utility.md) as well as the following libraries, APIs, and global variables to facilitate building out custom functionality. ### `underscore.js` [`Underscore.js`](https://github.com/jashkenas/underscore) is available out-of-the-box to make writing Activity scripts more pleasant. See [Underscore's documentation](https://underscorejs.org/) for available functions and utilities. ### `activity` Every activity script has a global variable `activity` that contains detailed information about the activity, including embedded, JSON-ified versions of the routes configuration and relevant `.upsun/config.yaml` files. The `activity` variable is the same as the [webhook payload](https://docs.upsun.com/integrations/activity/webhooks.md). See the documentation there for details and a complete example. Several of the utility functions below work by pulling out common portions of the `activity` object. ### `project` The `project` global variable includes information about the project subscription itself. That includes its ID and name, how many users are associated with the project, its SSH public key, and various other values. An example of this object is below: ```json { "attributes": {}, "created_at": "2026-03-15T19:50:09.514267+00:00", "default_domain": null, "description": "", "id": "azertyuiopqsdfghjklm", "owner": "...", "region": "eu-1.upsun.com", "repository": { "client_ssh_key": "ssh-rsa ...", "url": "azertyuiopqsdfghjklm@git.eu-1.upsun.com:kqyhl5f5nuzky.git" }, "status": { "code": "provisioned", "message": "ok" }, "subscription": { "environments": 3, "included_users": 1, "license_uri": "...", "plan": "development", "restricted": false, "storage": 5120, "subscription_management_uri": "...", "suspended": false, "user_licenses": 1 }, "timezone": "Europe/Dublin", "title": "Activity script examples", "updated_at": "2026-04-21T17:15:35.526498+00:00" } ``` ### Storage API Activity scripts have access to a limited key/value storage API to persist values from one execution to another. The API is similar to the JavaScript `LocalStorage` API. ```javascript // Access the storage API. // It isn't pre-required. var storage = require("storage"); // Retrieve a stored value. If the value isn't set it will return null. var counter = storage.get('counter') || 0; if (counter) { // Generate debug output. console.log("Counter is: " + counter); } // Write a value into the storage. Only string-safe values are supported. // To save an object or array, run JSON.stringify() on it first. storage.set('counter', counter + 1); // Remove a value completely. storage.remove('counter'); // Remove all values in storage, unconditionally. storage.clear(); ``` ### Fetch API Activity scripts support a modified version of the browser "Fetch API" for issuing HTTP requests. Unlike the typical browser version, however, they only support synchronous requests. That means the return value of `fetch()` is a `Response`, not a `Promise` for one. The returned `Response` is also a bit different: only the `ok`, `status` and `statusText` properties as well as the `text` and `json` methods are available. Note that because of the synchronous nature of our `fetch` implementation, the `Response.text` and `Response.json` methods are also synchronous, so they directly return a `string` and an `object`, respectively. The API is otherwise essentially the same as that [in the MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch). For instance, this example sends a GET request every time it executes: ```javascript var resp = fetch("http://example.com/site-deployed"); // The fetch call above being synchronous, we can directly access resp properties. // resp.ok is true if the response was a 2xx, false otherwise. if (!resp.ok) { console.log("Well that didn't work."); } ``` While this example sends a POST request with a JSON string as the body: ```javascript var body = JSON.stringify({ "some": "value", }); var resp = fetch("http://example.com/", { method: "POST", headers: { 'Content-Type': 'application/json', }, body: body, } ) if (!resp.ok) { console.log("Couldn't POST."); } else { // resp.json() is synchronous so this will log an object, not `Promise { }` console.log(resp.json()); } ``` For more `fetch()` options, see the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch). ### Cryptographic API A minimalist cryptographic API is also available to activity scripts. Its main use is for signing requests to 3rd party APIs. The `crypto.createHmac()` function allows you to create a secure HMAC hash and digest. ```javascript var h = crypto.createHmac("sha256", "foo"); h.update("bar"); h.digest("hex") ``` * The available hashing functions are `'sha256'`, `'sha1'` and `'md5'` as hashing functions. * The available digest formats are `'base64'`, `'hex'` or `''` (empty). An empty digest will yield a byte string. For example, if you wanted to call an AWS API, you would calculate the signature like so: ```Javascript function HMAC(key, value) { var h = crypto.createHmac("sha256", key); h.update(value); return h.digest(); } var kSecret = "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY"; HMAC(HMAC(HMAC(HMAC("AWS4" + kSecret,"20260830"),"us-east-1"),"iam"),"aws4_request"); ``` > Example taken from the [AWS documentation for signing API requests](https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.md). --- # Source: https://docs.upsun.com/add-services.md # Add services Upsun includes many services, so you don't have to subscribe to external cache or search engine services. Because the services are included in your project, you can manage them through Git and they're backed up together with the rest of your project. Your project defines the services configuration from a top-level key called `services`, which is placed in a unified configuration file like `.upsun/config.yaml`. If you don't need any services (such as for a static website), you don't need to include this configuration. Read on to see how to add services. ## Add a service Adding a service is a two-step process. ### 1. Configure the service All service configuration happens in the `.upsun/config.yaml` file in your Git repository. Configure your service in the following pattern: ```yaml {location=".upsun/config.yaml"} # The name of the service container. Must be unique within a project. services: : type: : # Other options... ``` An example service configuration for two databases might look like this: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. mariadb: type: mariadb:11.8 # The name of the service container. Must be unique within a project. postgresql: type: postgresql:18 ``` This YAML file contains a dictionary defining all of the services you want to use. The top-level key `services` defines an object of all of the services to be provisioned for the project. Below that, come custom service names (; in the example, `mariadb` and `postgresql`), which you use to identify the service in step 2. You can give it any name you want with lowercase alphanumeric characters, hyphens, and underscores. **Note**: Changing the service name is interpreted as creating an entirely new service. This **removes all data in that service**. Always back up your data before changing existing services in your ``.upsun/config.yaml`` file. #### Service options The following table presents the keys you can define for each service: | Name | Type | Required | Description | | --------------- | ---------- | ----------------- | ----------- | | `type` | `string` | Yes | One of the [available services](#available-services) in the format `type:version`. | | `configuration` | dictionary | For some services | Some services have additional specific configuration options that can be defined here, such as specific endpoints. See the given service page for more details. | | `relationships` | dictionary | For some services | Some services require a relationship to your app. The content of the dictionary has the same type as the `relationships` dictionary for [app configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). The `endpoint_name` for apps is always `http`. | ##### Resources (CPU, RAM, disk) Upsun allows you to configure resources (CPU, RAM, and disk) per environment for each of your services. For more information, see how to [manage resources](https://docs.upsun.com/manage-resources.md). You configure the disk size in [MB](https://docs.upsun.com/glossary.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. You can decrease the size of an existing disk for a service. If you do so, be aware that: - You need to [create new backups](https://docs.upsun.com/environments/backup.md) that the downsized disk can accommodate. Backups from before the downsize cannot be restored unless you increase the disk size again. - The downsize fails if there's more data on the disk than the desired size. ### 2. Define the relationship To define the relationship, use the following configuration: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Other options... # Relationships enable an app container's access to a service. # The example below shows simplified configuration leveraging a default service (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Other options... # Relationships enable an app container's access to a service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: ``` - ```` is the name you want to give to the relationship. - ```` is the name of the service as defined in the ``services`` section. - ```` is the endpoint your app will use to connect to the service (refer to the service reference to know which value to use). An example relationship to connect to the databases given in the [example in step 1](#1-configure-the-service): ```yaml {} applications: # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. : relationships: mariadb: postgresql: services: mariadb: type: mariadb:11.8 postgresql: type: postgresql:18 ``` .upsun/config.yaml ```yaml {} applications: # Relationships enable access from this app to a given service. # The example below shows configuration with explicitly set service names and endpoints. # See the Application reference for all options for defining relationships and endpoints. : relationships: database: service: mariadb endpoint: mysql postgresql: service: postgresql endpoint: postgresql services: mariadb: type: mariadb:11.8 postgresql: type: postgresql:18 ``` As with the service name, you can give the relationship any name you want with lowercase alphanumeric characters, hyphens, and underscores. It helps if the service name and relationship name are different, but it isn’t required. Each service offers one or more endpoints for connections, depending on the service. An endpoint is a named set of credentials to give access to other apps and services in your project. If you don't specify one in the [service configuration](#service-options), a default endpoint is created. The default endpoint varies by service, generally being its type (such as `mysql` or `solr`). ## Available services The following table presents the available service types and their versions. Add them to the `type` key of the [service configuration](#1-configure-the-service) in the format `type:version`. | Service | `type` | Supported versions | | ------- | ------ | ------------------ | | [Headless Chrome](https://docs.upsun.com/add-services/headless-chrome.md) | `chrome-headless` | 120 | | [ClickHouse](https://docs.upsun.com/add-services/clickhouse.md) | `clickhouse` | 25.8, 25.3, 24.3, 23.8 | | [Elasticsearch](https://docs.upsun.com/add-services/elasticsearch.md) | `elasticsearch` | 7.10 | | [Elasticsearch-Enterprise](https://docs.upsun.com/add-services/elasticsearch.md) Premium | `elasticsearch-enterprise` | 7.17, 8.5, 8.19 | | [Gotenberg](https://docs.upsun.com/add-services/gotenberg.md) | `gotenberg` | 8 | | [InfluxDB](https://docs.upsun.com/add-services/influxdb.md) | `influxdb` | 2.7, 2.3 | | [Kafka](https://docs.upsun.com/add-services/kafka.md) | `kafka` | 3.7 | | [MariaDB/MySQL](https://docs.upsun.com/add-services/mysql.md) | `mariadb` | 11.8, 11.4, 10.11, 10.6 | | [Memcached](https://docs.upsun.com/add-services/memcached.md) | `memcached` | 1.6 | | [Mercure](https://docs.upsun.com/add-services/mercure.md) | `mercure` | 0 | | [MongoDB](https://docs.upsun.com/add-services/mongodb.md) | `mongodb` | 4.0 | | [MongoDB](https://docs.upsun.com/add-services/mongodb.md) Premium | `mongodb-enterprise` | 7.0 | | [MariaDB/MySQL](https://docs.upsun.com/add-services/mysql.md) | `mysql` | 11.8, 11.4, 10.11, 10.6 | | [Network Storage](https://docs.upsun.com/add-services/network-storage.md) | `network-storage` | 1.0 | | [OpenSearch](https://docs.upsun.com/add-services/opensearch.md) | `opensearch` | 3, 2 | | [Oracle MySQL](https://docs.upsun.com/add-services/mysql.md) | `oracle-mysql` | 8.4, 8.0 | | [PostgreSQL](https://docs.upsun.com/add-services/postgresql.md) | `postgresql` | 18, 17, 16, 15, 14 | | [RabbitMQ](https://docs.upsun.com/add-services/rabbitmq.md) | `rabbitmq` | 4.1 | | [Redis](https://docs.upsun.com/add-services/redis.md) | `redis` | 8.0, 7.2 | | [Solr](https://docs.upsun.com/add-services/solr.md) | `solr` | 9.9, 9.6, 9.4, 9.2, 9.1 | | [Valkey](https://docs.upsun.com/add-services/valkey.md) | `valkey` | 8.1, 8.0 | | [Varnish](https://docs.upsun.com/add-services/varnish.md) | `varnish` | 7.6, 6.0 | | [Vault KMS](https://docs.upsun.com/add-services/vault.md) | `vault-kms` | 1.12 | ### Service versions These services generally follow [semantic versioning conventions](https://semver.org/). You can select the major version, but the latest compatible minor is applied automatically and can’t be overridden. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. ## Service timezones All services have their system timezone set to UTC by default. For some services, you can change the timezone for the running service (this doesn't affect the container itself and so logs are still in UTC). * [MySQL](https://docs.upsun.com/add-services/mysql.md#service-timezone) * [PostgreSQL](https://docs.upsun.com/add-services/postgresql.md#service-timezone) ## Connect to a service For security reasons, you can't access services directly through HTTP. You can connect through your app or by opening an SSH tunnel to access the service directly. Connecting to a service using an SSH tunnel is a two-step process. ### 1. Obtain service credentials To get the credentials for a given service, run the following command: ```bash {} upsun relationships ``` You get output like the following: ```yaml {} mariadb: - username: user scheme: mysql service: mariadb fragment: null ip: 198.51.100.37 hostname: abcdefghijklm1234567890123.mariadb.service._.eu.platformsh.site public: false cluster: abcdefgh1234567-main-abcd123 host: mariadb.internal rel: mysql query: is_master: true path: main password: '' type: 'mariadb:11.8' port: 3306 host_mapped: false url: 'mysql://user:@mariadb.internal:3306/main' ``` With this example, you can connect to the ``mariadb`` relationship with the user ``user``, an empty password, and the database name ``main`` (from the ``path``). The ``url`` property shows a full database connection that can be used from your app. You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``. Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) directly rather than hard coding any values. ### 2. Open an SSH tunnel Open a single [SSH tunnel](https://docs.upsun.com/development/ssh.md#connect-to-services) by running the following CLI command: ```bash {} upsun tunnel:single --relationship ``` By default, this opens a tunnel at ``127.0.0.1:30000``. You can specify the port for the connection using the ``--port`` flag. You can then connect to this service in a separate terminal or locally running app. With the example above, you connect to a URL like the following: ``mysql://user:@127.0.0.1:30000/main`` ## Upgrading services Upsun provides a large number of [managed service versions](#available-services). As new versions are made available, you will inevitably upgrade infrastructure to a more recent (or latest version). When you do so, we would recommend: 1. **Use preview environments**. Leverage preview (non-production environments) to perform the upgrade, then merge the upgrade into production (promotion). This will give you an opportunity to test inherited production data in a safe, isolated environment first. 1. **Upgrade progressively**. For one reason or another, you may be more than a single version behind the upgrade you are trying to perform. To avoid data loss issues caused by large differences in versions, [upgrade one version at a time](https://www.rabbitmq.com/upgrade.md#rabbitmq-version-upgradability). --- # Source: https://docs.upsun.com/create-apps/image-properties/additional_hosts.md # additional_hosts An additional hosts dictionary that maps hostnames to IP addresses. Optional in [single-runtime](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](https://docs.upsun.com/create-apps/app-reference/composable-image.md#primary-application-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 {} applications: : type: 'php:8.5' source: root: "/" additional_hosts: api.example.com: "192.0.2.23" web.example.com: "203.0.113.42" ``` .upsun/config.yaml ```yaml {} applications: : type: "composable:25.11" stack: runtimes: [ "php@8.4" ] source: root: "/" 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. --- # Source: https://docs.upsun.com/administration.md # Administration --- # Source: https://docs.upsun.com/administration/cli/api-tokens.md # Authenticate the CLI using an API token You need to set up an API token to authenticate the Upsun CLI for any of the following tasks: - Running automated tasks on a CI system - Running automated tasks directly on app container, for example in a cron job ## Before you begin You might need the [Upsun CLI](https://docs.upsun.com../cli.md) to perform certain tasks. For example, you need the CLI to do the following: - [Check the validity of an API token](#optional-check-the-validity-of-your-api-token). - [Load the CLI SSH certificate for non-CLI commands](#use-the-cli-ssh-certificate-for-non-cli-commands). ## 1. Create a machine user To safely run automated tasks, first create machine users. Each machine user has its own Upsun account associated with a unique email address. You can grant them restrictive [access permissions](https://docs.upsun.com../users.md) to handle specific automated tasks. For security purposes, create a machine user for each type of task you want to automate. To create a machine user, follow these steps: This sets your machine user as a viewer on your project and a contributor on development environments, with no access to other environment types. Note that you can further [adjust user roles](https://docs.upsun.com/administration/users.md#environment-type-roles) depending on your needs and each environment type. - In the email invitation, click **Create account**. - To create an Upsun account for the machine user, click **Sign up** and follow the instructions. - Go to your project and click Settings **Settings**. - In the **Project Settings** menu, click **Access**. - Click **Add**. - Enter your machine user’s email address. - For each [environment type](https://docs.upsun.com/administration/users.md#environment-type-roles), assign a role to your machine user and click **Save**. **Note**: Machine users with an email address under your single sign-on (SSO) domain can be excluded from the SSO enforcement rule so they aren’t required to authenticate through your identity provider. See the [SSO documentation](https://docs.upsun.com/administration/security/sso.md#service-users) for more information. ## 2. Create an API token 1. Log in to the Console as your machine user. 2. Open the user menu (your name or profile picture). 3. Click **My profile**. 4. Go to the **API tokens** tab and click **Create API token**. 5. Enter a name for your API token and click **Create API token**. 6. To copy the API token to your clipboard, click ** Copy**. Note that after you close the **API tokens** tab, you can't display the API token again. 7. Store the API token somewhere secure on your computer. ### Optional: check the validity of your API token To check that your API token is valid, run the following command: ```bash upsun auth:api-token-login ``` When prompted, enter your API token. You get output similar to this: ```bash The API token is valid. You are logged in. ``` For security reasons, rotate your API tokens regularly. When an API token is compromised, revoke it immediately. ## 3. Authenticate the CLI using your API token After you create your API token, you can use it to do the following: - Allow a CI system to run automated tasks using the Upsun CLI. - Run automated tasks on an app container using the Upsun CLI, for example in a cron job. Note that when running CLI commands in these cases, some operations might take time to complete. To avoid waiting for an operation to complete before moving on to the next one, use the `--no-wait` flag. ### Authenticate in a CI system You can allow your CI system to run automated tasks using the Upsun CLI. To do so, create an environment variable named `UPSUN_CLI_TOKEN` with your API token as its value. For more information, see your CI system's official documentation. To run SSH-based commands that aren't specific to the Upsun CLI, see how to [load the proper SSH certificate](#use-the-cli-ssh-certificate-for-non-cli-commands). ### Authenticate in an environment You can run automated tasks on an app container using the Upsun CLI. To do so, set your API token as a [top-level environment variable](https://docs.upsun.com../../development/variables.md#top-level-environment-variables). **Note**: Once you add the token as an environment variable, anyone with [SSH access](https://docs.upsun.com/development/ssh.md) can read its value. Make sure your [machine user has only the necessary permissions](#1-create-a-machine-user). - Open the environment where you want to add the variable. - Click Settings **Settings**. - Click **Variables**. - Click **+ Add variable**. - In the **Variable name** field, enter ``env:UPSUN_CLI_TOKEN``. - In the **Value** field, enter your API token. - Make sure the **Available at runtime** and **Sensitive variable** options are selected. - Click **Add variable**. Then add a build hook to your app configuration to install the CLI as part of the build process. ```yaml {location=".upsun/config.yaml"} hooks: build: | set -e echo "Installing Upsun CLI" curl -fsSL https://raw.githubusercontent.com/platformsh/cli/main/installer.sh | bash echo "Testing Upsun CLI" upsun ``` You can now call the CLI from within the shell on the app container or in a cron job. To run SSH-based commands that aren't specific to the Upsun CLI, see how to [load the proper SSH certificate](#use-the-cli-ssh-certificate-for-non-cli-commands). You can set up a cron job on a specific type of environment. For example, to run the `update` source operation on your production environment, use the following cron job: ```yaml crons: update: spec: '0 0 * * *' commands: start: | if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then upsun backup:create --yes --no-wait upsun source-operation:run update --no-wait --yes fi ``` ## Use the CLI SSH certificate for non-CLI commands When you set a `UPSUN_CLI_TOKEN` environment variable, the CLI authentication isn't complete until your run a CLI command or load the CLI SSH certificate. For example, after setting a `UPSUN_CLI_TOKEN` environment variable, you might need to run `ssh`, `git`, `rsync`, or `scp` commands before you run any CLI commands. In this case, to ensure all your commands work, load the CLI SSH certificate first. To do so, run the following command: ```bash upsun ssh-cert:load --no-interaction ``` --- # Source: https://docs.upsun.com/create-apps/app-reference.md # Choose an image type An _image_ represents the configuration of the container that contains the application (or service) that you want to deploy. 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. You can choose either Upsun's [single-runtime image](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md) or its [composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md). **The key difference between them is the type of flexibility that they offer**. For both image types, the image is defined in the `.upsun/config.yaml` file. ## Which image type should you choose? {#which-image-type} | **Criteria / Use‑case** | **Single‑runtime image** | **Composable image** | | ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **When it’s best used (typical use case)** | Good for simple applications that need only one runtime. | Best for applications needing custom secondary runtimes, static assets, or custom binaries/tools. | | **# of runtimes per container** | One — a single runtime per container. | Zero or more — you can define multiple runtimes (or none) per container. | | **Packages permitted / how dependencies are managed** | Only the base runtime and its extensions are permitted directly. To add non-runtime packages, you must use build-phase installation via hooks or dependencies. See [Keys used](#keys-used-in-each-image-type) below. | Supports multiple runtimes, extensions, packages and services. You define everything in the `stack` key (runtimes + Nix packages). See [Keys used](#keys-used-in-each-image-type) below. | | **Manual configuration / setup burden** | Lower: using a supported runtime means less manual setup; adding downloads, dependencies, and packages might require use of build hooks, which might complicate configuration. | Higher: you manually define the composition of the container or `stack` (runtimes + packages) of Nix packages. More flexible but requires more setup. | | **Maintenance & updates (patches, upgrades)** | Upsun handles image updates (minor and patch updates; security patches) automatically on deployment | You need to redeploy often to apply Nix package updates; update cadence depends on package maintainers.
Your team must be comfortable with upgrading, testing, and refactoring images promptly when Nix a channel becomes deprecated (every six months). | | **Flexibility (versions, custom binaries, tools)** | Limited to supported runtimes + permitted extensions. If you require combinations not supported by Upsun, you may hit limits (e.g. certain PHP + Node.js/Python combos). | High — you can mix runtimes, pick specific package versions, and include custom binaries/tools via Nix. | | **When to reconsider / migrate** | If you need many packages (beyond runtime extensions), complex dependencies, multiple runtimes, or custom tools, consider migrating to composable. | If you don’t need the complexity (just a simple runtime and minimal packages), composable may be unnecessary overhead. | ## Keys used in each image type {#keys-used-in-each-image-type} Both image types use many of the same keys. Differences in syntax or meaning are noted as needed - see the [Image properties](https://docs.upsun.com/create-apps/image-properties.md) section for the topics that describe each key. Defining your app's tech stack depends on the image type you choose: - Single-runtime image: Use the [``build``](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#build), [``dependencies``](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#dependencies), and [``runtime``](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#runtime) keys - Composable image: Use the [``stack.runtimes`` and ``stack.packages``](https://docs.upsun.com/create-apps/app-reference/composable-image.md#stack) keys ## 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](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#combine-single-runtime-and-composable-images) topic and [composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md#combine-single-runtime-and-composable-images) topic. --- # Source: https://docs.upsun.com/environments/backup.md # Back up an environment When you're making changes to your apps, you want to be sure those changes only improve things and don't make you lose any data. You also want to have a disaster recovery plan in place. Backups help you protect yourself against potential data loss. You might want to create backups of your live environment before merging a different environment into it or each time you increase the storage space of your services. You also have regularly scheduled automated backups of your production environments to cover most cases. Note that you can only create backups and restore active environments. To work with an [inactive environment](https://docs.upsun.com/glossary.md#inactive-environment), first activate it. ## How backup and restore works 1. As an [admin user](https://docs.upsun.com../administration/users.md), you can do a backup of your environment. This backup includes the complete data and code of the environment. All persistent data from all running [services](https://docs.upsun.com../add-services.md) and any files stored on [mounts](https://docs.upsun.com/create-apps/image-properties/mounts.md) are included. The backup is stored internally on Upsun. That is, the backup can be applied to environments on Upsun, but it can't be downloaded. If you need to download backups, instead [export your mount and service data](https://docs.upsun.com/learn/tutorials/exporting.md)). 2. You restore your environment using the backup. At this point, the data and code from the backup are restored to ensure a consistent state. The latest code in your repository may have been modified such that it no longer works correctly with the old, restored data. **Warning**: Upsun does not modify your Git repository. Any further changes you make use the latest code in your repository. 3. Depending on your needs, you can do the following: a) To use the code from the time of the backup as a baseline for future changes, make sure you restore it yourself in your Git repository. To do so, use Git commands such as `revert`. b) To use your latest code instead, just redeploy your environment or push a new change. **Note**: You may not want the code from the backup to be restored at step 2. For instance, if you have deleted containers since the backup, you may not want them to be restored with the backup. In this case, you can opt out of restoring the code. To do so, when you restore your backup, use the ``--no-code`` flag. Also, see [how resource allocation works](https://docs.upsun.com/manage-resources/resource-init.md#backup-restoration) when you restore a backup. ## Backups and downtime By default, creating a manual backup causes a momentary pause in site availability so that all requests can complete. This means the environment is backed up in a known consistent state. The total interruption is usually only 15 to 30 seconds. Any requests during that time are held temporarily, not dropped. To avoid this downtime, use [live backups](#live-backups). For consistent backups, create the backups during non-peak hours for your site. ## Data retention ### Manual backups [Manual backups](https://docs.upsun.com../environments/backup.md#create-a-manual-backup) are retained until you delete them or replace them with another backup. You can configure the maximum number of manual backups. Once that number is reached, any new manual backup automatically replaces the oldest backup. ### Automated backups Automated backups are retained for 2 days when you use the [default backup policy](#default-backup-policy) (meaning, 2 days worth of backups are retained at any given point). When you [configure your own automated backup policy](#configure-a-backup-policy), the retention time varies based on that configuration. Automated backups are always [live](#live-backups). ## Backup policy ### Default backup policy By default, Upsun provides 1 automated backup a day for your production environment, with a [2-day retention](https://docs.upsun.com/security/data-retention.md) (2 days worth of backups are retained at any given point). You can [configure your own backup policy](#configure-a-backup-policy). The default backup policy is equivalent to a custom backup policy using a `1d` interval and a count of `2` (see below). ### Configure a backup policy Upsun allows you to fully configure your own backup policy. You can setup a different automated backup schedule per environment type (production, staging, and development environments). On a given environment type, you can configure: - The total number of backups (manual and automated) - The total number of manual backups specifically - Multiple schedules for automated backups An automated backup schedule is composed of an interval and a count. The interval defines the frequency of the backups. An interval can be a couple of hours, days, weeks, months, or years. To configure an interval, use the following values: - ``h`` for hour - ``d`` for day - ``w`` for week - ``M`` for month - ``y`` for year The count defines the number of backups to retain. ### Configuration examples To take a backup every day and keep up to 7 backups, run the following command: ```bash {location="Terminal"} upsun project:curl settings -X PATCH \ -d '{ "data_retention": { "production": { "default_config": { "schedule": [ {"interval": "1d", "count": 7}, ] } } } }' ``` #### Configure multiple automated backup schedules You can use multiple schedules to implement you own backup policy. For instance, you may want to keep multiple recent backups and fewer older backups, using a command similar to the following: ```bash {location="Terminal"} upsun project:curl settings -X PATCH \ -d '{ "data_retention": { "production": { "default_config": { "schedule": [ {"interval": "1d", "count": 7}, {"interval": "1w", "count": 4}, {"interval": "1M", "count": 12} ] } } } }' ``` The command results in: - A backup every day for 7 days - A backup every week for 4 weeks - A backup every month for 12 months #### Set a limit for backups To configure the maximum number of backups (automated and manual backups alike) on your production environment, run a command similar to the following: ```bash {location="Terminal"} upsun project:curl /settings -X PATCH -d '{"data_retention": {"production": {"max_backups": 10}}}' ``` To configure the maximum number of manual backups on the production environment, run a command similar to the following: ```bash {location="Terminal"} upsun project:curl /settings -X PATCH -d '{"data_retention": {"production": {"default_config": {"manual_count": 1}}}}' ``` ## Live backups You can create backups without any downtime. This means your environment is running and open to connections during the backup. Because the connections may come in during backup creation, live backups may have data inconsistencies among containers. They may make restorations less reliable. To avoid such issues, schedule [manual backups](#create-a-manual-backup) during non-peak hours, when the short amount of downtime is least noticed. You can create a manual live backup on a Grid project: When [creating the backup](#create-a-manual-backup), select **Run live backup** in the last step. ## Create a manual backup You can create a manual backup using the [CLI](https://docs.upsun.com../administration/cli.md) or in the [Console](https://docs.upsun.com../administration/web.md). - Navigate to the environment you want to back up. - Click **Backups**. - Click **Backup**. - Click **Backup**. See more information on [backup policies](#backup-policy) and [data retention](#data-retention). ### Automate manual backups You can also automate the process of creating manual backups through [cron jobs](https://docs.upsun.com/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](https://docs.upsun.com../administration/cli/api-tokens.md#authenticate-in-an-environment). Although this process is automated, backups created in this way count as [manual backups](#manual-backups). They don't affect the automated backups taken as part of [a schedule](#configure-a-backup-policy). ## Physical storage location Backups are stored as binary large objects separate from your environments. This storage is replicated over multiple data centers in different locations [within the region your project is hosted in](https://upsun.com/trust-center/security/data-security/). This means that in the rare event a data center becomes unavailable, your backups are still available. --- # Source: https://docs.upsun.com/learn/bestpractices.md # Best practices --- # Source: https://docs.upsun.com/integrations/source/bitbucket.md # Integrate with Bitbucket If you have code in a Bitbucket repository, you might want to connect it to a Upsun project. This means you can keep your Bitbucket workflows and treat the Bitbucket repository as the source of truth for your code. Your Upsun project becomes a mirror of your Bitbucket repository. This means you shouldn't push code directly to Upsun. Any changes you push directly get overwritten by the integration when changes happen in the Bitbucket repository. When you set up an integration with Bitbucket, it automates the following processes for you: - Creating a new environment when a branch is created or a pull request is opened. - Rebuilding the environment when new code is pushed to Bitbucket. - Deleting the environment when a pull request is merged. You can set up an integration with either Bitbucket Cloud or a self-hosted [Bitbucket Server](https://confluence.atlassian.com/bitbucketserver/). ## Before you begin To manage source integrations, you need to be a [project admin](https://docs.upsun.com../../administration/users.md). You also need a Bitbucket Cloud or Bitbucket Server repository with working code. ## Bitbucket Cloud ### 1. Create an OAuth consumer To integrate your Upsun project with an existing Bitbucket Cloud repository, [create an OAuth consumer](https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/): ![A screenshot of how to setup the Bitbucket OAuth consumer](https://docs.upsun.com/images/integrations/bitbucket/bitbucket-oauth-consumer.svg "0.35") **Note**: Be sure to define the above as a private consumer by checking the **This is a private consumer** box. The **Callback URL** isn't important in this case. You can set it to `http://localhost`. Copy the **Key** and **Secret** for your consumer. ### 2. Enable the Cloud integration To enable the integration, use either the [CLI](https://docs.upsun.com/administration/cli.md) or the [Console](https://docs.upsun.com/administration/web.md). - ``PROJECT_ID`` is the ID of your Upsun project. - ``OWNER/REPOSITORY`` is the name of your repository in Bitbucket. - ``CONSUMER_KEY`` is the key of the [OAuth consumer you created](#1-create-an-oauth-consumer). - ``CONSUMER_SECRET`` is the secret of the [OAuth consumer you created](#1-create-an-oauth-consumer). For example, if your repository is located at ``https://bitbucket.org/platformsh/platformsh-docs``, the command is similar to the following: ```bash {} upsun integration:add \ --project abcdefgh1234567 \ --type bitbucket \ --repository platformsh/platformsh-docs \ --key abc123 \ --secret abcd1234 \ ``` - Select the project where you want to enable the integration. - Click **Settings Settings**. - Under **Project settings**, click **Integrations**. - Click **+ Add integration**. - Under **Bitbucket**, click **+ Add**. - Complete the form with: - The repository in the form ``owner/repository`` - The [key and secret you generated](#1-create-an-oauth-consumer) - Check that the other options match what you want. - Click **Add integration**. In both the CLI and Console, you can choose from the following options: | CLI flag | Default | Description | | ---------------- | ------- | ------------------------------------------------------------------------- | | `fetch-branches` | `true` | Whether to mirror and update branches on Upsun and create inactive environments from them. When enabled, merging on an Upsun environment isn't possible. That is, merging environments must be done on the source repository rather than on the Upsun project. See note below for details related to this flag and synchronizing code from a parent environment. | | `prune-branches` | `true` | Whether to delete branches from Upsun that don’t exist in the Bitbucket repository. When enabled, branching (creating environments) must be done on the source repository rather than on the Upsun project. Branches created on Upsun that are not on the source repository will not persist and will be quickly pruned. Automatically disabled when fetching branches is disabled. | | `build-pull-requests` | `true` | Whether to track all pull requests and create active environments from them, which builds the pull request. | | `resync-pull-requests` | `false` | Whether to sync data from the parent environment on every push to a pull request. | | `resources-init` | `false` | To [specify a resource initialization strategy](https://docs.upsun.com/manage-resources/resource-init.md#first-deployment) for new containers. Once set, the strategy applies to **all** the deployments you launch through your source integration. See more information on [available resource initialization strategies](https://docs.upsun.com/manage-resources/resource-init.md#specify-a-resource-initialization-strategy). | **Note**: To [keep your repository clean](https://docs.upsun.com/learn/bestpractices/clean-repository.md) and avoid performance issues, make sure you enable both the ``fetch-branches`` and ``prune-branches`` options. ### 3. Validate the integration Verify that your integration is functioning properly [using the CLI](https://docs.upsun.com../overview.md#validate-integrations): ```bash upsun integration:validate ``` #### Add the webhook manually If the integration was added with the correct permissions, the necessary webhook is added automatically. If you see a message that the webhook wasn't added, add one manually. To configure a webhook on a Bitbucket repository, you need to have Admin [user permissions](https://support.atlassian.com/bitbucket-cloud/docs/manage-webhooks/). 1. Get the webhook URL by running this command: `upsun integration:get --property hook_url`. 1. Copy the returned URL. 1. Follow the [Bitbucket instructions to create a webhook](https://support.atlassian.com/bitbucket-cloud/docs/manage-webhooks/#Create-webhooks) using the URL you copied. Make sure to update the triggers to include all pull request events except comments and approval. You can now start pushing code, creating new branches, and opening pull requests directly in your Bitbucket repository. Your Upsun environments are automatically created and updated. ## Bitbucket Server ### 1. Generate a token To integrate your Upsun project with a repository on a Bitbucket Server instance, you first need to create an access token associated with your account. [Generate a token](https://confluence.atlassian.com/display/BitbucketServer/HTTP+access+tokens). and give it at least read access to projects and admin access to repositories. Copy the token. ### 2. Enable the Server integration To enable the integration, use either the [CLI](https://docs.upsun.com/administration/cli.md) or the [Console](https://docs.upsun.com/administration/web.md). - ``PROJECT_ID`` is the ID of your Upsun project. - ``OWNER/REPOSITORY`` is the name of the repository in Bitbucket server. - ``BITBUCKET_SERVER_ACCESS_TOKEN`` is the [token you generated](#1-generate-a-token). - ``BITBUCKET_SERVER_URL`` is the URL for your Bitbucket server. For example, if your repository is located at ``https://example.com/upsun/upsun-docs``, the command is similar to the following: ```bash {} upsun integration:add \ --project abcdefgh1234567 \ --type bitbucket_server \ --repository upsun/upsun-docs \ --username user@example.com \ --token abc123 --bitbucket-url https://example.com ``` - Select the project where you want to enable the integration. - Click Settings **Settings**. - Under **Project settings**, click **Integrations**. - Click **+ Add integration**. - Under **Bitbucket server**, click **+ Add**. - Complete the form with: - Your server URL - Your Bitbucket username - The [token you generated](#1-generate-a-token) - The Bitbucket server project name - The repository in the form ``owner/repository`` - Check that the other options match what you want. - Click **Add integration**. In both the CLI and Console, you can choose from the following options: | CLI flag | Default | Description | | ``fetch-branches`` | ``true`` | Whether to mirror and update branches on Upsun and create inactive environments from them. | | ``prune-branches`` | ``true`` | Whether to delete branches from Upsun that don’t exist in the Bitbucket server repository. Automatically disabled when fetching branches is disabled. | | ``build-pull-requests`` | ``true`` | Whether to track all pull requests and create active environments from them, which builds the pull request. | | ``pull-requests-clone-parent-data`` | ``true`` | Whether to clone data from the parent environment when creating a pull request environment. | To [keep your repository clean ](https://docs.upsun.com/learn/bestpractices/clean-repository.md) and avoid performance issues, make sure you enable both the ``fetch-branches`` and ``prune-branches`` options. ### 3. Validate the integration Verify that your integration is functioning properly [using the CLI](https://docs.upsun.com../overview.md#validate-integrations): ```bash upsun integration:validate ``` #### Add the webhook manually If the integration was added with the correct permissions, the necessary webhook is added automatically. If you see a message that the webhook wasn't added, add one manually. To configure a webhook on a Bitbucket repository, you need to have Admin [user permissions](https://support.atlassian.com/bitbucket-cloud/docs/manage-webhooks/). 1. Get the webhook URL by running this command: `upsun integration:get --property hook_url`. 1. Copy the returned URL. 1. Follow the [Bitbucket instructions to create a webhook](https://confluence.atlassian.com/bitbucketserver076/managing-webhooks-in-bitbucket-server-1026535073.md#ManagingwebhooksinBitbucketServer-creatingwebhooksCreatingwebhooks) using the URL you copied. Send all events except comments and approval. You can now start pushing code, creating new branches, and opening pull requests directly in your Bitbucket repository. Your Upsun environments are automatically created and updated. ## Environment parent and status When a **branch** is created in Bitbucket, an environment is created in Upsun with the default branch as its parent. It starts as an [inactive environment](https://docs.upsun.com/glossary.md#inactive-environment) with no data or services. When a **pull request** is opened in Bitbucket, an environment is created in Upsun with the pull request's target branch as its parent. It starts as an [active environment](https://docs.upsun.com/glossary.md#active-environment) with a copy of its parent's data. ## Source of truth When you add an integration, your Bitbucket repository is considered to be the source of truth for the project. Your Upsun project is only a mirror of that repository and you can only push commits to Bitbucket. To clone your code, follow these steps: - In the Console, open the project you want to clone. - Click **Code**. - Click **Git**. - Run the command you find using Git. When you do this, you're cloning from your integrated Bitbucket repository, if you have the [appropriate access to do so](https://docs.upsun.com/integrations/source/troubleshoot.md). ### Sync, fetch, and prune An integration from Bitbucket to Upsun establishes that: - Bitbucket is the source of truth, where Git operations occur - Upsun is a mirror of that repository - provisioning infrastructure according to configuration, and orchestrating environments according to the branch structure of the Bitbucket repository Actions that take place on Upsun don't affect commits on Bitbucket. Because of this, the Bitbucket integration enables both `fetch-branches` (track branches on Bitbucket) and `prune-branches` (delete branches that don't exist on Bitbucket) by default. You can change these settings but it is recommend to keep them. When enabled by default, you are limited by design as to what actions can be performed within the context of a Upsun project with a Bitbucket integration: | Action | Observation | Recommendation | | :---------------- | :---------------- | :------- | | Branch from parent | Running [`environment:branch`](https://docs.upsun.com/administration/cli/reference#environmentbranch) with the CLI, or selecting **Branch** in Console produces a new child environment, but it's deleted shortly after automatically. | Contribute to the Bitbucket repository itself by creating a branch and pull request. When the PR has been opened, a new environment will be provisioned for it. | | Merge in parent | Running [`environment:merge`](https://docs.upsun.com/administration/cli/reference#environmentmerge) with the CLI fails locally, and the **Merge** option in Console is not clickable. | Review and merge pull requests and/or branches on the Bitbucket repository. | | Merge into child (sync code) | Running [`environment:synchronize`](https://docs.upsun.com/administration/cli/reference#environmentsynchronize) with the CLI fails locally, and the **Sync** option in Console won't allow me to include `code` in that sync. | Perform the merge locally from a matching branch on Bitbucket. For example, clone the most recent parent (`git pull origin parent-branch`), switch to the pull request branch (`git checkout ga-staging`), and then merge the parent into the current branch (`git merge main`). | ## Pull request URLs When a pull request is deployed, the integration reports the primary URL for the deployed environment. So you get a link to the deployed environment right in the pull request. If you have multiple routes, ensure the correct one is reported by [specifying the primary route](https://docs.upsun.com/define-routes.md#route-configuration-reference). --- # Source: https://docs.upsun.com/learn/overview/build-deploy.md # Build and deploy Each time you push a change to your app through Git or activate an [environment](https://docs.upsun.com/environments.md), your app goes through a process to be built and deployed. If your app is redeployed with no changes to its codebase, the output of the previous build and deploy process is reused. The build process looks through the configuration files in your repository and assembles the necessary containers. The deploy process makes those containers live, replacing any previous versions, with minimal interruption in service. ![The steps in the build and deploy process](https://docs.upsun.com/images/workflow/build-pipeline.svg "0.50") Hooks are points in the build and deploy process where you can inject a custom script. ## The build The outcome of the build process is designed to be repeatable and reusable. Each app in a project is built separately. Container configuration depends exclusively on your configuration files. So each container is tied to a specific Git commit. If there are no new changes for a given container, the existing container can be reused. This saves you the time the build step would take. This means the build is independent of the given environment and preview environments are perfect copies of production. If you use environment variables to set up different build configuration options for different environments, your build step isn't reused and your preview environments may differ from production. You can't connect to services (like databases) during the build step. Once the app has gone through all of the build steps, it can connect to services in the deploy process. ### Build steps 1. **Validate configuration**: The configuration is checked by validating the `.upsun` directory and scanning the repository for any app configuration to validate. 2. **Pull container images**: Any container images that have been built before and that don't have any changes are pulled to be reused. 3. **Install dependencies**: If you have specified additional global dependencies, they're downloaded during this step. This is useful for commands you may need in the build hook. 4. **Run build flavor commands**: For some languages (NodeJS, PHP), a series of standard commands are run based on the build flavor. You can change the flavor or skip the commands by specifying it in your `.upsun/config.yaml` file. 5. **Run build hook**: The `build` hook comprises one or more shell commands that you write to finish creating your production code base: for example, compiling Sass files, running a bundler, rearranging files on disk, or compiling. The committed build hook runs in the build container. During this time, commands have write access to the file system, but there aren't connections to other containers (services and other apps). For automated builds, you can use the [`CI` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) in build scripts and tooling to modify build behavior (for example, to disable attempts to connect to other containers during the build phase, or to disable interactivity). These modifications can help to prevent build failures. You can also manually [cancel deployments stuck on the build hook](https://docs.upsun.com/environments/cancel-activity.md). 6. **Freeze app container**: The file system is frozen and produces a read-only container image, which is the final build artifact. ## The deploy The deploy process connects each container from the build process and any services. The connections are defined in your app and services configuration. So unlike the build process, you can now access other containers, but the file system is read-only. ### Deploy steps 1. **Hold requests**: Incoming [idempotent requests](https://www.iana.org/assignments/http-methods/http-methods.xhtml) (like `GET`, `PUT`, `DELETE` but **not** `POST`, `PATCH` etc.) are held. 1. **Unmount current containers**: Any previous containers are disconnected from their file system mounts. 1. **Mount file systems**: The file system is connected to the new containers. New branches have file systems cloned from their parent. 1. **Expose services**: Networking connections are opened between any containers specified in your app and services configurations. 1. **Run (pre-) start commands**: The [commands](https://docs.upsun.com/create-apps/image-properties/web.md#web-commands) necessary to start your app are run. Often this stage will only include a start command, which is restarted if ever terminated going forward. You may also, however, define a `pre_start` command, when you need to run _per-instance_ actions. In this case, as you might expect, the `pre_start` command is run, then the `start` command. 1. **Run deploy hook**: The `deploy` hook is any number of shell commands you can run to finish your deployment. This can include clearing caches, running database migrations, and setting configuration that requires relationship information. 1. **Serve requests**: Incoming requests to your newly deployed application are allowed. After the deploy process is over, any commands in your `post_deploy` hook are run. ## Deployment types Upsun supports two deployment types - automatic and manual. These types help to provide control over when changes are applied to development, staging and production environments. ### Automatic deployment (default) This is the default behavior for all environments. With automatic deployment, changes like code pushes and variable updates are deployed immediately. This type of deployment is best suited for rapid iteration during development. ### Manual deployment You can deploy applications manually in any environment type (development/preview, staging, and production). When [enabled](#change-deployment-type), manual deployment lets you control when deployments happen: changes are staged but not deployed until you explicitly trigger a deployment. Manual deployment is ideal for teams that want to bundle multiple changes and deploy them together in a controlled manner. When manual deployment is enabled in an environment, the following actions are queued until deployment is triggered: | Category | Staged Activities | |----------------------|------------------| | **Code** | `environment.push`, `environment.merge`, `environment.merge-pr` | | **Variables** | `environment.variable.create`, `update`, `delete` | | **Resources** | `environment.resources.update` | | **Domains & Routes** | `environment.domain.*`, `environment.route.*` | | **Subscription** | `environment.subscription.update `| | **Environment Settings** | `environment.update.http_access`, `smtp`, `restrict_robots` | **Note**: To restart your application without applying staged changes, run ``upsun redeploy`` or click **Redeploy** in the Console. ### Change deployment type {#change-deployment-type} You can adjust deployment behavior in your environment. The output should look similar to the example below: ```bash {} Selected project: [my-project (ID)] Selected environment: main (type: production) Deployment type: manual ``` To switch to manual, navigate to the environment settings in the Console and select the manual deployments option. ### Trigger deployment manually Once manual deployment is enabled, eligible changes are staged. You can deploy them in the following ways: The output should look similar to the example below: ```bash {} Deploying staged changes: +---------------+---------------------------+-----------------------------------------------------------+---------+ | ID | Created | Description | Result | +---------------+---------------------------+-----------------------------------------------------------+---------+ | 5uh3xwmkh5boq | 2026-01-01T14:01:10+00:00 | Patrick pushed to main | failure | | fno2qiodq7e3c | 2026-01-01T13:06:18+00:00 | Arseni updated resource allocation on main | success | | xzvcazrtoafeu | 2026-01-01T13:01:10+00:00 | Pilar added variable HELLO_WORLD to main | success | | fq73u53ruwloq | 2026-01-01T12:06:17+00:00 | Pilar pushed to main | success | +---------------+---------------------------+-----------------------------------------------------------+---------+ ``` In the Console, a deploy button will be visible in the environment whenever changes are staged. Click this button to deploy your staged changes.Trigger the deployment of staged changes with the following: ```bash {} POST /projects/{projectId}/environments/{environmentId}/deploy ``` **Note**: As soon as your deployment type is switched from manual to automatic, all currently staged changes are deployed immediately and the environment resumes its default automatic deployment behavior. ## Zero Downtime Deployments ## What is Zero Downtime? By default, deployments use a stop-start [deployment strategy](#deployment-strategies) (services stop, then restart with updates). Zero Downtime Deployments use a _rolling_ deployment strategy, enabling you to deploy changes to your environment without taking your app offline and without interrupting live traffic. ## How Zero Downtime works Instead of stopping services before updating, a temporary copy of your application is created and prepared behind the scenes during the deployment process. Your services work with both the original application and the temporary copy during the whole deployment process, which means that any changes you make to your services during deployment will be applied to the original application. Here's the step-by-step process: **1. A temporary clone of your application is created** - Upsun starts a temporary container that runs a cloned version of your app. - The clone handles all live traffic during this time. - Services (for example, Redis) serve both the original app _and_ the clone. ![A duplicate is made of your current application](https://docs.upsun.com/images/ZDD/ZDD-1.jpg "0.4") **2. The original application is updated** - The original app is updated with the new code and configuration. - The deploy hook is run on the original app. **3. The clone is removed after deployment** - When deployment of the original app is complete, the clone (the temporary container) is shut down and removed. - All traffic and services are now applied to the original app only. ![The duplicate of your original application is removed](https://docs.upsun.com/images/ZDD/ZDD-2.jpg "0.4") **Note**: During a zero-downtime deployment, the original app and its clone run simultaneously short period (a few seconds to a couple of minutes). **You are billed for extra resources while both app versions active.** If your app’s deployment phase takes longer and uses more resources, expect proportionally higher costs. ### Deployment strategies #### Stop-start (default) - Services stop first then restart with the new version - Deployment is fast but may cause temporary downtime or freezing depending on the application #### Rolling (ZDD) - Creates a temporary copy of your services - Routes traffic to the temporary copy while updating the original services - Removes the temporary copy once the deployment is complete - No downtime for users - Deployment may take longer and use slightly more resources temporarily ### Stop-start vs Rolling (ZDD) | Feature | Stop-start (default) | Rolling (ZDD) | |---------|--------------------|---------------| | **User impact** | Services may be unavailable briefly | Users experience no downtime | | **Deployment speed** | Fast | Slightly longer | | **Resource usage** | Standard | Higher temporarily (due to parallel services) | | **Process** | Stop services → deploy updates → start services | Deploy temporary services → switch traffic → update original services → remove temporary services | | **Best for** | Small apps, quick updates | Apps requiring uninterrupted availability | | **Limitations** | Causes downtime/freezetime | Longer deploy time, higher temporary resource use | ### Use cases {#use-cases} | Use Case | Recommendation | |----------|----------------| | Code pushes | Suitable | | Config or environment variable changes | Suitable | | Stateful service updates (databases, caches) | Not suitable | | Database schema migrations | Not suitable (unless updates are both backward **and** forward compatible) | ## How to use Zero Downtime Deployments Before running zero-downtime deployments, it is recommended that you enable [manual deployment](#manual-deployment). **With Manual Deployments** ```bash {} upsun environment:deploy --strategy rolling ``` In the Console, navigate to the environment settings and trigger a deployment from the deployment modal. Select Zero Downtime as a deployment strategy. ``POST /projects/{projectId}/environments/{environmentId}/deploy { "strategy": "rolling" }`` ## Connection handling During any deployment, long-lived connections like WebSockets or Server-Sent Events (SSE) are dropped. With ZDD, you can plan for smooth reconnection: - SSE supports automatic [retry logic](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#retry). - WebSocket clients should implement reconnect logic. ## Zero Downtime Troubleshooting This section covers two common scenarios and how to resolve them. **Note**: If the last deployment failed, you can only use the default stop-start strategy. ### Application is slow to start If your application takes longer to become responsive, traffic might be [switched back to your original application](#how-zero-downtime-works) before it’s fully ready. This can cause temporary errors immediately after deployment. **Use a post_start command**: You can use the ``post_start`` command to ensure your app is fully active before traffic is routed to it. This command can perform checks or wait until your application starts listening on the expected port. For example, if your framework needs several seconds to initialize (e.g. building caches or database connections), ``post_start`` can help coordinate the handover so the app receives traffic only when it’s ready. An example of a ``post_start`` command waiting for your application would be: ``web: commands: post_start: | date curl -sS --retry 20 --retry-delay 1 --retry-connrefused localhost -o /dev/null`` **For more information about the ``post_start`` command, visit [web commands](https://docs.upsun.com/create-apps/image-properties/web.md#post_start).** ### Deployment fails midway If deployment fails partway through, one of the applications (either the original or the clone) may remain active in the background while the other continues to serve traffic. This can lead to an increase in resource usage and costs. To troubleshoot a failure, try one or both of the following: - [Enable manual deployments](#change-deployment-type) if not already enabled; then, try to manually redeploy the application. - Deploy the environment using the stop-start strategy to ensure no clones remain active. If you still experience issues, [contact support](https://docs.upsun.com/learn/overview/get-support.md). ## Deployment philosophy Upsun values consistency over availability, acknowledging that it's nearly impossible to have both. During a deployment, the [deploy hook](https://docs.upsun.com/create-apps/hooks/hooks-comparison.md#deploy-hook) may make database changes that are incompatible with the previous code version. Having both old and new code running in parallel on different servers could therefore result in data loss. Upsun believes that a minute of planned downtime for authenticated users is preferable to a risk of race conditions resulting in data corruption, especially with a CDN continuing to serve anonymous traffic uninterrupted. This brief downtime affects only the environment being updated. Deployments to a staging or development branch have no impact on the production environment and cause no downtime. ## What's next * See how to [configure your app](https://docs.upsun.com/create-apps.md) for the entire process. * Learn more about [using build and deploy hooks](https://docs.upsun.com/create-apps/hooks.md). --- # Source: https://docs.upsun.com/define-routes/cache.md # HTTP cache Upsun supports HTTP caching at the server level. Caching is enabled by default, but is only applied to ``GET`` and ``HEAD`` requests. The cache can be controlled using the `cache` key in your `.upsun/config.yaml` file. If a request can be cached, Upsun builds a cache key from several request properties and stores the response associated with this key. When a request comes with the same cache key, the cached response is reused. When caching is on... * you can configure cache behavior for different location blocks in your `.upsun/config.yaml`; * the router respects whatever cache headers are sent by the application; * cookies bypass the cache; * responses with the `Cache-Control` header set to `Private`, `No-Cache`, or `No-Store` aren't cached. You should _not_ use the Upsun HTTP cache if you're using [Varnish](https://docs.upsun.com../add-services/varnish.md) or an external CDN such as [Fastly](https://docs.upsun.com../domains/cdn/fastly.md) or [Cloudflare](https://docs.upsun.com../domains/cdn/cloudflare.md). Mixing cache services together most likely results in caches that are stale and can't be cleared. For more details, see [best practices on HTTP caching](https://docs.upsun.com/learn/bestpractices/http-caching.md). ## Basic usage The HTTP cache is enabled by default, however you may wish to override this behavior. To configure the HTTP cache, add a `cache` key to your route. You may like to start with the defaults: ```yaml {location=".upsun/config.yaml"} routes: https://{default}/: type: upstream upstream: myapp:http cache: enabled: true default_ttl: 0 cookies: ['*'] headers: ['Accept', 'Accept-Language'] ``` ## Example In this example, requests are cached based on the URI, the `Accept` header, `Accept-Language` header, and `X-Language-Locale` header. Any response that lacks a `Cache-Control` header is cached for 60 seconds. The presence of any cookie in the request disables caching of that response. ```yaml {location=".upsun/config.yaml"} routes: https://{default}/: type: upstream upstream: myapp:http cache: enabled: true headers: ['Accept', 'Accept-Language', 'X-Language-Locale'] cookies: ['*'] default_ttl: 60 ``` ## How it works ### The cache key If a request can be cached, Upsun builds a cache key from several request properties and stores the response associated with this key. When a request comes with the same cache key, the cached response is reused. There are two parameters that let you control this key: `headers` and `cookies`. The default value for these keys are the following: ```yaml {location=".upsun/config.yaml"} routes: https://{default}/: # ... cache: enabled: true cookies: ['*'] headers: ['Accept', 'Accept-Language'] ``` ### Duration The cache duration is decided based on the `Cache-Control` response header value. If no `Cache-Control` header is in the response, then the value of `default_ttl` key is used. ### Conditional requests Conditional requests using `If-Modified-Since` and `If-None-Match` are both supported. The web server doesn't honor the `Pragma` request header. ### Cache revalidation When the cache is expired (indicated by `Last-Modified` header in the response) the web server sends a request to your application with `If-Modified-Since` header. If the `If-None-Match` header is sent in the conditional request when `Etag` header is set in the cached response, your application can extend the validity of the cache by replying `HTTP 304 Not Modified`. ### Flushing The HTTP cache doesn't support a complete cache flush, but you can invalidate the cache by setting `cache: false`. Alternatively, the cache clears on a rebuild, so triggering a rebuild (pushing a new commit) effectively causes a complete cache flush. ## Cache configuration properties ### `enabled` Turns the cache on or off for a route. **Note**: Regular expressions in routes are **not** supported. ### Allowing only specific cookies Some applications use cookies to invalidate cache responses, but expect other cookies to be ignored. This is a case of allowing only a subset of cookies to invalidate the cache. ```yaml {location=".upsun/config.yaml"} routes: https://{default}/: # ... cache: enabled: true cookies: ["MYCOOKIE"] ``` ### Cache HTTP and HTTPS separately using the `Vary` header Set the Vary header to `X-Forwarded-Proto` [custom request header](https://docs.upsun.com/development/headers.md) to render content based on the request protocol (i.e. HTTP or HTTPS). By adding `Vary: X-Forwarded-Proto` to the response header, HTTP and HTTPS content would be cached separately. ### Cache zipped content separately Use `Vary: Accept-Encoding` to serve different content depending on the encoding. Useful for ensuring that gzipped content isn't served to clients that can't read it. --- # Source: https://docs.upsun.com/environments/cancel-activity.md # Cancel an activity If you have a stuck activity or you pushed a change you know doesn't work, you can cancel a running or pending activity on an environment. This works for activities such as builds, cron jobs, and source operations. You can cancel activities using the [CLI](https://docs.upsun.com../administration/cli.md) or in the [Console](https://docs.upsun.com../administration/web.md). If you have more than one running or pending activity, choose which activity to cancel. You can also cancel a specific activity by specifying its ID: ```bash {} upsun activity:cancel ``` Get the ID from the [activity log](https://docs.upsun.com/increase-observability/logs/access-logs.md#activity-logs). - Open the environment where you want to cancel an activity. - In the [activity log](https://docs.upsun.com/increase-observability/logs/access-logs.md#activity-logs), click More **More** next to the activity you want to cancel. - Click **Cancel**. ## Non-cancellable activities An activity can finish in between when you load the Console and when you click **Cancel**. For example, when the activity is a [source operation](https://docs.upsun.com../create-apps/source-operations.md) and the related build hook has already completed. In such cases, you get a message that the activity can't be cancelled. --- # Source: https://docs.upsun.com/domains/cdn.md # Content delivery networks (CDNs) Using a CDN speeds up the delivery of your site's content to its users. The CDN deploys edge servers at many locations around the world. These edge servers behave like local caches to nearby users. Bringing content closer to users helps enhance your site's perceived performance and so can improve user engagement and retention. Fastly is the recommended CDN for Upsun projects. Self-service projects don't include a CDN by default, but you can set up one at any time, such as [Fastly](https://docs.upsun.com/domains/cdn/fastly.md) or [Cloudflare](https://docs.upsun.com/domains/cdn/cloudflare.md). ## DNS records To start routing client traffic through your CDN, [set up a custom domain](https://docs.upsun.com../steps.md). If you use `CNAME` records for your custom domain, these records [can't point to apex domains](https://docs.upsun.com../steps/dns.md). But most CDN providers offer workarounds. For example, Fastly offers [Anycast options](https://docs.upsun.com/domains/cdn/fastly.md#3-handle-apex-domains) and Cloudflare offers [`CNAME` flattening](https://docs.upsun.com/domains/cdn/cloudflare.md#3-handle-apex-domains). ## Host header forwarding When an HTTP request is made to a website, the client adds a `Host` header to the request. The value of this header is the domain name the request is made to. When a server hosts multiple websites, like what a CDN does, it can use the `Host` header to identify which domain to access to handle the request. When a request is made from a client to fetch a resource on a CDN edge server, the `Host` header value is rewritten to point to the CDN. If the requested resource isn't cached on the edge server, the edge server makes a request to the Upsun server to pull and cache the resource. For this process to be successful, set an `X-Forwarded-Host` header to forward the original `Host` header value to the Upsun server. Use your root domain as the value of your `X-Forwarded-Host` header, for example: `example.com`. To ensure your app handles the `X-Forwarded-Host` header, you might need to adjust your app configuration. For more information on how to set up an `X-Forwarded-Host` HTTP header, see your CDN provider's official documentation. ## Disable the router cache When you use a CDN, the Upsun router [HTTP caching](https://docs.upsun.com../../define-routes/cache.md) becomes redundant. To disable it, change your cache configuration for the routes behind a CDN to the following: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": type: upstream upstream: "myapp:http" cache: # Disable the HTTP cache on this route. It's handled by the CDN instead. enabled: false ``` ## Prevent direct access to your server When you use a CDN, you might want to prevent direct access to your Upsun server for security purposes. ### IP filtering and HTTP auth While using password or IP based authentication might be possible, it is insecure, and unreliable. There are many scenarios in which the implementation can fail, and the security features circumvented. Furthermore, IP based filtering will usually be impossible due to the fact that most CDNs use the `x-forwarded` HTTP header, which your project origin will use as the visitor IP address. Both methods are highly insecure, and we highly recommend against them. ### Enable mTLS If your CDN provider supports it, you can secure your site through [mTLS](https://docs.upsun.com../../define-routes/https.md#enable-mtls). To enable mTLS, follow these steps: 1. Obtain an Origin Certificate Authority (CA) certificate from your CDN provider. 2. Check that the CA certificate is a `.crt` file. If the file is a `.pem` file, rename it to `cdn.crt`. 3. Add the `cdn.crt` file to your Git repository. 4. Change your routing configuration for the routes behind a CDN to the following: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}": tls: client_authentication: "require" client_certificate_authorities: - !include type: string path: cdn.crt ``` The procedure can vary depending on your CDN. Contact your CDN provider for specific assistance. Note that mTLS is a mutual authentication process. It allows your CDN to check that it's communicating with your Upsun server and vice versa. So in addition to the CA certificate supplied by your CDN provider, you need to [create your own TLS certificate](https://docs.upsun.com../../define-routes/https.md). --- # Source: https://docs.upsun.com/environments/change-parent.md # Change an environment's parent All environments default to having another environment as their parent. If you [branched](https://docs.upsun.com/glossary.md#branch) the environment from another, its parent starts as the environment it was created from. If you pushed a branch through Git or a [source integration](https://docs.upsun.com../integrations/source.md), the parent defaults to the default environment. To change the environment's parent, follow these steps: Run the following command: ```bash {} upsun environment:info -e parent ``` So if you have the environment ``new-feature`` and want to change its parent to ``main``, run the following: ```bash {} upsun environment:info -e new-feature parent main ``` If you're not using a [source integration](https://docs.upsun.com/integrations/source.md), you can also set a parent for your environment when pushing changes to it. To do so, run the following command: ```bash git push -o "environment.parent=" ``` Learn more about how to [trigger actions on `push`](https://docs.upsun.com/environments.md#push-options). --- # Source: https://docs.upsun.com/projects/change-project-timezone.md # Change the project timezone The project timezone affects [automated backups](https://docs.upsun.com../environments/backup.md). The project timezone doesn't affect: - [App runtime](https://docs.upsun.com/create-apps/timezone.md). - [Cron jobs](https://docs.upsun.com/create-apps/image-properties/crons.md). - [System logs](https://docs.upsun.com/increase-observability/logs.md). UTC is the default timezone for all logs. To change the timezone for a project, follow these steps: 1. Open the project where you want to change the timezone. 2. Click Settings **Settings**. 3. Select the timezone from the list. 4. Click **Save**. --- # Source: https://docs.upsun.com/learn/bestpractices/clean-repository.md # Keep your Git repository clean When a Git repository contains a high number of references and files, the performance of Git can decrease. This is why most Git providers have repository size limits in place (for more information, see the [GitHub](https://docs.github.com/en/repositories/working-with-files/managing-large-files/about-large-files-on-github), [GitLab](https://docs.gitlab.com/ee/user/gitlab_com/index.md#account-and-limit-settings) and [Bitbucket](https://support.atlassian.com/bitbucket-cloud/docs/reduce-repository-size/) documentation). The Upsun API and [Console](https://docs.upsun.com/administration/web.md) are closely tied to Git. When the performance of Git decreases, Upsun API servers also become slower. As a user, you can then experience significant latencies. If your repository becomes too large, your Console may even become unresponsive, leaving you unable to access your project. To avoid such issues, make sure you keep your Git repository clean by following the instructions on this page. If you're already facing performance issues and suspect they might be related to the size of your Git repository, see how you can [troubleshoot a sizeable Git repository](#troubleshoot-a-sizeable-git-repository). ## Enable the automated pruning of old branches in your project To keep your repository size to a minimum, make sure that branches that don't exist anymore in your repository have also been deleted from Upsun. To automate this process, when setting up a [source integration](https://docs.upsun.com/integrations.md), enable the `prune-branches` option. If you already have a source integration set up and want to enable the `prune-branches` option, follow these steps: - Then, to enable the ``prune-branches`` option, run the following command: ```bash {} upsun integration:update --project --prune-branches true ``` - Navigate to your project. - Click Settings **Settings**. - Click **Project Settings**. - Click **Integrations** and select your source integration. - Click **Edit**. - Enter your access token and click **Continue**. - Select your repository and check the following boxes: - **Fetch branches from the remote repository to your project** (``fetch-branches`` option, mandatory to enable ``prune-branches``). - **Remove branches from your project that have disappeared remotely (requires the fetch branches option to be enabled)** (``prune-branches`` option). - Click **Save**. ## Upload your files through mounts Keeping too many files, especially large binary files, in your Git repository can cause performance and stability issues. Therefore, Upsun recommends that you only commit your source code in Git. To upload any other files to your app, [create mounts](https://docs.upsun.com/create-apps/image-properties/mounts.md) and [transfer your files directly to them](https://docs.upsun.com/development/file-transfer.md#transfer-a-file-to-a-mount). **Note**: Upsun does not currently support [Git Large File Storage](https://git-lfs.com/). There is a **100MB default file size limit** for direct Git pushes to Upsun. Pushing files larger than the limit will result in rejecting the push, so please keep this in mind. If you’d like to request a custom limit, please [contact Support](https://docs.upsun.com/learn/overview/get-support.md). ## Troubleshoot a sizeable Git repository If you're experiencing latencies or can't access your Console anymore, your Git repository may have become too large and may need to be cleaned up. To do so, follow these instructions: 1. Remove old, unwanted files from your repository (especially large files). You can do it manually, or use a tool such as [BFG Repo-Cleaner](https://rtyley.github.io/bfg-repo-cleaner/). 2. Remove stale branches from your repository and Upsun project. 3. Rebase and/or squash commits to clean up your history. 4. Make sure you [enable the automated pruning of old branches in your project](#enable-the-automated-pruning-of-old-branches-in-your-project) and [upload your files through mounts](#upload-your-files-through-mounts) to avoid facing the same situation in the future. --- # Source: https://docs.upsun.com/administration/cli.md # Command line interface (CLI) See how to use and manage your Upsun projects directly from your terminal. Anything you can do within the Console can be done with the CLI. The CLI uses the git interface and the [Upsun REST API](https://api.platform.sh/docs/) to accomplish tasks. Its source code is hosted on [GitHub](https://github.com/platformsh/cli). ## 1. Install To install the CLI, use a [Bash installation script](https://github.com/platformsh/cli#user-content-bash-installer). You can also install with [Homebrew](https://brew.sh/) (on Linux, macOS, or the Windows Subsystem for Linux) or [Scoop](https://scoop.sh/) (on Windows. You must also have the [Extras bucket](https://github.com/ScoopInstaller/Extras) already installed for this). ```bash {} brew install platformsh/tap/upsun-cli ``` ```bash {} scoop bucket add platformsh https://github.com/platformsh/homebrew-tap.git scoop install upsun ``` **Note**: If you are using Scoop, you **must** have the [Extras bucket](https://github.com/ScoopInstaller/Extras) already installed before installing the Upsun CLI. ## 2. Authenticate To list and manage your projects, authenticate by running the following command: ```bash upsun ``` This process opens a browser tab for you to log in. It also creates certificates on your computer for [SSH](https://docs.upsun.com../../development/ssh.md). Once you are logged in, a list of your projects appears, along with some tips for getting started. If you experience authentication issues or want to force a login, run the command `upsun login`. ## 3. Use Now you can run actions on your projects such as branching and merging. You can also simulate a local build of your codebase as if you were pushing a change to Upsun, including your services and data. Get a list of all available commands with: ```bash upsun list ``` To get more information on a specific command, preface it with `help`: ```bash upsun help get ``` You get output similar to the following: ```bash Command: project:get Aliases: get Description: Clone a project locally Usage: upsun get [-e|--environment ENVIRONMENT] [--depth DEPTH] [--build] [-p|--project PROJECT] [--host HOST] [-i|--identity-file IDENTITY-FILE] [--] [] [] Arguments: project The project ID directory The directory to clone to. Defaults to the project title Options: -e, --environment=ENVIRONMENT The environment ID to clone. Defaults to the project default, or the first available environment --depth=DEPTH Create a shallow clone: limit the number of commits in the history --build Build the project after cloning -p, --project=PROJECT The project ID or URL --host=HOST The project's API hostname -i, --identity-file=IDENTITY-FILE An SSH identity (private key) to use -h, --help Display this help message -q, --quiet Do not output any message -V, --version Display this application version -y, --yes Answer "yes" to any yes/no questions; disable interaction -n, --no Answer "no" to any yes/no questions; disable interaction -v|vv|vvv, --verbose Increase the verbosity of messages Examples: Clone the project "abc123" into the directory "my-project": upsun get abc123 my-project ``` ### Select the right project and environment When you are in an empty directory or a directory not associated with a specific Upsun project, if you run a command that requires a specific project and environment, you are prompted to select them. For example, if you run the following command: ```bash upsun environment:info ``` You get the following output: ```bash Enter a number to choose a project: [0] My project (xb3pfo734qxbeg) [1] A great project (3p5fmol45kxp6) [2] An even better project (rjify4y564xaa) > ``` If your working directory is inside a local checkout of your project repository, your project and environment are detected automatically. You can always specify the project and environment in two ways: * As arguments for the command: ```bash upsun environment:info --project=my-project --environment=staging ``` * With environment variables: ```bash export PLATFORM_PROJECT=my-project; export PLATFORM_BRANCH=staging; upsun environment:info ``` In [multi-app](https://docs.upsun.com../../create-apps/multi-app.md) projects, this applies also to selecting the right app (the environment variable would be `PLATFORM_APPLICATION_NAME`). #### RootNotFoundException If you check out a project via Git directly and not using the `upsun get` command, the CLI may be unable to determine what project it's in. You might run a CLI command from within a project directory you've checked out and get an error like this: ```text {no-copy="true"} [RootNotFoundException] Project root not found. This can only be run from inside a project directory. ``` Then the CLI hasn't been able to determine the project to use. To fix this, run: ```bash upsun project:set-remote --project ``` Replace `` with the ID of your project. You can find that in the Console or by running `upsun projects` to list all accessible projects. ### Choose between the CLI and Git commands Some CLI commands (especially many within the `environment` namespace) have some overlap with Git commands. Generally, they offer more options than the Git commands alone. For example, `upsun push` offers options such as `--activate` (to activate an environment before pushing) and `--no-wait` (so you can continue working without waiting for the push to complete). For all of them, you don't need to configure a Git remote. It's enough to have a project ID. An example of how this affects commands is that when you run `upsun merge`, it doesn't affect your local codebase. You don't even need the code locally. The code is only merged between environments remotely. ### Customize the CLI You can customize how the CLI operates and what it returns with a configuration file (`~/.upsun-cli/config.yaml`) or environment variables. For details, see the [customization instructions on GitHub](https://github.com/platformsh/legacy-cli#user-content-customization). #### Automate repetitive tasks You might want to use the CLI in a script to automate repetitive tasks such as synchronizing your files locally. In such cases, you want to customize the CLI to bypass any confirmation questions. You can set the answer to every question as `yes` using the `UPSUN_CLI_NO_INTERACTION` environment variable. For instance, to locally sync every mount point for your app named `myapp`, you could use this command: ```bash export PLATFORM_PROJECT=my-project; export PLATFORM_BRANCH=main; export UPSUN_CLI_NO_INTERACTION=1; upsun mount:download --all --app app --target local-backup ``` ### Autocomplete commands The CLI provides tab autocompletion for commands, options, and some values (your projects, valid regions). To enable autocompletion, follow this step: Add the following to your shell’s startup (``.bashrc``, ``.zshrc``, or the equivalent): ```bash {} eval $(upsun completion) ``` ### Run commands on your container You can use the Upsun CLI to run commands on your container. You can use any command you've added in [dependencies](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#dependencies) or a [hook](https://docs.upsun.com/create-apps/image-properties/hooks.md). The syntax looks like the following: ```bash upsun ssh -- ``` For example, to run a specific Python script named `my-script.py` on your current environment, run the following command: ```bash upsun ssh -- python my-script.py ``` Or to use [Drush](https://www.drush.org/latest/install/) to rebuild the cache on the `feature` environment, run this command: ```bash upsun ssh -e feature -- drush -y cache-rebuild ``` ### Update the CLI To update to the latest version, use the same tool as for [installation](#1-install): ```bash {} $ scoop update upsun ``` ## Upgrade from the legacy CLI To upgrade from the legacy CLI, follow the [installation instructions](#1-install). Once you've installed the latest version, the CLI guides you through removing the installed legacy CLI. --- # Source: https://docs.upsun.com/domains/cdn/cloudflare.md # Set up your Cloudflare CDN You can [use a CDN](https://docs.upsun.com/domains/cdn.md) to deliver your site's content to users more quickly. ## Before you begin You need: - An up-and-running Upsun project - A [Cloudflare](https://www.cloudflare.com/) CDN subscription ## 1. Avoid double-caching To avoid stale content that can't be cleared, avoid using Cloudflare with [HTTP caching](https://docs.upsun.com/define-routes/cache.md). For routes where Cloudflare is used, disable HTTP caching using the following configuration: ```yaml {location=".upsun/config.yaml"} https://{default}/: type: upstream ... cache: enabled: false ``` ## 2. Set up your Cloudflare CDN To properly configure your Cloudflare CDN, see the Cloudflare official documentation on [how to get started](https://developers.cloudflare.com/cache/get-started/). Then set up a [custom domain](https://docs.upsun.com../steps.md). To get the [DNS challenge to succeed](https://docs.upsun.com../troubleshoot.md#ownership-verification), have your CDN point to your [project's target URL](https://docs.upsun.com../../domains/steps.md#1-get-the-target-for-your-project). ## 3. Handle apex domains To start routing client traffic through Cloudflare, you need to [create `CNAME` records for your domain names](https://docs.upsun.com../../domains/steps/dns.md) through your DNS provider. But `CNAME` records can't point to apex domains. As a workaround, Cloudflare offers [`HTTPS` records](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#svcb-and-https) and [`CNAME` flattening](https://developers.cloudflare.com/dns/additional-options/cname-flattening/). ## 4. Mitigate security risks Like all networks exposed to the internet, your origin server may become the target of security attacks. The best way to protect your site from threats like on-path attacks, spoofing attacks, or credential stuffing, is to configure mutual TLS (mTLS). [mTLS](https://www.cloudflare.com/en-gb/learning/access-management/what-is-mutual-tls/) not only has both parties in a connection authenticate each other through the TLS protocol. It also ensures that requests can't be sent directly to the origin server (Upsun). Instead, requests must transit through Cloudflare first. **Note**: mTLS is only compatible with environments where you have attached domains you own, meaning: - Your production environment - Each preview environment where you have [attached a custom domain](https://docs.upsun.com/domains/steps/custom-domains-preview-environments.md) Therefore, mTLS is **not** compatible with preview environments created by a [source code integration](https://docs.upsun.com/integrations/source.md). If you can't use mTLS, you can still take the following measures to protect your site from on-path attacks: 1. [Enable full strict SSL/TLS encryption](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/). Any communication between a client and Cloudflare or between Cloudflare and your Upsun server is then encrypted through HTTPS. In addition, Cloudflare checks that your Upsun server's [TLS certificate](https://docs.upsun.com/glossary.md#transport-layer-security-tls) was issued by a trusted certificate authority. This confirms the client is truly communicating with your Upsun server. 2. [Enable HTTP strict transport security (HSTS)](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/http-strict-transport-security/). This ensures that your HTTPS connections can't be downgraded to HTTP. --- # Source: https://docs.upsun.com/create-apps/app-reference/composable-image.md # Composable image The Upsun composable image provides enhanced flexibility when defining your app. It enables you to install several runtimes and tools in your application container, in a **"one image to rule them all"** approach. The composable image is built on [Nix](https://nix.dev), which offers the following benefits: - You can add as many packages to your application container as you need, choosing from over 120,000 packages from [the Nixpkgs collection](https://search.nixos.org/packages). - The packages you add are built in isolation, enabling you to install different versions of the same package. - With [Nix](https://nix.dev/reference/glossary#term-Nix), there are no undeclared dependencies in your source code. What works on your local machine is guaranteed to work on any other machine. This page introduces all the settings available to configure your composable image from your `.upsun/config.yaml` file (usually located at the root of your Git repository). Note that multi-app projects can be [set in various ways](https://docs.upsun.com../multi-app.md). You can also skip directly to this [comprehensive example](https://docs.upsun.com/create-apps.md#comprehensive-example) of a composable image configuration in the "Configure apps" topic. This example includes all of the primary application properties listed in the table in the next section. ## Primary application properties {#primary-application-properties} In the `.upsun/config.yaml` file, configure each application as a unique key beneath the top-level `applications` key. In a composable image, you can add multiple runtimes to a single application container by defining them in the [`.applications..stack`](https://docs.upsun.com/create-apps/app-reference/composable-image.md#example-stack-configuration) key, described later in this topic. The following table presents all of the properties available to each unique application. The **Set in instance** column defines whether the given property can be overridden within a `web` or `workers` instance. To override any part of a property, you must provide the entire property. **Note**: - The ``type`` and ``stack`` properties are unique to the composable image type and are described later in this topic. All other properties are available in both single-runtime and composable images — click a property name to view its details in a separate topic. - The ``stack`` key replaces the ``build``, ``dependencies``, and ``runtime`` keys that are available in the [single-runtime image](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md). | Name | Type | Required | Set in instance? | Description | |----------------------|------------------------------------------------------------------------------------------|----------|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | [`type`](#type) | A type | Yes | No | [Defines the version of the Nix channel](#supported-nix-channels). Mandatory in each application that uses the composable image. Example: `type: "composable:25.11"`. | | [`stack`](#stack) | `runtimes` and/or `packages` arrays | Yes | No | Specifies [Upsun-supported `runtimes`](#supported-nix-packages) and extra [Nixpkgs `packages`](https://search.nixos.org/packages) beyond those in the `type` channel. | | [`container_profile`](https://docs.upsun.com/create-apps/image-properties/container_profile.md) | A container profile | | Yes | Determines which combinations of CPU and RAM an app or service container can use. Default value is `HIGH_CPU`; see [Resources](#resources) if using multiple runtimes. | | [`relationships`](https://docs.upsun.com/create-apps/image-properties/relationships.md) | A dictionary of relationships | | Yes | Connections to other services and apps. | | [`mounts`](https://docs.upsun.com/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 `upsun resources:set`. | |[`web`](https://docs.upsun.com/create-apps/image-properties/web.md) | A web instance | | N/A | How the web application is served. | | [`workers`](https://docs.upsun.com/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](https://docs.upsun.com../timezone.md). | | [`access`](https://docs.upsun.com/create-apps/image-properties/access.md) | An access dictionary | | Yes | Access control for roles accessing app environments. | | [`variables`](https://docs.upsun.com/create-apps/image-properties/variables.md) | A variables dictionary | | Yes | Variables to control the environment. | | [`firewall`](https://docs.upsun.com/create-apps/image-properties/firewall.md) | A firewall dictionary | | Yes | Outbound firewall rules for the application. | | [`hooks`](https://docs.upsun.com/create-apps/image-properties/hooks.md) | A hooks dictionary | | No | Specifies commands and/or scripts to run in the `build`, `deploy`, and `post_deploy` phases. | | [`crons`](https://docs.upsun.com/create-apps/image-properties/crons.md) | A cron dictionary | | No | Scheduled tasks for the app. | | [`source`](https://docs.upsun.com/create-apps/image-properties/source.md) | A source dictionary | | No | Details about the app’s source code and available operations. | | [`additional_hosts`](https://docs.upsun.com/create-apps/image-properties/additional_hosts.md) | An additional hosts dictionary | | Yes | Mappings of hostnames to IP addresses. | | [`operations`](https://docs.upsun.com/create-apps/runtime-operations.md) | A dictionary of runtime operations | | No | Runtime operations for the application. | ## `type` {#type} Required for all applications that use the composable image. Defines the version of the Nix channel that application uses. For example, to specify the Nix channel `25.11` for ``, use the following syntax: ```yaml {location=".upsun/config.yaml"} applications: : type: "composable:25.11" ``` ### Supported Nix channels Upsun supports the following Nix channel versions: - `25.11` View the list of [supported Nix runtimes](#supported-nix-packages) in the `stack` section below. ## `stack` {#stack} You must define the `stack` element by using distinct `runtimes` and `packages` keys, as described in the following table. See the [example `stack` configuration](#example-stack-configuration) that follows this table. | Name | Type | Required | Additional keys | Description | |-----------------|---------------------|------------------| ----------|-------------------------------------------------------------------| | `runtimes` | array | No | `extensions`, `disabled_extensions`, and related subkeys | An array of 1+ language runtimes specified as `""` or ``.
The first declared runtime (or _[primary runtime](#multiple-runtimes-primary-runtime)_) is started automatically.
See the complete list of [supported runtimes](#supported-nix-packages) below. | | `packages` | array | No | `package`, `channel`, additional keys to demonstrate passthrough flexibility | Additional Nix tools/libraries, using the channel from `type` unless overridden locally by specifying the `package` and its `channel`. Format: `` | **Runtimes extensions or packages?**: Be sure you understand where to specify a runtime’s additional components. For example: - **PHP**: Manage extensions by using the ``stack.runtimes.extensions`` and ``stack.runtimes.disabled_extensions`` keys. - Note: In some scenarios, you might [add PHP settings](https://docs.upsun.com/languages/php.md#customize-php-settings) via environment variables or ``php.ini``. - **Python**: Install extra packages via the ``stack.packages`` key. See the [example ](#example-stack-configuration) below. For other runtimes, see the [Languages](https://docs.upsun.com/languages.md) section. ### Example: `stack` configuration {#example-stack-configuration} The `config.yaml` file excerpt below shows the following `stack` configuration: - **Primary runtime:** `php@8.4` with additional extensions and one disabled extension - **Secondary runtimes:** `nodejs@24` and `python@3.14` - **Nix packages:** - `yarn` and `python313Packages.yq` from the channel defined in `type` - `python313Packages.jupyterlab` (with config) and `wkhtmltopdf` from the `unstable` channel ```yaml {location=".upsun/config.yaml"} applications: : type: "composable:25.11" stack: runtimes: - "php@8.4": extensions: - apcu - pdo_sqlite - facedetect - sodium - xsl - name: blackfire # php@8.4 extension configuration: # extension subkeys server_id: server_token: disabled_extensions: - gd - "nodejs@24" - "python@3.14" packages: - yarn # Package manager - python313Packages.yq # Python package - package: python313Packages.jupyterlab channel: unstable - package: wkhtmltopdf # Conversion tool channel: unstable ``` **Warning**: Although ``nix`` commands are available during the build phase, they are not supported at runtime because the final image is read-only. When you use the Upsun composable image, you don’t need ``nix`` commands. Anything you declare under the ``stack`` key is automatically installed and the binaries are included in your ``$PATH``, making them immediately available to use. For example, to [start a secondary runtime](#multiple-runtimes-primary-runtime), you can run it directly in your [start](https://docs.upsun.com/create-apps/image-properties/web.md#web-commands) without using ``nix run``. ### Working with multiple runtimes: primary runtime {#multiple-runtimes-primary-runtime} 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 (or _secondary_ runtimes), you need to start them manually by using [web commands](https://docs.upsun.com/create-apps/image-properties/web.md#web-commands). To find out which start command to use, go to the [Languages](https://docs.upsun.com/languages.md) section and visit the documentation page dedicated to your runtime. Containers that define multiple runtimes typically require some resource sizing adjustments. For details, see the [Resources](#resources) section of this topic. See the [`stack` configuration example](#example-stack-configuration) above, which declares multiple runtimes. ### PHP as a primary runtime {#php-as-a-primary-runtime} If a PHP runtime is the first declared (or _primary_) runtime in the app: - The PHP-FPM service starts automatically. - You can configure the PHP-FPMP service by using `request_terminate_timeout` and `sizing_hints` keys in the app's `stack.runtimes` key. The [`stack` configuration example](#example-stack-configuration) above declares PHP as a primary runtime but does not show these additional keys. For the complete list of PHP extension keys and PHP-FPM sizing hints, see [Modify your PHP runtime when using the composable image](https://docs.upsun.com/languages/php.md#modify-your-php-runtime-when-using-the-composable-image) section in the "PHP" topic. Related resource: [When php-fpm runs out of workers: a 502 error field guide](https://devcenter.upsun.com/posts/when-php-fpm-runs-out-of-workers-a-502-error-field-guide/) (Dev Center article) ### Upsun-supported Nix runtimes {#supported-nix-packages} **Note**: Upsun officially supports the Nix runtimes listed below. To use them in your container, add them to the ``stack.runtimes`` array. Runtimes **not** listed below are supported only by Nix as Nixpkgs packages, not as Upsun runtimes. In those cases, add them to ``stack.packages``. For example, if your app requires the [FrankenPHP](https://search.nixos.org/packages?channel=unstable&show=frankenphp&from=0&size=50&sort=relevance&type=packages&query=frankenphp) runtime from the ``unstable`` channel, you would add ``frankenphp`` to ``stack.packages``. See the [stack](#example-stack-configuration) above for a similar addition. For some runtimes (such as Clojure), you can specify only a major version. For other runtimes (such as Elixir), you can specify a major or a major.minor version. Security and other patches are applied automatically. | **Language** | **Nix package** | **Supported version(s)** | |----------------------------------------------|-----------------|-------------------------------------------------| | [Clojure](https://clojure.org/) | `clojure` | 1 | | [Elixir](https://docs.upsun.com/languages/elixir.md) | `elixir` | 1.191.181.17 | | [Go](https://docs.upsun.com/languages/go.md) | `golang` | 1.251.24 | | [Java](https://docs.upsun.com/languages/java.md) | `java` | 25 | | [Javascript/Bun](https://bun.sh/) | `bun` | 1 | | [JavaScript/Node.js](https://docs.upsun.com/languages/nodejs.md) | `nodejs` | 242220 | | [Perl](https://www.perl.org/) | `perl` | 5 | | [PHP](https://docs.upsun.com/languages/php.md) | `php` | 8.48.38.2 | | [Python](https://docs.upsun.com/languages/python.md) | `python` | 3.133.123.11 | | [Ruby](https://docs.upsun.com/languages/ruby.md) | `ruby` | 3.43.3 | ### PHP extensions and Python packages {#php-extensions-and-python-packages} To discover which PHP extensions and Python packages are available for these runtimes: 1. Go to the [NixOS search](https://search.nixos.org/). 1. Enter a runtime and click **Search**. 1. In the **Package sets** side bar, select the right set of extensions/packages for your runtime version. You can choose the desired extensions/packages from the filtered results. ![Screenshot of the Nix package sets selection for PHP@8.3](https://docs.upsun.com/images/nixos/nixos-packages.png "0.5") **Note: PHP extension names**: To help you find PHP extension names, some maintainers provide a ``PHP upstream extension`` value in the [NixOS search engine](https://search.nixos.org/packages?channel=unstable&show=php82Extensions.gd). ![Screenshot of an upstream extension value shown in the NixOS search](https://docs.upsun.com/images/nixos/nixossearch-upstream-value.png) If this information is not provided, copy the ```` extension name from the appropriate ``Extensions.`` search result and add it to ``stack.runtimes.extensions`` as shown in the [stack](#example-stack-configuration) above. 4. Add extensions to `stack.runtimes.extensions` and packages to `stack.packages` as described in the [`stack`](#stack) section above. ## Resources (CPU, memory, disk space) {#resources} By default, Upsun assigns a container profile and container size to each application and service on the first deployment of a project. The container _profile_ defines and enforces a specific CPU-to-memory ratio. The default container profile for an app or service in a composable image is ``HIGH_CPU``. Use the Upsun CLI or Console to manually adjust the allocated container _size_ (CPU and memory resources)—that is, to perform a **vertical‑scaling** action. When you redeploy, the container runs with the CPU‑to‑memory ratio defined by its profile, so it enforces the size you specified. If you define **multiple runtimes** in an application's `.applications..stack.runtimes` key, you need to do one of the following: - Change the [`.applications..container_profile`](https://docs.upsun.com/create-apps/image-properties/container_profile.md) to a profile that uses a larger container size. - Change the [resource initialization policy](https://docs.upsun.com/manage-resources/resource-init.md) (the default CPU and RAM ratio) by running this command: ```bash upsun push --resources-init=manual ``` Related topics: - For detailed steps for changing the container size, see the [Vertical scaling](https://docs.upsun.com/manage-resources/adjust-resources.md#vertical-scaling) section of the "Resource configuration topic. - For details about container sizes for each resource allocation strategy (shared CPU, guaranteed CPU, and initial allocation), see the [Advanced: Container profiles](https://docs.upsun.com/manage-resources/adjust-resources.md#advanced-container-profiles) section of the "Resource configuration" topic. - To learn more about general resource management in Upsun, see the topics in the [Manage resources](https://docs.upsun.com/manage-resources.md) section. ### Downsize a disk You can reduce the target disk size of an app. Keep in mind: - Backups created before the downsize are incompatible and cannot be used; you must [create new backups](https://docs.upsun.com/environments/backup.md). - The downsize will fail if the disk contains more data than the target size. ## Combine single-runtime and composable images {#combine-single-runtime-and-composable-images} In a [multiple application context](https://docs.upsun.com/create-apps/multi-app.md), you can use a mix of [single-runtime images](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md) and composable images. The following sample configuration includes two applications: - ``frontend`` – uses a single-runtime image - ``backend`` – uses a composable image In this app, PHP is the primary runtime and is started automatically (PHP-FPM also starts automatically when PHP is the primary runtime). For details, see the [PHP as a primary runtime](#php-as-a-primary-runtime) section in this topic. ```yaml {location=".upsun/config.yaml"} applications: frontend: # this app uses the single-runtime image with a specific node.js runtime type: 'nodejs:24' backend: # this app uses the composable image and specifies two runtimes type: "composable:25.11" stack: runtimes: - "php@8.4": extensions: - apcu - sodium - xsl - pdo_sqlite - "python@3.13" packages: - "python313Packages.yq" # python package specific ``` --- # Source: https://docs.upsun.com/languages/php/composer-auth.md # Authenticated Composer repositories p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. [Packagist](https://packagist.org/) is the primary Composer repository for public PHP packages. But you can also have Composer download PHP packages from a private, third-party Composer repository. To make sure Composer has the necessary credentials to do so, follow the instructions on this page. ## Before you begin You need: - An Upsun project using [PHP](https://docs.upsun.com../php.md) and Composer - Credentials to access a private third-party Composer repository - The [Upsun CLI](https://docs.upsun.com../../administration/cli.md) ## 1. Declare a private Composer repository To allow Composer to download packages from a private third-party repository, declare the repository in your Composer setup. ```json {location="composer.json"} { "repositories": [ { "type": "composer", "url": "https://" } ] } ``` ## 2. Set up Composer authentication using a variable To allow Composer to successfully authenticate when accessing the declared private repository, set an [`env:COMPOSER_AUTH` variable](https://docs.upsun.com../../development/variables.md) for your project. To do so, run the following command: ```bash upsun variable:create --level project --name env:COMPOSER_AUTH \ --json true --visible-runtime false --sensitive true --visible-build true \ --value '{"http-basic": {"": {"username": "", "password": ""}}}' ``` The [`env:` prefix](https://docs.upsun.com../../development/variables.md#top-level-environment-variables) means that the variable is exposed as its own Unix environment variable. The `--visible-runtime false` and `--visible-build true` flags mean the variable is available to Composer only during the build. ## 3. Clear your project's build cache For security reasons, make sure that the authentication credentials aren't cached in your project's build container. To do so, run the following command: ```bash upsun project:clear-build-cache ``` ## Access dependencies downloaded from a private repository When you download a dependency from a private third-party Composer repository, that dependency is usually hosted in a [private Git repository](https://docs.upsun.com../../development/private-repository.md). Access to private Git repositories is restricted through the use of SSH keys. But most private Composer tools mirror tagged releases of dependencies and serve them directly without hitting the Git repository. To avoid having to authenticate against a remote Git repository, make sure your dependencies specify tagged releases. --- # Source: https://docs.upsun.com/administration/web/configure-environment.md # Configure environments From your project's main page in the Console, you can see all your environments as a list or a project tree: ![List of all environments as a tree](https://docs.upsun.com/images/management-console/environments.png "0.5") In this overview, the names of inactive environments are lighter. Selecting an environment allows you to see details about it, such as its [activity feed](#activity-feed), [services](#service-information), [metrics](https://docs.upsun.com../../increase-observability/metrics.md), and [backups](https://docs.upsun.com../../environments/backup.md). ## Activity Feed When you access an environment in the Console, you can see its [activity feed](https://docs.upsun.com../../increase-observability/logs/access-logs.md#activity-logs). This allows you to check which activities have happened or are currently happening on the selected environment: ![Environment activity list](https://docs.upsun.com/images/management-console/activity.png "0.5") You can filter activities by type (such as merge, sync, or redeploy). ## Actions on environments Each environment offers ways to keep environments up to date with one another: * [Branch **Branch**](https://docs.upsun.com/glossary.md#branch) to create a new child environment. * [Merge **Merge**](https://docs.upsun.com/glossary.md#merge) to copy the current environment into its parent. * [ **Sync**](https://docs.upsun.com/glossary.md#sync) to copy changes from its parent environment into the current environment. There are also additional options: * Settings **Settings** to [configure the environment](#environment-settings). * More **More** to get more options. * **URLs** to access the deployed environment from the web. * **SSH** to access your project using SSH. * **Code** * **CLI** for the command to get your project set up locally with the [Upsun CLI](https://docs.upsun.com../cli.md). * **Git** for the command to clone the codebase via Git. If you're using Upsun as your primary remote repository, the command clones from the project. If you have set up an [external integration](https://docs.upsun.com../../integrations/source.md), the command clones directly from the integrated remote repository. If the project uses an external integration to a repository that you haven't been given access to, you can't clone until your access has been updated. See how to [troubleshoot source integrations](https://docs.upsun.com../../integrations/source/troubleshoot.md). ## Environment URL When you access an environment in the Console, you can view its URL. While the environment is loading in the Console, a `Waiting for URL...` message is displayed instead of the URL. If this message isn't updated once your [default environment](https://docs.upsun.com../../environments/_index.md#default-environment)'s information is loaded, follow these steps: 1. Check that [you have defined routes](https://docs.upsun.com../../define-routes.md) for your default environment. 2. Verify that your [application](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md), [services](https://docs.upsun.com../../add-services.md), and [routes](https://docs.upsun.com../../define-routes.md) configurations are correct. 3. Check that your default environment is [active](https://docs.upsun.com../../environments/deactivate-environment.md#reactivate-an-environment). ## Environment settings To access the settings of an environment, click Settings **Settings** within that environment. ![Settings for an environment](https://docs.upsun.com/images/management-console/env-settings.png "0.75") ### Environment name Under **Environment name**, you can edit the name and type of your environment and view its parent environment: ![Environment status](https://docs.upsun.com/images/management-console/env-name.png "0.5") ### Status Under **Status**, you can check whether or not your environment is [active](https://docs.upsun.com/glossary.md#active-environment). ![Environment status](https://docs.upsun.com/images/management-console/env-status.png "0.5") For preview environments, you can [change their status](https://docs.upsun.com../../environments/deactivate-environment.md). ### Outgoing emails Under **Outgoing emails**, you can allow your environment to [send emails](https://docs.upsun.com../../development/email.md): ![Environment email](https://docs.upsun.com/images/management-console/env-email.png "0.75") ### Hide from search engines Under **Hide from search engines**, you can tell [search engines to ignore the site](https://docs.upsun.com../../environments/search-engine-visibility.md): ![Environment search](https://docs.upsun.com/images/management-console/env-search.png "0.5") ### HTTP access control Under **HTTP access control**, you can [control access to your environment using HTTP methods](https://docs.upsun.com../../environments/http-access-control.md): ![Settings control access with password and by IP](https://docs.upsun.com/images/management-console/settings-basics-access-control.png "0.5") ### Variables Under **Variables**, you can define [environment variables](https://docs.upsun.com../../development/variables/_index.md): ![Configure Upsun environment variables](https://docs.upsun.com/images/management-console/settings-variables-environment.png "0.6") ## Service information For each environment, you can view information about how your routes, services, and apps are currently configured. To do so, click **Services**. By default, you see configured routes. ### Routes The **Router** section shows a list of all the [routes configured on your environment](https://docs.upsun.com../../define-routes.md). You can see each route's type and check if caching and server side includes have been enabled for it. To view the configuration file where your routes are set up, click **Configuration**. ### Applications To see detailed information about an app container, select it in the tree or list on the left-hand side: ![Services: app overview](https://docs.upsun.com/images/management-console/service-tab/app-overview.png "0.5") The **Overview** tab gives you information about your app. You can see: * The language version, the container size, the amount of persistent disk, the number of cron jobs, and the command to SSH into the container. * A summary of [metrics for the environment](https://docs.upsun.com../../increase-observability/metrics.md). * All cron jobs with their name, frequency, and command. * All workers with their name, size, amount of persistent disk, and command to SSH into the container. To view [the configuration file where your app is set up](https://docs.upsun.com../../create-apps/), click **Configuration**. ### Services To see detailed information about a [running service](https://docs.upsun.com../../add-services.md), select it in the tree or list on the left-hand side: ![Services: service overview](https://docs.upsun.com/images/management-console/service-tab/service-overview.png "0.5") The **Overview** gives you information about the selected service. You can see the service version, the container size, and the disk size, if you've configured a persistent disk. You can also see a summary of [metrics for the environment](https://docs.upsun.com../../increase-observability/metrics.md). To view the configuration file where your services are set up, click **Configuration**. --- # Source: https://docs.upsun.com/administration/web/configure-project.md # Configure a project Each project has settings that apply to everything within that project, including all its environments. You can only see and update settings for projects where you are a [Project Admin](https://docs.upsun.com../users.md). To access the settings, click Settings **Settings** from the main project page. The settings are divided into several sections. ## General The **General** section shows you the project's region and allows you to update the project name and [timezone](https://docs.upsun.com../../projects/change-project-timezone.md). ![configure project](https://docs.upsun.com/images/console/settings-general.png "1.0") ## Access The **Access** section allows you to [manage user access to the project](https://docs.upsun.com../users.md). ![Project configure icon](https://docs.upsun.com/images/console/settings-access-users.png "0.7") ## Certificates The **Certificates** section shows a list of your project's TLS certificates. To see details about a certificate or delete one, click **Edit **. See how to [add custom certificates](https://docs.upsun.com../../domains/steps/tls.md). ![A list of certificates in a project](https://docs.upsun.com/images/management-console/settings-certificates.png "0.7") ## Domains The **Domains** section allows you to manage the domains where your project is accessible. See how to [set up your domain](https://docs.upsun.com../../domains/steps.md). ![project domain](https://docs.upsun.com/images/management-console/settings-domains.png "0.7") ## Deploy Key The **Deploy Key** section shows you the public SSH key you can add to your private repositories. Adding it lets Upsun access the repositories during the build process. This is useful if you want to reuse some code components across multiple projects and manage those components as dependencies of your project. ![Project deploy key](https://docs.upsun.com/images/management-console/settings-deploy-key.png "0.7") ## Integrations The **Integrations** section allows you to manage all of your [integrations](https://docs.upsun.com../../integrations.md). ![Integrations](https://docs.upsun.com/images/management-console/settings-integrations.png "0.7") ## Variables The **Variables** section allows you to manage all project-wide [variables](https://docs.upsun.com../../development/variables.md). ![Project variables](https://docs.upsun.com/images/management-console/settings-variables-project.png "0.7") --- # Source: https://docs.upsun.com/create-apps.md # Configure apps Control your apps and how they’re built and deployed on Upsun with YAML configuration. Within a single project, you can have one or more apps and each app can have multiple instances. Instances are where the same code can be run with different configurations, such as one for external communication and one for background processes. Apps and instances use similar properties, with minor differences depending on the image type that you choose: - [Single-runtime image](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md) - [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) Not sure which image type to use? See [choosing an image type](https://docs.upsun.com/create-apps/app-reference.md). ## A minimal application To create a very basic app (for this example, using a single-runtime image), you need a few things: * A unique name not shared by any other app in the project. * The runtime `type` defining what language it uses. * A definition of how to handle requests from the outside `web`. The following example shows such a basic setup for Node.js: ```yaml {location=".upsun/config.yaml"} # Top-level key, which contains configurations for all app containers. applications: # The app's name, which must be unique within the project. myapp: # The language and version for your app. type: 'nodejs:24' # The app's configuration when it's exposed to the web. web: commands: start: npm start locations: '/': # The public directory relative to the app root. root: 'public' # Forward resources to the app. passthru: true # What files to use when serving a directory. index: ["index.html"] # Allow files even without specified rules. allow: true ``` ## Use multiple apps You might have multiple apps you want to run from a single Git repository, such as a RESTful web service and a front-end or a main website and a blog. In such cases, you configure each app separately and define the relationships among them. See the various ways to set up a [multi-app project](https://docs.upsun.com/create-apps/multi-app.md). ## Connect to services If you want to use one of the [databases or other services Upsun provides](https://docs.upsun.com../add-services.md), set it up by following these steps: 1. Configure the service based on the documentation for that service. 1. Use the information from that service inside your app's [`relationships` definition](https://docs.upsun.com/create-apps/image-properties/relationships.md) to configure how your app communicates with the service. ## Control the build and deploy process Your app generally needs to undergo some steps to be turned from the code in your Git repository into a running app. If you're running a PHP or Node.js app, this starts with the [build flavor](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#build), which runs a default set of tasks. Then any [global dependencies](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#dependencies) can be installed. Once these optional tasks are done, you can run [hooks](https://docs.upsun.com/create-apps/hooks.md) at various points in the process. Hooks are places for your custom scripts to control how your app is built and deployed. ## Configure what's served Once your app is built, it needs a defined way to communicate with the outside world. Define its behavior with a [`web` instance](https://docs.upsun.com/create-apps/image-properties/web.md). There you can set what command runs every time your app is restarted, how dynamic requests are handled, and how to respond with static files. ## Response compression Response compression reduces payload sizes and generally increases your app's response times. Dynamic responses generated by your app aren't compressed because of a [general security issue](https://en.wikipedia.org/wiki/BREACH). While your app can compress its own response, doing so when the response includes any user-specific information, including a session cookie, opens up an attack vector over SSL/TLS connections. For that reason, you generally shouldn't compress generated responses. Requests for static files that are served directly by Upsun are compressed automatically using either gzip or Brotli compression if: * The request headers for the file support gzip or Brotli compression. * The file is served directly from disk by Upsun and not passed through your application. * The file would be served with a cache expiration time in the future. * The file type is one of: HTML, JavaScript, JSON, PDF, PostScript, SVG, CSS, CSV, plain text, or XML. Also, if there is a request for a file and another file exists with the same name plus a `.gz` or `.br` extension, the compressed file is served regardless of the original file type. So a request for `styles.css` that accepts a gzipped file (according to the request headers) automatically returns a `styles.css.gz` file if it exists. This approach supports any file type and offers some CPU optimization, especially if the cache lifetime is short. ## Comprehensive example **PHP specifics**: Unlike other runtimes, most PHP applications do not have a start command. There is a daemon running configured to work automatically with the web server. More often than not there will be a single entry-point a “front-controller”. In the case of PHP the ``passthru`` property is a string with the location of the front-controller rather than a boolean. The following example shows a setup for a PHP app with comments to explain the settings. ```yaml {} applications: # The app's name, which must be unique within the project. myapp: # The language and version for your app. type: 'php:8.5' # Global dependencies to be added and cached and then available as commands. dependencies: php: composer/composer: '^2' # Relationships enable an app container's access to a service or another app. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mysql: # Scripts that are run as part of the build and deploy process. hooks: # Build hooks can modify app files on disk but not access any services like databases. build: ./build.sh # Deploy hooks can access services but the file system is now read-only. deploy: ./deploy.sh # Post deploy hooks run when the app is accepting outside requests. post_deploy: ./post_deploy.sh # Define writable, persistent filesystem mounts. # The key is the directory path relative to the application root. # In this case, `web-files` is just a unique name for the mount. mounts: 'web/files': source: storage source_path: 'web-files' # The app's configuration when it's exposed to the web. web: locations: '/': # The app's public directory relative to its root. root: 'public' # A front controller to determine how to handle requests. passthru: '/app.php' # Allow uploaded files to be served, but don't run scripts. # Missing files get sent to the front controller. '/files': root: 'web/files' scripts: false allow: true passthru: '/app.php' services: mysql: type: mariadb:11.8 ``` .upsun/config.yaml ```yaml {} applications: # The app's name, which must be unique within the project. : # The list of packages you want installed (from the Upsun collection # of supported runtimes and/or from Nixpkgs). # For more information, see the Composable image page in the App reference section. type: "composable:25.11" stack: runtimes: - "php@8.4": # The list of PHP extensions you want installed. extensions: - apcu - ctype - iconv - mbstring - pdo_pgsql - sodium - xsl disabled_extensions: - gd - "nodejs@24" packages: - yarn - imagemagick - package: wkhtmltopdf channel: unstable # Relationships enable an app container's access to a service or another app. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mysql: # Scripts that are run as part of the build and deploy process. hooks: # Build hooks can modify app files on disk but not access any services like databases. build: ./build.sh # Deploy hooks can access services but the file system is now read-only. deploy: ./deploy.sh # Post deploy hooks run when the app is accepting outside requests. post_deploy: ./post_deploy.sh # Define writable, persistent filesystem mounts. # The key is the directory path relative to the application root. # In this case, `web-files` is just a unique name for the mount. mounts: 'web/files': source: storage source_path: 'web-files' # The app's configuration when it's exposed to the web. web: locations: '/': # The app's public directory relative to its root. root: 'public' # A front controller to determine how to handle requests. passthru: '/app.php' # Allow uploaded files to be served, but don't run scripts. # Missing files get sent to the front controller. '/files': root: 'web/files' scripts: false allow: true passthru: '/app.php' services: mysql: type: mariadb:11.8 ``` --- # Source: https://docs.upsun.com/create-apps/image-properties/crons.md # crons A cron dictionary that defines scheduled tasks for the app. Optional in [single-runtime](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](https://docs.upsun.com/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](https://docs.upsun.com/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](https://docs.upsun.com/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 {} applications: : type: 'nodejs:24' source: root: "/" crons: mycommand: spec: 'H * * * *' commands: start: sleep 60 && echo sleep-60-finished && date stop: killall sleep shutdown_timeout: 18 ``` .upsun/config.yaml ```yaml {} applications: : type: "composable:25.11" stack: runtimes: [ 'nodejs:24' ] source: root: "/" 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` key uses the `H` syntax. ### Single-runtime image: Example cron jobs ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'php:8.5' 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' ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'ruby:4.0' crons: # Execute a rake script every 19 minutes. ruby: spec: '*/19 * * * *' commands: start: 'bundle exec rake some:task' ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'php:8.5' crons: # Run Laravel's scheduler every 5 minutes. scheduler: spec: '*/5 * * * *' commands: start: 'php artisan schedule:run' ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'php:8.5' 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 ``` ### Composable image: Example cron jobs ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: "composable:25.11" stack: runtimes: [ "php@8.4" ] 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' ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: "composable:25.11" stack: runtimes: [ "ruby@4.0" ] crons: # Execute a rake script every 19 minutes. ruby: spec: '*/19 * * * *' commands: start: 'bundle exec rake some:task' ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: "composable:25.11" stack: runtimes: [ "php@8.4" ] crons: # Run Laravel's scheduler every 5 minutes. scheduler: spec: '*/5 * * * *' commands: start: 'php artisan schedule:run' ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: "composable:25.11" stack: runtimes: [ "php@8.4" ] 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 ``` ### 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 {} applications: myapp: type: 'php:8.5' source: root: "/" crons: update: spec: '0 0 * * *' commands: start: | if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then upsun backup:create --yes --no-wait upsun source-operation:run update --no-wait --yes fi ``` .upsun/config.yaml ```yaml {} applications: myapp: type: "composable:25.11" source: root: "/" stack: runtimes: [ "php@8.4" ] crons: update: spec: '0 0 * * *' commands: start: | if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then upsun backup:create --yes --no-wait upsun 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](https://docs.upsun.com/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](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#primary-application-properties) or [composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md#primary-application-properties)). To run cron jobs in a timezone other than UTC, set the [timezone property](https://docs.upsun.com/create-apps/timezone.md). ### Paused crons [Preview environments](https://docs.upsun.com/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 `upsun 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: Run the following command: ```bash {} upsun redeploy ``` --- # Source: https://docs.upsun.com/domains/steps/custom-domains-preview-environments.md # Set up a custom domain on a preview environment [Preview environments](https://docs.upsun.com/glossary.md#preview-environment) in your project can't use the custom domain [set up on your production environment](https://docs.upsun.com../steps.md). By default and for each preview environment, Upsun automatically replaces the custom production domain with an automatically generated URL. If you don't want to use these default URLs, you can add a custom domain to each of your preview environments (`staging` or `development` [environment types](https://docs.upsun.com/glossary.md#environment-type)). To do so, no need to modify your [routes configuration](https://docs.upsun.com../../define-routes.md). When you add a new custom domain for a preview environment, just attach it to the custom production domain it replaces. If you have multiple custom production domains, you need to select which one you're replacing. **Example**: You have two environments, a production environment and a staging environment. You’ve added the ``example.com`` custom domain to your production environment. You want to add the ``staging.example.com`` custom domain to your staging environment. To do so, you need to attach the new ``staging.example.com`` custom domain to its corresponding custom production domain ``example.com``. You can then access your staging environment through ``staging.example.com``, and still access your production environment through ``example.com``. If you have multiple custom domains on your production environment, when you set up a custom domain on a preview environment, you don't need to update your [routes configuration](https://docs.upsun.com../../define-routes.md) either. Upsun automatically figures out the routing of your preview environment based on the following elements: - The custom production domains in your existing [routes configuration](https://docs.upsun.com../../define-routes.md) - The custom domains for preview environments attached to each of those custom production domains ## Before you start You need: - A production environment with at least one custom domain already set up - At least one preview (staging or development) environment - Optional: The [Upsun CLI](https://docs.upsun.com../../administration/cli.md) (v4.8.0+) To prevent abuse, by default you can add custom domains to up to 5 preview environments per project only. This limit doesn't include the production environment, and you can increase it without charge. To do so, [contact Support](https://docs.upsun.com/learn/overview/get-support.md). **Note**: If you delete a custom production domain, all of the attached custom domains for preview environments are deleted too. You need to rebuild the affected preview environments for the deletion to be complete. ## Add a custom domain to a preview environment To add a custom domain to a preview environment, follow these steps: - [Configure your DNS provider](https://docs.upsun.com/domains/steps.md#2-configure-your-dns-provider). In particular, make sure your DNS record points to the target of your preview environment. **Note**: Using the target of your production environment to configure your DNS provider is technically possible, but Upsun recommends using the target of your preview environment as a best practice. - Run a command similar to the following: ```bash {} upsun domain:add staging.example.com --environment --attach ``` - Get the target for your preview environment. To do so, navigate to your preview environment and click **Settings Settings**. Select the **Domains** tab. In the **Configure your domain** section, copy the content of the **CNAME record** field. Save it for later use at step 7. - Click **Add domain**. - Name the custom domain for your preview environment. - Attach the custom domain for your preview environment to the desired production custom domain. - Click **Add**. - Click **Okay**. - [Configure your DNS provider](https://docs.upsun.com/domains/steps.md#2-configure-your-dns-provider). In particular, make sure your DNS record points to the target of your preview environment. **Note**: Using the target of your production environment to configure your DNS provider is technically possible, but Upsun recommends using the target of your preview environment as a best practice. **Note**: You can’t update a custom domain when it’s used on a preview environment. You can only delete it and create a new one as a replacement. ### Example You've added the `mysite.com` custom domain to your production environment. You now want to add the `mydev.com` custom domain to a preview environment called `Dev`. To do so, follow these steps: - Get the target for ``Dev``. To do so, navigate to ``Dev`` and click **Settings Settings**. Select the **Domains** tab. In the **Configure your domain** section, copy the content of the **CNAME record** field. Save it for later use at step 7. - Click **Add domain**. - Enter ``mydev.com`` as a name for the custom domain you want to add to ``Dev``. - Select ``mysite.com`` as the production custom domain you want to attach ``mydev.com`` to. - Click **Add**. - Click **Okay**. - [Configure your DNS provider](https://docs.upsun.com/domains/steps.md#2-configure-your-dns-provider). In particular, make sure your DNS record points to ``Dev``’s target. In the above example, the `Dev` environment needs to exist for you to add the `mydev.com` custom domain successfully. If the `Dev` environment is later removed, the `mydev.com` custom domain is removed too. ## List the custom domains of a preview environment - Navigate to your preview environment and click **Settings Settings**. - Select the **Domains** tab. All the custom domains for your preview environment are displayed. ## Get a specific custom domain used on a preview environment - Navigate to your preview environment and click **Settings Settings**. - Select the **Domains** tab. All the custom domains for the selected environment are displayed. - To see which actions you can perform on a displayed custom domain, click **More More** next to it. ## Remove a custom domain from a preview environment - Navigate to your preview environment and click **Settings Settings**. - Select the **Domains** tab. All the custom domains for the selected environment are displayed. - Click **More More** on the custom domain you want to delete. - Click **Delete**. - Click **Yes, delete**. --- # Source: https://docs.upsun.com/create-apps/web/custom-headers.md # Set custom headers on static content When your app responds to dynamic requests, it can generate headers on the fly. To set headers for static content, add them in [your `web` configuration](https://docs.upsun.com/create-apps/image-properties/web.md). You might want to do so to add custom content-type headers, limit what other sites can embed your content, or allow cross origin requests. Say you want to limit most files to be embedded only on your site, but you want an exception for Markdown files. And you want to serve both Markdown and [AAC](https://en.wikipedia.org/wiki/Advanced_Audio_Coding) files with the correct content types to avoid [MIME sniffing](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#mime_sniffing). Start by defining a header for files in general: ```yaml {location=".upsun/config.yaml"} applications: myapp: # The type of the application to build. type: "nodejs:24" source: root: "/" web: locations: "/": ... # Apply rules to all static files (dynamic files get rules from your app) headers: X-Frame-Options: SAMEORIGIN ``` This sets the `X-Frame-Options` header to `SAMEORIGIN` for all static files. Now your files can only be embedded within your site. Now set up an exception for Markdown (`*.md`) using a [rule](https://docs.upsun.com/create-apps/image-properties/web.md#rules): ```yaml {location=".upsun/config.yaml"} applications: myapp: # The type of the application to build. type: "nodejs:24" source: root: "/" web: locations: "/": #... rules: \.md$: headers: Content-Type: "text/markdown; charset=UTF-8" ``` This rule sets an explicit content type for files that end in `.md`. Because specific rules override the general heading configuration, Markdown files don't get the `X-Frame-Options` header set before. **Setting charset**: By default, [HTTP charset parameters](https://www.w3.org/International/articles/http-charset/index.en) are not sent to the response. If not set, modern browsers will detect ``ISO-8859-1`` and likely default to ``windows-1252`` as this has 32 more international characters. To set the HTTP charset parameters to your desired charset, you can add ``; charset=UTF-8`` in the ``Content-Type`` parameters. Now set a rule for AAC files. ```yaml {location=".upsun/config.yaml"} applications: myapp: # The type of the application to build. type: "nodejs:24" source: root: "/" web: locations: "/": ... rules: \.aac$: headers: X-Frame-Options: SAMEORIGIN Content-Type: audio/aac ``` This rule sets an explicit content type for files that end in `.aac`. It repeats the rule for `X-Frame-Options` because the `headers` block here overrides the more general configuration. So now you have three header configurations: * `X-Frame-Options: SAMEORIGIN` **and** `Content-Type: audio/aac` for AAC files * Only `Content-Type: text/markdown` for Markdown files * Only `X-Frame-Options: SAMEORIGIN` for everything else ## Cross origin requests To allow cross origin requests, add a `Access-Control-Allow-Origin` header to responses. You can do so for specific origins or for all origins with a wildcard. ```yaml {location=".upsun/config.yaml"} applications: myapp: # The type of the application to build. type: "nodejs:24" source: root: "/" web: locations: "/": ... # Apply rules to all static files (dynamic files get rules from your app) headers: Access-Control-Allow-Origin: "*" ``` If you use the wildcard value, the headers are modified for each request in the following ways: * The value of the `Access-Control-Allow-Origin` header is set to the value of the `Origin` request header. * The `Vary` header is included with a value of `Origin`. See why in the [MDN web docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#access-control-allow-origin). This is done so that credentialed requests can be supported. They would otherwise fail CORS checks if the wildcard value is used. ## `Strict_Transport_Security` header The `Strict_Transport_Security` header returns a value of `max-age=0` unless you enable [HTTP Strict Transport Security (HSTS)](https://docs.platform.sh/define-routes/https.md#enable-http-strict-transport-security-hsts) in your [routes configuration](https://docs.upsun.com../../define-routes.md). Note that once HSTS is enabled, configuration capabilities depend on the [HSTS properties](https://docs.upsun.com/define-routes/https.md#enable-http-strict-transport-security-hsts) set in your routes configuration. For example, the `max-age` value is set to `31536000` by Upsun and can't be customized. --- # Source: https://docs.upsun.com/security/data-retention.md # Data retention Upsun logs and stores various types of data as a normal part of its business. This information is only retained as needed to perform relevant business functions. Retention periods vary depending on the type of data stored. If a legal obligation, law enforcement request, or ongoing business need so requires, data may be retained after the original purpose for which it was collected ceases to exist. ## Account information Information relating to customer accounts (login information, billing information, etc.) is retained for as long as the account is active with Upsun. Customers may request that their account be deleted and all related data be purged by opening a [support ticket](https://docs.upsun.com/learn/overview/get-support.md). ## System logs System level access and security logs are maintained by Upsun for diagnostic purposes. These logs aren't customer-accessible. These logs are retained for at least 6 months and at most 2 years depending upon legal and standards compliance required for each system. ## Application logs Application logs on each customer environment are retained with the environment. Individual log files are truncated at 100 MB, regardless of their age. See how to [access logs](https://docs.upsun.com../increase-observability/logs/access-logs.md). When an environment is deleted, its application logs are deleted as well. ## Backups The backups retention depends on the [automated backup policy](https://docs.upsun.com../environments/backup.md#automated-backups). ## Tombstone backups When a project is deleted, Upsun takes a final backup of active environments, as well as the Git repository holding user code. This final backup is to allow Upsun to recover a recently deleted project in case of accident. These "tombstone" backups are retained for between 7 days and 6 months depending upon legal and standards compliance required for each system. ## Analytics Upsun uses Google Analytics on various web pages, and so Google Analytics stores collected data for a period of time. We have configured our Google Analytics account to store data for 14 months from the time you last accessed our site, which is the minimum Google allows. ## Trials User data - which includes pushed code and data contained within services - is retained for a shorter period during trials. See [Trial details](https://docs.upsun.com/glossary.md#trial). --- # Source: https://docs.upsun.com/development/local/ddev.md # Use DDEV for local development [DDEV](https://ddev.readthedocs.io/en/stable/) is an open-source tool for local development environments. It allows you to use Docker in your workflows while maintaining a GitOps workflow. You get fully containerized environments to run everything locally without having to install tools (including the Upsun CLI, PHP, and Composer) on your machine. Please see the [Upsun Integration docs on DDEV Docs](https://ddev.readthedocs.io/en/stable/users/providers/upsun/). --- # Source: https://docs.upsun.com/environments/deactivate-environment.md # Deactivate an environment If you have environments you aren't using, you may want to deactivate them to save resources for what you need. To deactivate an environment, you need to be an admin for the project or the given environment. **Note**: Your default environment is protected. It can’t be deactivated through the Console or the CLI. To change which environment is the default, see how to [rename the default branch](https://docs.upsun.com/environments/default-environment.md). Deactivating the project results in the following: * The environment becomes [inactive](https://docs.upsun.com/glossary.md#inactive-environment). Unless it's reactivated, it's no longer deployed and isn't accessible from the web or via SSH. * All services running on this environment are deleted. * All data specific to the environment is deleted. If the environment is reactivated, it syncs data from its parent environment. ## Deactivate an environment To deactivate an environment, follow these steps: Run the following command: ```bash {} upsun environment:deactivate ``` ## Delete the branch Inactive environments still have branches in Git. To delete the branch entirely, run the following command: ```bash git push origin --delete ``` ## Reactivate an environment Reactivating an environment [syncs](https://docs.upsun.com/glossary.md#sync) data from its parent environment. To reactivate an inactive environment, follow these steps: Run the following command: ```bash {} upsun environment:activate ``` If you're not using a [source integration](https://docs.upsun.com/integrations/source.md), you can also activate an environment when pushing changes to it. To do so, run the following command: ```bash git push -o "environment.status=active" ``` Learn more about how to [trigger actions on `push`](https://docs.upsun.com/environments.md#push-options). --- # Source: https://docs.upsun.com/languages/nodejs/debug.md # Debugging p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. Effectively debugging web apps takes effort, especially when an HTTP request goes through multiple layers before reaching your web app. Follow the steps below to debug a specific app. You can choose to debug in an environment deployed to Upsun or with your app running locally but connected to deployed services. In either case, make sure to debug in a preview environment. For more general information, see how to [troubleshoot development](https://docs.upsun.com/development/troubleshoot.md). ## 1. Create a new environment Start by creating a new environment completely isolated from production but with the same data for debugging: ```bash upsun branch debug-branch ``` ## 2. Get access To access deployed apps and services, open tunnels to everything your app has relationships with: ```bash {} upsun tunnel:open ``` In the same terminal, set the relevant environment variables: ```bash {} export PLATFORM_RELATIONSHIPS="$(upsun tunnel:info --encode)" export PORT=8888 ``` ## 3. Run your app in inspect mode In the same terminal as the previous step, run the following command: ```bash {} node --inspect ``` Replace `` with the file defined for [your app's `start` command](https://docs.upsun.com/languages/nodejs.md#4-start-your-app). You get output something like this: ```bash Debugger listening on ws://127.0.0.1:9229/10701e5d-d627-4180-a967-d47a924c93c0 For help, see: https://nodejs.org/en/docs/inspector Listening on port 8888 ``` ## 4. (If debugging remotely) Forward the debugger port locally In another terminal, create an SSH tunnel that forwards to the 9229 port: ```bash ssh -N -L 9229:localhost:9229 $(upsun ssh --pipe) ``` ## 5. Connect the debugger You can now connect the debugger as if you were debugging a local application. See examples with some common tools: Use the ``Node.js: Attach`` debugger option. If you haven’t created the option: - On the **Run and Debug** tab, click ``create a launch.json file``. - Select ``Node.js`` as the environment. - In the ``configurations`` array, start IntelliSense (usually ctrl+space). - Select ``Node.js: Attach``. - Make sure the port is the same as in [step 4 above](#4-if-debugging-remotely-forward-the-debugger-port-locally). Once you have the option: In the **Run and Debug** tab, select ``Attach`` from the menu and click **Start Debugging** (the green arrow). See more on [Node.js debugging in Visual Studio Code](https://code.visualstudio.com/docs/nodejs/nodejs-debugging). Now when you load the site at your deployed URL (if debugging remote) or localhost (if debugging locally), the local debugger you've attached is called. Set breakpoints: Directly in your source files. ## Other issues ### pm2 process manager blocks other processes If you're using the [`pm2` process manager](https://github.com/unitech/pm2) to start your app from a script, you might find it daemonizes itself and blocks other processes (such as backups) by constantly respawning. This may happen even if you use the `--no-daemon` flag. Instead of using a script, call `pm2 start` directly in your [`start` command](https://docs.upsun.com/languages/nodejs.md#4-start-your-app). --- # Source: https://docs.upsun.com/environments/default-environment.md # Rename the default environment You can set the name of your default/production environment when creating a project. To change it after project creation, follow the steps below. For consistency, the steps are all given using the [CLI](https://docs.upsun.com../administration/cli.md). The examples below are based off of changing the default environment from `old` to `main`. Replace these names with what suits your situation. If your site is already live, remember that deactivating an environment is a destructive operation that can result in data loss. To minimize potential issues, take the following steps: - Switch the default environment during non-peak hours. - Keep your data by taking a [backup of the `old` environment](https://docs.upsun.com../environments/backup.md) - Reduce your DNS time-to-live (TTL) to a minimum. ## Requirements If you have a domain set for your default environment, remove it before changing the default branch. Otherwise you get an error that `default domain must be a valid project domain`. To change the default branch, you need to be an [admin for the project](https://docs.upsun.com../administration/users.md) ## Note on source integrations The following steps depend of whether your project has a [source integration](https://docs.upsun.com../integrations/source.md). If it doesn't, Upsun is your primary remote repository for the project. If it does, GitHub, GitLab, or BitBucket hosts your primary remote repository for the project. ## 1. Create a `main` environment
Without a source integration With a source integration In your local copy of your repository, create a new environment from ``old`` called ``main``: ```bash {} upsun environment:branch main old ``` In your local copy of the external repository, make sure your default branch is up to date: ```bash {} git checkout old && git pull origin old ``` Then create the ``main`` branch off of your default branch and push it to the remote repository: ```bash {} git checkout -b main git push origin main ``` Source integrations include all branches, but don’t activate the corresponding environments in Upsun. Activate the ``main`` environment by running the following command: ```bash {} upsun environment:activate main ``` ## 2. Copy settings If you have variables or other settings specific to your default environment, add those to the `main` environment. For example, you may have variables for your production environment set to not be inheritable (such as if you set them with `--inheritable=false` through the CLI). These variables aren't added automatically to child environments and so you need to add them to the `main` environment manually. If you want the `main` environment to send emails, [turn on outgoing email](https://docs.upsun.com../development/email.md). ## 3. Make `main` a top-level branch To have `main` be your default, it needs to not be a child of `old`. Use the following command to remove its parent and make it a top-level branch: ```bash upsun environment:info -e main parent - ``` ## 4. Make `main` the parent for other environments
Without a source integration With a source integration You probably have other environments that are children of ``old``. For each environment, update its parent to ``main``: ```bash {} upsun environment:info -e parent main ``` To preserve your data on Upsun, it’s best to switch your work in progress to be based off of ``main``. Close any open pull/merge requests and resubmit them against ``main``. If you want to continue working on branches after switching the default branch, rebase them by running ``git rebase --onto main ``. Once you resubmit a request, it appears under the ``main`` environment on Upsun. ## 5. Deactivate the `old` branch To change your default branch, you first need to deactivate the existing default branch to remove protections. Deactivate the `old` environment without deleting it by running the following CLI command: ```bash upsun environment:delete --no-delete-branch old ``` ## 6. Set `main` as the default branch
Without a source integration With a source integration Once ``old`` has been deactivated, set the project’s default branch to ``main``: ```bash {} upsun project:info default_branch main ``` Set the project’s default branch in Upsun to ``main``: ```bash {} upsun project:info default_branch main ``` Follow the instructions to change the default branch to ``main`` for your provider: - [GitHub](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-branches-in-your-repository/changing-the-default-branch) - [GitLab](https://docs.gitlab.com/ee/user/project/repository/branches/default.md#change-the-default-branch-name-for-a-project) - [BitBucket](https://community.atlassian.com/t5/Bitbucket-questions/How-to-change-MAIN-branch-in-BitBucket/qaq-p/977418) ## 7. Update DNS records Whether or not you're using a CDN, if your site is live you have probably added an Upsun address somewhere when configuring a [custom domain](https://docs.upsun.com../domains/steps.md). If you have a CDN, it's with the CDN provider. If you don't have a CDN, it's probably a `CNAME` record. In either case, the setting probably has the old environment name as part of it. Update the setting to use the new environment name. Verify that the new URL is correct by comparing it to the result from this command: ```bash upsun environment:info edge_hostname ``` ## 8. Optional: Delete the `old` environment If you no longer want the `old` environment, such as to stop accidental use, delete it completely: ```bash upsun environment:delete --delete-branch old ``` --- # Source: https://docs.upsun.com/define-routes.md # Define routes A [_route_](https://docs.upsun.com/glossary.md#route) defines how requests are handled _after_ they reach Upsun. It tells the Upsun platform how to handle incoming web requests and to which application (or destination) to direct the requests. You define routes in a [_router_](https://docs.upsun.com/glossary.md#router), which is the `.routes` key in your project's `.upsun/config.yaml` file in your Git repository. Routes define how your web applications are accessed, which is helpful when you have [multiple apps](https://docs.upsun.com../create-apps/multi-app.md) in one project or you want to redirect requests to specific destinations, such as `example.com` rather than `www.example.com`. If you have a single route served by a single app, you do not need to configure routes: your project includes a [default route](#default-route-definition). **Before adding routes to your Upsun project, you must configure your DNS records** so that each route’s hostname resolves to the project’s assigned target (for example, via CNAME or appropriate DNS records). If DNS doesn’t point to your project, certificate renewal will fail. ## Examples These examples show how to define routes. ### Default route definition If you don't include a file defining routes, a single default route is deployed. If you have one app to direct traffic to and its name is `myapp`, this is equivalent to the following: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": type: upstream upstream: myapp:http ``` All traffic to your domain (say, `https://example.com`) is sent to your app. This also includes redirecting requests from `http` to `https`. It affects your [default domain](#default). ### Basic redirect definition In a basic situation, you have one app to direct traffic to. Say its name is `myapp`. And say you want to redirect requests from `https://www.example.com` to `https://example.com`. Define your routes like this: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": type: upstream upstream: "myapp:http" "https://www.{default}/": type: redirect to: "https://{default}/" ``` This affects your [default domain](#default). You have one route that serves content (the one with the `upstream`) and one that redirects to the first (the one with the `redirect`). Redirects from `http` to `https` are generally included by default and don't need to be listed. ### Multi-app route definition The specifics of configuring the Router container for multiple applications is explored in detail in the [Multiple apps](https://docs.upsun.com/create-apps/multi-app/routes.md) documentation. ### Sticky routing Sticky routing ensures that all requests from a specific client are consistently routed to the same instance of your application. This can be critical for stateful applications that rely on local session data, preventing user context from being lost in a horizontally scaled environment. You can enable it in your [route configuration](#route-configuration-reference) to have the router attempt to send repeated requests from the same client to the same instance. At Upsun, sticky routing is implemented using a hash of the client’s IP address. This ensures requests from the same IP are generally routed to the same container. ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": type: upstream upstream: app:http sticky: true ``` This enables sticky routing at the router level. **Note**: Because the routing uses IP hashing, scaling your environment up or down can change the hash distribution, causing requests to be routed to different containers. For production workloads that require persistent sessions, use an external session store (for example, [Redis](https://docs.upsun.com/add-services/redis.md)), or design your app to be stateless. ## Trailing slashes All defined routes have at least a slash in the path. So you might define routes for 2 apps named `myapp` and `api` as follows: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}": type: upstream upstream: "myapp:http" "https://subdomain.example.com": type: upstream upstream: "api:http" ``` Both of these routes would be resolved with trailing slashes. So if you check your [`PLATFORM_ROUTES` variable](https://docs.upsun.com../development/variables/use-variables.md#use-provided-variables), you see the following resolved routes (assuming `example.com` is your default domain): ```json { "https://example.com/": { "primary": true, "id": null, "attributes": {}, "type": "upstream", "upstream": "myapp", "original_url": "https://{default}" }, "https://subdomain.example.com/": { "primary": false, "id": null, "attributes": {}, "type": "upstream", "upstream": "api", "original_url": "https://subdomain.example.com" } } ``` ## Route placeholders Each route in your configuration file is defined in one of two ways: * An absolute URL such as `https://example.com/blog` * A URL with a placeholder such as `https://{default}/blog` The available placeholders are `{default}` and `{all}`. They stand in for the [custom domains](https://docs.upsun.com../domains/steps.md) you've defined in your project. These domains can be top-level domains (`example.com`) or subdomains (`app.example.com`). ### `{default}` `{default}` represents your default custom domain. If you have set your default domain to `example.com`, `example.com` and `{default}` in your `.upsun/config.yaml` file have the same result for your Production environment. You can use the `{default}` placeholder: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/blog": type: upstream upstream: "myapp:http" ``` And you can use an absolute URL: ```yaml {location=".upsun/config.yaml"} routes: "https://example.com/blog": type: upstream upstream: "myapp:http" ``` In both cases, the URLs for your Production environment are the same. #### URLs in preview environments URLs in [preview environments](https://docs.upsun.com../glossary.md#preview-environment) (development and staging types) follow a different pattern. No matter how you have set your default domain (even if you don't have one), using either the absolute URL or the `{default}` placeholder results in the same URL. In any case, you get the same URL for an environment named `feature`: ```txt {no-copy="true"} https://feature-t6dnbai-abcdef1234567.us-2.platformsh.site/blog ``` Note that the `example.com` prefix isn't part of the generated URL. ### `{all}` You can also set up multiple domains for a single project. To define rules for all of them, use `{all}` in your template. Say you have both `example.com` and `example.net` as domains in a project. You can then define the following routes: ```yaml {location=".upsun/config.yaml"} routes: "https://{all}/": type: upstream upstream: "myapp:http" "https://www.{all}/": type: redirect to: "https://{all}/" ``` The first route means you're serving the same content at multiple domains: your app runs at both `https://example.com` and `https://example.net`. The second route means that `https://www.example.com` redirects to `https://example.com` _and_ `https://www.example.net` redirects to `https://example.net`. If your project has no domains or only one, `{all}` behaves exactly like `{default}`. If you have two routes sharing the same HTTP scheme, domain, and path and the first route is using `{default}` and the second is using `{all}`, the route using `{default}` takes precedence. Say you have two apps named `app1` and `app2` and define two routes like this: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": type: upstream upstream: "app1:http" "https://{all}/": type: upstream upstream: "app2:http" ``` Requests to your default domain are served by `app1`. ## Wildcard routes Upsun supports wildcard routes, so you can map multiple subdomains to the same application. Both `redirect` and `upstream` routes support wildcard routes. Prefix a route with an asterisk (`*`), for example `*.{default}`. If you have configured `example.com` as your default domain, HTTP requests to `www.example.com`, `blog.example.com`, and `us.example.com` are all routed to the same endpoint. It also works on preview environments. If you have a branch named `feature`, it's `{default}` domain looks something like: `feature-def123-vmwklxcpbi6zq.us.upsun.com` (depending on the project's region). So requests to `blog.feature-def123-vmwklxcpbi6zq.us.upsun.com` and `us.feature-def123-vmwklxcpbi6zq.eu.upsun.com` are both routed to the same endpoint. Let's Encrypt wildcard certificates aren't supported (they would need DNS validation). So if you want to use a wildcard route and protect it with HTTPS, you need to provide a [custom TLS certificate](https://docs.upsun.com../domains/steps/tls.md). ## Route identifiers When your project has deployed and routes are generated, all placeholders (`{default}` and `{all}`) are replaced with appropriate domain names and any additional routes (such as redirecting HTTP to HTTPS) are created. This means the final generated routes differ by environment and so shouldn't be hard coded in your app. These routes are available in the `PLATFORM_ROUTES` environment variable as a base64-encoded JSON object. They are also available within an application container from the `/run/config.json` file so you can maintain a high number of routes more easily. To locate routes in a standardized fashion in any environment, you may specify an `id` for on each route. This identifier is the same across all environments. Say you have two apps, `app1` and `app2`, that you want to serve at two subdomains, `site1` and `site2`. You can define your routes like this: ```yaml {location=".upsun/config.yaml"} routes: "https://site1.{default}/": type: upstream upstream: 'app1:http' "https://site2.{default}/": type: upstream id: 'the-second' upstream: 'app2:http' ``` To see the generated routes on your environment named `feature`, run: ```bash upsun ssh --environment feature 'echo $PLATFORM_ROUTES | base64 --decode | jq .' ``` The result is something like this: ```json { "https://site1.feature-t6dnbai-abcdef1234567.us-2.platformsh.site/": { "primary": true, "id": null, "attributes": {}, "type": "upstream", "upstream": "app1", "original_url": "https://site1.{default}/" }, "https://site2.feature-t6dnbai-abcdef1234567.us-2.platformsh.site/": { "primary": null, "id": "the-second", "attributes": {}, "type": "upstream", "upstream": "app2", "original_url": "https://site2.{default}/" }, "http://site1.feature-t6dnbai-abcdef1234567.us-2.platformsh.site/": { "to": "https://site1.feature-t6dnbai-abcdef1234567.us-2.platformsh.site/", "original_url": "http://site1.{default}/", "type": "redirect", "primary": null, "id": null, "attributes": {} }, "http://site2.feature-t6dnbai-abcdef1234567.us-2.platformsh.site/": { "to": "https://site2.feature-t6dnbai-abcdef1234567.us-2.platformsh.site/", "original_url": "http://site2.{default}/", "type": "redirect", "primary": null, "id": null, "attributes": {}, } } ``` The `site2` HTTPS route has an `id` specified as `the-second`, while the other routes have `null` for their `id`. You can use this `id` to look up the domain of the route in every environment. ## Route attributes You might want to add extra information to routes to identify them in your app. Route `attributes` are arbitrary key-value pairs attached to a route. This metadata has no impact on Upsun, but is available in the `PLATFORM_ROUTES` environment variable. So you can define a route like this: ```yaml {location=".upsun/config.yaml"} routes: "http://{default}/": type: upstream upstream: "myapp:http" attributes: "foo": "bar" ``` The attributes appear in the routes data like so: ```json "https://feature-t6dnbai-abcdef1234567.us-2.platformsh.site/": { "primary": true, "id": null, "attributes": { "foo": "bar" }, "type": "upstream", "upstream": "myapp", "original_url": "https://{default}/" } ``` ## Route limits The maximum size of the routes document is 128 KB, which should fit around 300 different routes. If your `.upsun/config.yaml` file would result in too large of a route information value, it's rejected. The full list of generated route information is often much larger than what's specified in the `.upsun/config.yaml` file. For example, by default all HTTPS routes (and all uses of `{all}`) are duplicated to create HTTP redirect routes. As a general rule, you should keep to your defined routes under 100. If your `.upsun/config.yaml` file is rejected for being too big, do one of the following: * Move redirect routes to the application. * Collapse the route definitions into a [regular expression-based redirect](https://docs.upsun.com/define-routes/redirects.md#partial-redirects). Let's Encrypt allows a maximum of 100 hostnames per certificate. You can have 1 Let's Encrypt certificate for each of your environments. If you define both a `{default}` and a `www.{default}` route for each domain you use, you can add up to 50 hostnames. Going over this limitation results in a warning on deploy and no new TLS certificates are issued. Non-default ports (other than `80` and `443`) aren't supported and can't be included in routes configuration. ## Route configuration reference You can configure each route separately with the following properties: | Name | Type | Required | Description | | ------------- | --------- | ----------------------- | ----------- | | `type` | `string` | Yes | One of the following options: - `upstream` means content is served at that route by an app and requires the `upstream` property to be set. - `redirect` means the route is redirected elsewhere in your project and requires the `to` property. - `proxy` means requests are redirected _outside_ your project and requires the `to` property. See more about [proxy routes](https://docs.upsun.com/define-routes/proxy.md). | | `upstream` | `string` | If `type` is `upstream` | The `name` of the app to be served (as defined in your [app configuration](https://docs.upsun.com/create-apps.md)) followed by `:http`. Example: `app:http` | | `sticky` | `boolean` | No | Enables [sticky routing](#sticky-routing) for the route. When `true`, the router attempts to send repeat requests from the same client to the same upstream container, based on a hash of the client’s IP address. | | `to` | `string` | If `type` is `redirect` | The absolute URL or other route to which the given route should be redirected with an HTTP 301 status code. | | `ssi` | `boolean` | No | Whether [server side includes](https://docs.upsun.com/define-routes/ssi.md) are enabled. | | `redirects` | Object | No | Defines redirects for partial routes. For definition and options, see the [redirect rules](https://docs.upsun.com/define-routes/redirects.md). | | `cache` | Object | No | Defines caching policies for the given route. Enabled by default. For details and options, see [route caching](https://docs.upsun.com/define-routes/cache.md). | | `id` | `string` | No | A unique identifier for the route. See [route identifiers](#route-identifiers). | | `primary` | `boolean` | No | Whether the route is the primary route for the project. Can only be `true` for one route in the configuration file, but if you use the [`{all}` placeholder](#all), it can be `true` for multiple final routes. Defaults to the first defined `upstream` route. | | `tls` | Object | No | TLS configuration. See [HTTPS](https://docs.upsun.com/define-routes/https.md#optional-configure-tls-connections). | | `attributes` | Object | No | Any key-value pairs you want to make available to your app. See [route attributes](#route-attributes). | ## CLI access The [Upsun CLI](https://docs.upsun.com../administration/cli.md) can show you the routes you have configured for an environment. These are the routes as defined in the `.upsun/config.yaml` file with the [placeholders](#route-placeholders) plus the default redirect from HTTP to HTTPS. They aren't the final generated routes. Run the following command: ```bash upsun environment:routes ``` You get output similar to: ```bash Routes on the project Example (abcdef123456), environment main (type: production): +---------------------------+----------+---------------------------+ | Route | Type | To | +---------------------------+----------+---------------------------+ | https://www.{default}/ | upstream | myapp:http | | https://www.{default}/api | upstream | api:http | | http://www.{default}/ | redirect | https://www.{default}/ | | http://www.{default}/api | redirect | https://www.{default}/api | +-----------------------+----------+-------------------------------+ To view a single route, run: upsun route:get ``` Viewing a single route gives you more detailed info, such as its cache and SSI settings. ## WebSocket routes To use the WebSocket protocol on a route, `cache` must be disabled because WebSocket is incompatible with buffering, which is a requirement for the router caching. 1. Define a route that serves WebSocket: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/ws": type: upstream upstream: "myapp:http" cache: enabled: false # Below HTTP config may not be necessary for every Websocket client. "https://{default}/ws": type: upstream upstream: "myapp:http" cache: enabled: false ``` 2. [Disable request buffering](https://docs.upsun.com/create-apps/image-properties/web.md#locations) in your app configuration. ```yaml {location=".upsun/config.yaml"} applications: myapp: web: commands: start: /app/.linuxbrew/bin/websocketd --port=$PORT ./wsmanager.sh upstream: socket_family: tcp protocol: http locations: '/': passthru: true request_buffering: enabled: false ``` ## `.htaccess` files Upsun uses Nginx servers, not Apache ones. You [can't use `.htaccess` files with Nginx](https://www.nginx.com/resources/wiki/start/topics/examples/likeapache-htaccess/), they are therefore ignored on Upsun. You can accomplish the same redirect and rewrite goals with your [routes](https://docs.upsun.com../define-routes.md) and [web server locations](https://docs.upsun.com../create-apps/web.md). --- # Source: https://docs.upsun.com/projects/delete-project.md # Delete a project To delete a project, you must be an organization owner or have the [manage plans permission](https://docs.upsun.com../administration/users.md#organization-permissions). To delete an Upsun project, including all data, code, and active environments: - Run the following command: ```bash {} upsun project:delete --project ``` - Read the consequences to deletion and enter ``y``. - Enter the project title to confirm. You are billed only for the portion of a month when the project was active. When you remove all your projects from your user account, you stop being charged. --- # Source: https://docs.upsun.com/languages/python/dependencies.md # Manage Python dependencies p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. You can manage Python packages in different ways. Python images come with pip installed, but they're flexible enough so you can choose what package manager you want. This article describes how to configure major package management tools. This package management is different from global dependencies (packages available as commands), which you can add in your [app configuration](https://docs.upsun.com../../create-apps.md). See more about [managing global dependencies](https://docs.upsun.com/languages/python.md#package-management). ## Pip [pip](https://pip.pypa.io/en/stable/) is the primary package installer for Python and comes installed on every Python container. You can use it to install packages from the Python Package Index and other locations. To manage packages with pip, commit a `requirements.txt` file with all of the dependencies needed for your app. Then install the packages in your [`build` hook](https://docs.upsun.com../../create-apps/hooks.md), such as by running the following command: `pip install -r requirements.txt`. The following sections present ideas to keep in mind to ensure repeatable deployments on Upsun. ### pip version The version of pip on Python containers gets updated regularly. But it isn't guaranteed to be the latest version or the version that matches your local environment. You might want to define a specific version of pip in your deployments to further enforce repeatable builds. To do so, modify your [app configuration](https://docs.upsun.com../../create-apps.md), as in the following examples: ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" type: 'python:3.14' hooks: build: | # Fail the build if any errors occur set -eu # Download the latest version of pip python3.14 -m pip install --upgrade pip # Install dependencies pip install -r requirements.txt ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" type: 'python:3.14' variables: env: PIP_VERSION: '22.3.1' hooks: build: | # Fail the build if any errors occur set -eu # Download a specific version of pip python3.14 -m pip install pip==$PIP_VERSION # Install dependencies pip install -r requirements.txt ``` ### pip freeze You can write `requirements.txt` files in various ways. You can specify anything from the latest major to a specific patch version in a [requirement specifier](https://pip.pypa.io/en/stable/reference/requirement-specifiers/). Use `pip freeze` before committing your requirements to pin specific package versions. This ensures repeatable builds on Upsun with the same packages. ## Pipenv [Pipenv](https://pipenv.pypa.io/en/latest/) is a package manager for Python that creates and manages a virtual environment for Python projects. Dependencies are tracked and defined within a `Pipfile`. It also generates a `Pipfile.lock` file to produce repeatable installs. You can specify the latest or a specific version of Pipenv in your deployments to ensure repeatable builds. Because Pipenv depends on pip, you might want to also specify the pip version. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" type: 'python:3.14' dependencies: python3: pipenv: '*' hooks: build: | # Fail the build if any errors occur set -eu # Download the latest version of pip python3.14 -m pip install --upgrade pip # Install dependencies # Include `--deploy` to fail the build if `Pipfile.lock` isn't up to date pipenv install --deploy ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" type: 'python:3.14' variables: env: PIP_VERSION: '22.3.1' dependencies: python3: pipenv: '2024.4.1' hooks: build: | # Fail the build if any errors occur set -eu # Download a specific version of pip python3.14 -m pip install pip==$PIP_VERSION # Install dependencies # Include `--deploy` to fail the build if `Pipfile.lock` isn't up to date pipenv install --deploy ``` ## UV [uv](https://docs.astral.sh/uv/) is an extremely fast Python package and project manager, written in Rust. ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' dependencies: python3: uv: "*" ``` ## Poetry [Poetry](https://python-poetry.org/docs/) is a tool for dependency management and packaging in Python. It allows you to declare the libraries your project depends on and manages them for you. Poetry offers a lock file to ensure repeatable installs and can build your project for distribution. It also creates and manages virtual environments to keep project work isolated from the rest of your system. To set up Poetry on Upsun, follow these steps: 1. Configure your virtual environment by setting two variables in your [app configuration](https://docs.upsun.com../../create-apps.md). - [`POETRY_VIRTUALENVS_IN_PROJECT`](https://python-poetry.org/docs/configuration/#virtualenvsin-project): Setting this to `true` places the virtual environment at the root of the app container: `/app/.venv`. - [`POETRY_VIRTUALENVS_CREATE`](https://python-poetry.org/docs/configuration/#virtualenvscreate): Setting this to `true` ensures that the same virtual environment created during the build hook is reused in subsequent steps. Set the variables as follows: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' variables: env: POETRY_VIRTUALENVS_IN_PROJECT: true POETRY_VIRTUALENVS_CREATE: true ``` 2. Install Poetry. You can specify the latest or a specific version of Poetry in your deployments to ensure repeatable builds. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" type: 'python:3.14' dependencies: python3: poetry: '*' variables: env: POETRY_VIRTUALENVS_IN_PROJECT: true POETRY_VIRTUALENVS_CREATE: true hooks: build: | # Fail the build if any errors occur set -eu # Download the latest version of pip python3.14 -m pip install --upgrade pip # Install dependencies poetry install ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" type: 'python:3.14' dependencies: python3: poetry: '>=1.8' variables: env: POETRY_VIRTUALENVS_IN_PROJECT: true POETRY_VIRTUALENVS_CREATE: true hooks: build: | # Fail the build if any errors occur set -eu # Download the latest version of pip python3.14 -m pip install --upgrade pip # Install dependencies poetry install ``` 3. Make Poetry available outside the build hook. Although step 2 updated the `PATH` to make Poetry available during the build hook, it isn't enough to make it available at subsequent stages. To use Poetry in a start command, a deploy hook, or during SSH sessions, update the `PATH` in a [`.environment` file](https://docs.upsun.com../../development/variables/set-variables.md#set-variables-via-script). ```text {location=".environment"} # Updates PATH when Poetry is used, making it available during deploys, start commands, and SSH. if [ -n "$POETRY_VERSION" ]; then export PATH="/app/.local/bin:$PATH" fi ``` --- # Source: https://docs.upsun.com/learn/tutorials/dependency-updates.md # Automate your code updates Upsun allows you to update your dependencies through [source operations](https://docs.upsun.com/create-apps/source-operations.md). ## Before you start You need: - The [Upsun CLI](https://docs.upsun.com/administration/cli.md) - An [API token](https://docs.upsun.com/administration/cli/api-tokens.md#2-create-an-api-token) ## 1. Define a source operation to update your dependencies To facilitate updating your dependencies in your project, define a source operation in your `.upsun/config.yaml` file depending on your dependency manager: ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" source: operations: update: command: | set -e composer update git add composer.lock git add -A git diff-index --quiet HEAD || git commit --allow-empty -m "Update Composer dependencies" ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" source: operations: update: command: | set -e npm update git add package.json package-lock.json git add -A git diff-index --quiet HEAD || git commit --allow-empty -m "Update npm dependencies" ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" source: operations: update: command: | set -e yarn upgrade git add yarn.lock git add -A git diff-index --quiet HEAD || git commit --allow-empty -m "Update yarn dependencies" ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" source: operations: update: command: | set -e go get -u go mod tidy git add go.mod go.sum git add -A git diff-index --quiet HEAD || git commit --allow-empty -m "Update Go dependencies" ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" source: operations: update: command: | set -e pipenv update git add Pipfile Pipfile.lock git add -A git diff-index --quiet HEAD || git commit --allow-empty -m "Update Python dependencies" ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" source: operations: update: command: | set -e bundle update --all git add Gemfile Gemfile.lock git add -A git diff-index --quiet HEAD || git commit --allow-empty -m "Update Ruby dependencies" ``` ## 2. Automate your dependency updates with a cron job After you've defined a source operation to [update your dependencies on your project](#1-define-a-source-operation-to-update-your-dependencies), you can automate it using a cron job. Note that it’s best not to run source operations on your production environment, but rather on a dedicated environment where you can test changes. Make sure you have the [Upsun CLI](https://docs.upsun.com/administration/cli.md) installed and [an API token](https://docs.upsun.com/administration/cli/api-tokens.md#2-create-an-api-token) so you can run a cron job in your app container. 1. Set your API token as a top-level environment variable: - Open the environment where you want to add the variable. - Click Settings **Settings**. - Click **Variables**. - Click **+ Add variable**. - In the **Variable name** field, enter ``env:UPSUN_CLI_TOKEN``. - In the **Value** field, enter your API token. - Make sure the **Available at runtime** and **Sensitive variable** options are selected. - Click **Add variable**. **Note**: Once you add the API token as an environment variable, anyone with [SSH access](https://docs.upsun.com/development/ssh.md) can read its value. Make sure you carefully check your [user access on this project](https://docs.upsun.com/administration/users.md#manage-project-users). 2. Add a build hook to your app configuration to install the CLI as part of the build process: ```yaml {location=".upsun/config.yaml"} applications: myapp: hooks: build: | set -e echo "Installing Upsun CLI" curl -fsSL https://raw.githubusercontent.com/platformsh/cli/main/installer.sh | bash echo "Testing Upsun CLI" upsun ``` 3. Then, to configure a cron job to automatically update your dependencies once a day, use a configuration similar to the following: ```yaml {location=".upsun/config.yaml"} applications: myapp: # ... crons: update: # Run the code below every day at midnight. spec: '0 0 * * *' commands: start: | set -e upsun sync -e development code data --no-wait --yes upsun source-operation:run update --no-wait --yes ``` The example above synchronizes the `development` environment with its parent and then runs the `update` source operation defined [previously](#1-define-a-source-operation-to-update-your-dependencies). **Note**: If you have enabled a [source integration](https://docs.upsun.com/integrations/source.md), and have enabled ``--fetch-branches`` on that integration, merging on Upsun is not possible. Therefore, the ``sync`` command in the example above would fail. ## 3. Configure notifications about dependency updates To get notified every time a source operation is triggered and therefore every time a dependency is updated, you can configure activity scripts or webhooks. ### Notifications through an activity script After you've defined a source operation to [update your dependencies on your project](#1-define-a-source-operation-to-update-your-dependencies), you can configure an activity script to receive notifications every time a dependency update is triggered. **Example**: You want to get notified of every dependency update through a message posted on a Slack channel. To do so, follow these steps: - In your Slack administrative interface, [create a new Slack webhook](https://api.slack.com/messaging/webhooks). You get a URL starting with ``https://hooks.slack.com/``. - Replace ``SLACK_URL`` in the following ``.js`` script with your webhook URL. - Add the following code to a ``.js`` file: ```javascript {} /** * Sends a color-coded formatted message to Slack. * * To control what events trigger it, use the --events switch in * the Upsun CLI. * * Replace SLACK_URL in the following script with your Slack webhook URL. * Get one here: https://api.slack.com/messaging/webhooks * You should get something like: const url = 'https://hooks.slack.com/...'; * * activity.text: a brief, one-line statement of what happened. * activity.log: the complete build and deploy log output, as it would be seen in the Console log screen. */ function sendSlackMessage(title, message) { const url = 'SLACK_URL'; const messageTitle = title; const color = activity.result === "success" ? "#66c000" : "#ff0000"; const body = { attachments: [ { title: messageTitle, text: message, color: color, }, ], }; const resp = fetch(url, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(body), }); if (!resp.ok) { console.log("Sending slack message failed: " + resp.body.text()); } } sendSlackMessage(activity.text, activity.log); ``` - Run the following [Upsun CLI](https://docs.upsun.com/administration/cli.md) command: ```bash {} upsun integration:add --type script --file ./my_script.js --events=environment.source-operation ``` Optional: to only get notifications about specific environments, add the following flag to the command: ``--environments=your_environment_name``. Anytime a dependency is updated via a source operation, the activity script now reports it to Slack. ### Notifications through a webhook After you've defined a source operation to [update your dependencies on your project](#1-define-a-source-operation-to-update-your-dependencies), you can configure a webhook to receive notifications every time a dependency update is triggered. [Webhooks](https://docs.upsun.com/integrations/activity/webhooks.md) allow you to host a script yourself externally. This script receives the same payload as an activity script and responds to the same events, but can be hosted on your own server and in your own language. To configure the integration between your webhook and your source operation, run the following [Upsun CLI](https://docs.upsun.com/administration/cli.md) command: ```bash upsun integration:add --type=webhook --url=URL_TO_RECEIVE_JSON --events=environment.source-operation ``` Optional: to only get notifications about specific environments, add the following flag to the command: `--environments=your_environment_name`. To test the integration and the JSON response, you can generate a URL from a service such as [webhook.site](https://webhook.site) and use the generated URL as `URL_TO_RECEIVE_JSON`. This URL then receives the JSON response when a source operation is triggered. Anytime a dependency is updated via a source operation, the webhook now receives a POST message. This POST message contains complete information about the entire state of the project at that time. --- # Source: https://docs.upsun.com/dedicated-environments/dedicated-gen-2/development.md # Source: https://docs.upsun.com/development.md # Development --- # Source: https://docs.upsun.com/integrations/activity/discord.md # Example: Discord The following example activity script posts a message to a Discord channel every time it's triggered. To use it, follow these steps: 1. In your Discord administrative interface, [create a new Discord webhook](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks). Give it a name and specify the channel where it should post messages. Copy the URL for the webhook. 2. Replace `DISCORD_URL` in the following script with your webhook URL. 3. Paste the code into a `.js` file. 4. Add it as a new [script integration](https://docs.upsun.com/integrations/activity.md#installing). Specify which events should trigger it using the `--events` flag. Optionally specify environments with the `--environments` flag. Now, any activities that meet the events/environment criteria you specified are reported to Discord. Once you have it working, you're free to modify the code below as desired. For more on the message format, see the [Discord webhook API reference](https://discord.com/developers/docs/resources/webhook#execute-webhook). ```javascript /** * Sends a message to Discord. * * To control what events trigger it, use the --events switch in * the Upsun CLI. * * @param {string} title * The title of the message block to send. * @param {string} message * The message body to send. */ function sendDiscordMessage(title, message) { const url = DISCORD_URL; const messageTitle = title + (new Date().getDay() === 5) ? " (On a Friday! :calendar:)" : ""; const body = { content: messageTitle, embeds: [ { description: message, }, ], }; const resp = fetch(url, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(body), }); if (!resp.ok) { console.log("Sending Discord message failed: " + resp.body.text()); } } sendDiscordMessage(activity.text, activity.log); ``` Common properties you may want to send to Discord (in the last line of the script) include: - `activity.text`: A brief, one-line statement of what happened. - `activity.log`: The complete build and deploy log output, as it would be seen in the Console log screen. For more properties, see the [activity reference](https://docs.upsun.com/integrations/activity/reference.md). --- # Source: https://docs.upsun.com/domains/steps/dns.md # DNS management and apex domains Using `CNAME` records helps [prevent downtime](#cname-records) during maintenance operations. But `CNAME` records can't point to apex domains, so you need to [set up a workaround](#workarounds-for-apex-domains). Available workarounds depend on your DNS provider. ## `CNAME` records Each site on Upsun is made up of a set of containers. To map incoming requests to the appropriate container, Upsun runs routers in [each region](https://docs.upsun.com../../development/regions.md). A router's IP address can change in two cases: - During an upgrade or maintenance operation, routers can be taken offline while changes are applied. - During a region upscale or downscale, routers can be added or removed. In such situations, using `A` records can cause downtime. `A` records map a domain to an IP address. When a router's IP address changes, you need to manually update your `A` records. Your site remains offline until you do, or until the router is back from maintenance. To prevent downtime, create `CNAME` records through your DNS provider. `CNAME` records map a domain to another. Set up your `CNAME` records to point at your project's [target URL](https://docs.upsun.com../../domains/steps.md#1-get-the-target-for-your-project). The DNS record for this target URL automatically resolves to the IP addresses of the routers in your project's region. When a router's IP address changes, the DNS record is automatically and immediately updated. This prevents downtime without intervention from you. Note that `CNAME` records can't point to [apex domains](https://docs.upsun.com/glossary.md#apex-domain). Check with your DNS provider if they offer [workarounds](#workarounds-for-apex-domains). ## Workarounds for apex domains Although `CNAME` records can't point to apex domains, most DNS providers offer workarounds. Contact your DNS provider and choose the option that works for you. If you use a CDN, you likely already have a workaround in place, such as with [Fastly](https://docs.upsun.com../cdn/fastly.md#3-handle-apex-domains) and [Cloudflare](https://docs.upsun.com../cdn/cloudflare.md#3-handle-apex-domains). ### Custom records Some DNS providers offer custom records such as `ANAME`, `ALIAS` or `HTTPS` records, which you can manage like `CNAME` records. But unlike `CNAME` records, these custom records can point to apex domains. To use custom records, follow the instructions on [how to set up a custom domain](https://docs.upsun.com/domains/steps.md). When you come to configuring your DNS provider, instead of a `CNAME` record, add a custom record pointing from your domain to [your project's target URL](https://docs.platform.sh/domains/steps.md#2-get-the-target-for-your-project). ### Domain forwarding If your DNS provider doesn't support custom records, consider using domain forwarding. If your domain is `example.com`, domain forwarding redirects all requests from `example.com` to `www.example.com`. To use domain forwarding, follow these steps: 1. Make the `www.` version of your site the default (canonical) version and configure your app and routes to [use the `www` subdomain as `upstream`](https://docs.upsun.com../../define-routes.md). 2. Follow the instructions on [how to set up a custom domain](https://docs.upsun.com/domains/steps.md). When you come to configuring your DNS provider, instead of a `CNAME` record, add a record forwarding requests from `` to `www.`. ### Redirection service If your DNS provider doesn't support custom records or domain forwarding, consider using a redirection service. If your domain is `example.com`, a redirection service uses an `A` record to redirect all requests from `example.com` to `www.example.com`. To use a redirection service, follow these steps: 1. Make the `www.` version of your site the default (canonical) version and configure your app and routes to [use the `www` subdomain as `upstream`](https://docs.upsun.com../../define-routes.md). 2. Follow the instructions on [how to set up a custom domain](https://docs.upsun.com/domains/steps.md). When you come to configuring your DNS provider, instead of a `CNAME` record, add an `A` record pointing from your domain to the redirection service. ### `A` records If your DNS provider doesn't support any other workaround, consider using `A` records, but only as a last resort. When you use `A` records, [if a router's IP address changes](#cname-records), you need to update your `A` records manually. Until you do, your site can appear offline because requests are lost. To use `A` records, follow these steps: 1. [Get the IP addresses](https://docs.upsun.com/development/regions.md#public-ip-addresses) of your project's production environment. 2. Follow the instructions on [how to set up a custom domain](https://docs.upsun.com/domains/steps.md). When you come to configuring your DNS provider, instead of a `CNAME` record, add `A` records pointing from your domain to each of the IP addresses from step 1. When a request comes in, one of those IP addresses is used at random. --- # Source: https://docs.upsun.com/domains.md # Custom domains --- # Source: https://docs.upsun.com/languages/dotnet.md # C#/.NET Core p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. Upsun supports deploying .NET applications by allowing developers to define a build process and pass its variables to the .NET Core build environment. ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 10.0 - 8.0 ### Specify the language To use .Net Core, specify `dotnet` as your [app's `type`](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#types): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. : type: 'dotnet:' ``` For example: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'dotnet:10.0' ``` ## Building the application To build basic applications in .NET containers, it's enough to use the [`dotnet publish` command](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish) with the default [framework-dependent deployment](https://docs.microsoft.com/en-us/dotnet/core/deploying/#publish-framework-dependent): ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'dotnet:10.0' hooks: build: | set -xe dotnet publish --output "$PLATFORM_OUTPUT_DIR" \ -p:UseRazorBuildServer=false \ -p:UseSharedCompilation=false ``` where `PLATFORM_OUTPUT_DIR` is the output directory for compiled languages available at build time. Typically, .NET Core builds start a collection of build servers, which are helpful for repeated builds. On Upsun, however, if this process isn't disabled, the build process doesn't finish until the idle timeout is reached. As a result, you should include `-p` toggles that disable the Razor compiler for dynamic CSHTML pages (`UseRazorBuildServer`) and the .NET MSBuild compiler (`UseSharedCompilation`). If you want multiple builds for your application, make sure to call `dotnet build-server shutdown` at the end of your build hook. ## Running the application .NET Core applications should be started using the `web.commands.start` directive in `.upsun/config.yaml`. This ensures that the command starts at the right moment and stops gracefully when a redeployment needs to be executed. Also, should the program terminate for any reason, it's automatically restarted. Note that the start command _must_ run in the foreground. Incoming requests are passed to the application using either a TCP (default) or Unix socket. The application must use the [appropriate environment variable](https://docs.upsun.com/create-apps/image-properties/web.md#where-to-listen) to determine the URI to listen on. For a TCP socket ([recommended](https://go.microsoft.com/fwlink/?linkid=874850)), the application must listen on `http://127.0.0.1`, using the `PORT` environment variable. There is an Nginx server sitting in front of your application. Serving static content via Nginx is recommended, as this allows you to control headers (including cache headers) and also has marginal performance benefits. Note that HTTPS is also terminated at the Nginx proxy, so the `app.UseHttpsRedirection();` line in `Startup.cs` should be removed. To force HTTPS-only, refer to the [routes documentation](https://docs.upsun.com../define-routes/https.md#enable-https). The following example configures an environment to serve the static content folders commonly found in [ASP.NET MVC](https://dotnet.microsoft.com/apps/aspnet/mvc) templates using Nginx, while routing other traffic to the .NET application. ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'dotnet:10.0' web: locations: "/": root: "wwwroot" allow: true passthru: true rules: # Serve these common asset types with customs cache headers. \.(jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff2?|otf|ttf)$: allow: true expires: 300s commands: start: "dotnet WebApplication1.dll" ``` You can also route all requests to the application unconditionally: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'dotnet:10.0' web: locations: "/": allow: false passthru: true commands: start: "dotnet WebApplication1.dll" ``` --- # Source: https://docs.upsun.com/add-services/edgee.md # Edgee (Edge Analytics) Edge Analytics enables enterprises to collect analytics data at the edge, rather than in the browser. This approach helps prevent data loss caused by ad blockers, privacy restrictions, or performance limitations. Built on Edgee’s open-source technology and Upsun’s global CDN and edge infrastructure, it delivers analytics in a privacy-compliant manner without impacting website performance. Edge Analytics integrates with platforms such as GA4, Amplitude, and Segment, providing an edge-based solution for data collection and analysis. **Before you begin you need:** - An up-and-running Upsun [Fixed or Flex](https://docs.upsun.com/administration/organizations.md#fixed-and-flex-organizations) project - [Fastly CDN subscription](https://docs.upsun.com/domains/cdn.md) ## Setup Edgee Edge Analytics integrates smoothly with your existing Upsun infrastructure and analytics tools. Our structured onboarding process includes dedicated technical sessions, staged deployment, and continuous support to ensure successful implementation. **Learn more about expected setup steps [here](https://www.edgee.cloud/docs/getting-started).** ## Configuration options Choose between cookieless and cookie-based user identification. **Learn more on which option is best for you based on Edgee documentation [here](https://www.edgee.cloud/docs/services/overview#cookieless-mode).** ## Pricing Edgee is available as an add-on, offering two flexible plans designed to suit your needs. - **Team Plan** — for growing teams that need actionable analytics. - **Enterprise Plan** — for organizations requiring advanced features and scalability. Pricing is usage-based, determined by the number of requests, events tracked, and type of additional components required. Our predictable pricing model includes all features, technical support, and continuous updates — with no hidden costs. **Learn more**: [Contact our Sales team](https://upsun.com/contact-us/) to learn more or request a quote. **FAQ**: For more information, read the FAQ posted on the [Edgee website here](https://www.edgee.cloud/docs/introduction/faq). --- # Source: https://docs.upsun.com/add-services/elasticsearch.md # Elasticsearch (Search service) Elasticsearch is a distributed RESTful search engine built for the cloud. See the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.md) for more information. ### Enterprise edition **Premium Service**: Elasticsearch versions 7.11 or later are no longer included in any Upsun plan. New versions of Elasticsearch will also be released as premium services. The versions displayed below are currently supported but can only be added separately at an additional cost, as they are premium services. **To add Elasticsearch, [contact Sales](https://upsun.com/contact-us).** - 7.17 - 8.5 - 8.19 ## Deprecated versions The following versions are still available in your projects for free, but they're at their end of life and are no longer receiving security updates from upstream. - 7.9 - 7.7 - 7.6 - 7.5 - 7.2 - 6.8 - 6.5 To ensure your project remains stable in the future, switch to [a premium version](#enterprise-edition). Alternatively, you can switch to one of the latest, free versions of [OpenSearch](https://docs.upsun.com/add-services/opensearch.md). To do so, follow the same procedure as for [upgrading](#upgrading). ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "username": null, "scheme": "http", "service": "elasticsearch", "fragment": null, "ip": "123.456.78.90", "hostname": "azertyuiopqsdfghjklm.elasticsearch.service._.eu-1.platformsh.site", "port": 9200, "cluster": "azertyuiopqsdf-main-7rqtwti", "host": "elasticsearch.internal", "rel": "elasticsearch", "path": null, "query": [], "password": "ChangeMe", "type": "elasticsearch:8.19", "public": false, "host_mapped": false } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_ELASTICSEARCH_HOST=="$(echo "$RELATIONSHIPS_JSON" | jq -r '.elasticsearch[0].host')" ``` For [premium versions](#enterprise-edition), the service type is `elasticsearch-enterprise`. ## Usage example ### 1. Configure the service To define the service, use the `elasticsearch` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: elasticsearch: ``` If you’re using a [premium version](https://docs.upsun.com/add-services/elasticsearch.md#enterprise-edition), use the ``elasticsearch-enterprise`` type instead. Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. ### 2. Define the relationship To define the relationship, use the following configuration: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: elasticsearch ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). ### Example configuration ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: elasticsearch: services: # The name of the service container. Must be unique within a project. elasticsearch: type: elasticsearch:8.19 ``` If you’re using a [premium version](https://docs.upsun.com/add-services/elasticsearch.md#enterprise-edition), use the ``elasticsearch-enterprise`` type instead. .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: elasticsearch: service: elasticsearch endpoint: elasticsearch services: # The name of the service container. Must be unique within a project. elasticsearch: type: elasticsearch:8.19 ``` If you’re using a [premium version](https://docs.upsun.com/add-services/elasticsearch.md#enterprise-edition), use the ``elasticsearch-enterprise`` type instead. ### Use in app To use the configured service in your app, add a configuration file similar to the following to your project. Note that configuration for [premium versions](#enterprise-edition) may differ slightly. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: elasticsearch: services: elasticsearch: type: elasticsearch:8.19 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/myapp" # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: elasticsearch: service: elasticsearch endpoint: elasticsearch services: elasticsearch: type: elasticsearch:8.19 ``` This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory. `myapp` has access to the `elasticsearch` service, via the corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) (as per [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships). From this, `myapp` can retrieve access credentials to the service through the [relationship environment variable](https://docs.upsun.com/add-services/elasticsearch.md#relationship-reference). ```bash {location="myapp/.environment"} # Set environment variables for individual credentials, # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. export ELASTIC_SCHEME="${ELASTICSEARCH_SCHEME}" export ELASTIC_HOST="${ELASTICSEARCH_HOST}" export ELASTIC_PORT="${ELASTICSEARCH_PORT}" # Surface more common Elasticsearch connection string variables for use in app. export ELASTIC_USERNAME="${ELASTICSEARCH_USERNAME}" export ELASTIC_PASSWORD="${ELASTICSEARCH_PASSWORD}" export ELASTIC_HOSTS=["$ELASTIC_SCHEME://$ELASTIC_HOST:$ELASTIC_PORT"] ``` The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``ELASTIC_HOSTS`` can be used within the application to connect to the service. Note that ``ELASTIC_HOSTS``, and all [Upsun-service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) like ``ELASTICSEARCH_HOST``, are environment-dependent. Unlike the build produced for a given commit, they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment. A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](https://docs.upsun.com/get-started.md). **Note**: When you create an index on Elasticsearch, don’t specify the ``number_of_shards`` or ``number_of_replicas`` settings in your Elasticsearch API call. These values are set automatically based on available resources. ## Authentication By default, Elasticsearch has no authentication. No username or password is required to connect to it. Starting with Elasticsearch 7.2 you may optionally enable HTTP Basic authentication. To do so, include the following in your `.upsun/config.yaml` configuration: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. elasticsearch: type: elasticsearch:8.19 configuration: authentication: enabled: true ``` If you're using a [premium version](#enterprise-edition), use the `elasticsearch-enterprise` type. That enables mandatory HTTP Basic auth on all requests. The credentials are available in any relationships that point at that service, in the `username` and `password` properties. You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``. Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) directly rather than hard coding any values. This functionality is generally not required if Elasticsearch isn't exposed on its own public HTTP route. However, certain applications may require it, or it allows you to safely expose Elasticsearch directly to the web. To do so, add a route to `.upsun/config.yaml` that has `elasticsearch:elasticsearch` as its upstream (where `elasticsearch` is whatever you named the service). For example: ```yaml {location=".upsun/config.yaml"} routes: "https://es.{default}/": type: upstream upstream: "elasticsearch:elasticsearch" services: # The name of the service container. Must be unique within a project. elasticsearch: type: elasticsearch:8.19 configuration: authentication: enabled: true ``` ## Plugins Elasticsearch offers a number of plugins. To enable them, list them under the `configuration.plugins` key in your `.upsun/config.yaml` file, like so: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. elasticsearch: type: elasticsearch:8.19 configuration: plugins: - analysis-icu ``` If you're using a [premium version](#enterprise-edition), use the `elasticsearch-enterprise` type. In this example you'd have the ICU analysis plugin and Python script support plugin. If there is a publicly available plugin you need that isn't listed here, [contact support](https://docs.upsun.com/learn/overview/get-support.md). ### Available plugins This is the complete list of official Elasticsearch plugins that can be enabled: | Plugin | Description | 2.4 | 5.x | 6.x | 7.x | 8.x | |-------------------------|-------------------------------------------------------------------------------------------|-----|-----|-----|-----|-----| | `analysis-icu` | Support ICU Unicode text analysis | * | * | * | * | * | | `analysis-nori` | Integrates Lucene Nori analysis module into Elasticsearch | | | * | * | * | | `analysis-kuromoji` | Japanese language support | * | * | * | * | * | | `analysis-smartcn` | Smart Chinese Analysis Plugins | * | * | * | * | * | | `analysis-stempel` | Stempel Polish Analysis Plugin | * | * | * | * | * | | `analysis-phonetic` | Phonetic analysis | * | * | * | * | * | | `analysis-ukrainian` | Ukrainian language support | | * | * | * | * | | `cloud-aws` | AWS Cloud plugin, allows storing indices on AWS S3 | * | | | | | | `delete-by-query` | Support for deleting documents matching a given query | * | | | | | | `discovery-multicast` | Ability to form a cluster using TCP/IP multicast messages | * | | | | | | `ingest-attachment` | Extract file attachments in common formats (such as PPT, XLS, and PDF) | | * | * | * | * | | `ingest-user-agent` | Extracts details from the user agent string a browser sends with its web requests | | * | * | | | | `lang-javascript` | JavaScript language plugin, allows the use of JavaScript in Elasticsearch scripts | | * | | | | | `lang-python` | Python language plugin, allows the use of Python in Elasticsearch scripts | * | * | | | | | `mapper-annotated-text` | Adds support for text fields with markup used to inject annotation tokens into the index | | | * | * | * | | `mapper-attachments` | Mapper attachments plugin for indexing common file types | * | * | | | | | `mapper-murmur3` | Murmur3 mapper plugin for computing hashes at index-time | * | * | * | * | * | | `mapper-size` | Size mapper plugin, enables the `_size` meta field | * | * | * | * | * | | `repository-s3` | Support for using S3 as a repository for Snapshot/Restore | | * | * | * | * | | `transport-nio` | Support for NIO transport | | | | * | * | ### Plugin removal Removing plugins previously added in your `.upsun/config.yaml` file doesn't automatically uninstall them from your Elasticsearch instances. This is deliberate, as removing a plugin may result in data loss or corruption of existing data that relied on that plugin. Removing a plugin usually requires reindexing. To permanently remove a previously enabled plugin, [upgrade the service](#upgrading) to create a new instance of Elasticsearch and migrate to it. In most cases it isn't necessary as an unused plugin has no appreciable impact on the server. ## Upgrading The Elasticsearch data format sometimes changes between versions in incompatible ways. Elasticsearch doesn't include a data upgrade mechanism as it's expected that all indexes can be regenerated from stable data if needed. To upgrade (or downgrade) Elasticsearch, use a new service from scratch. There are two ways to do so. ### Destructive In your `.upsun/config.yaml` file, change the version *and* name of your Elasticsearch service. Be sure to also update the reference to the now changed service name in its corresponding application's `relationship` block. When you push that to Upsun, the old service is deleted and a new one with the new name is created with no data. You can then have your application reindex data as appropriate. This approach has the downsides of temporarily having an empty Elasticsearch instance, which your application may or may not handle gracefully, and needing to rebuild your index afterward. Depending on the size of your data that could take a while. ### Transitional With a transitional approach, you temporarily have two Elasticsearch services. Add a second Elasticsearch service with the new version, a new name, and give it a new relationship in `.upsun/config.yaml`. You can optionally run in that configuration for a while to allow your application to populate indexes in the new service as well. Once you're ready to switch over, remove the old Elasticsearch service and relationship. You may optionally have the new Elasticsearch service use the old relationship name if that's easier for your app to handle. Your application is now using the new Elasticsearch service. This approach has the benefit of never being without a working Elasticsearch instance. On the downside, it requires two running Elasticsearch servers temporarily, each of which consumes resources and needs adequate disk space. Depending on the size of your data, that may be a lot of disk space. --- # Source: https://docs.upsun.com/languages/elixir.md # Elixir p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. Upsun supports building and deploying applications written in Elixir. There is no default flavor for the build phase, but you can define it explicitly in your build hook. Upsun Elixir images support both committed dependencies and download-on-demand. The underlying Erlang version is 22.0.7. ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 1.18 - 1.15 ### Specify the language To use Elixir, specify `elixir` as your [app's `type`](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#types): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. : type: 'elixir:' ``` For example: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'elixir:1.18' ``` ## Built-in variables Upsun exposes relationships and other configuration as [environment variables](https://docs.upsun.com../development/variables.md). Most notably, it allows a program to determine at runtime what HTTP port it should listen on and what the credentials are to access [other services](https://docs.upsun.com../add-services.md). To get the `PORT` environment variable (the port on which your web application is supposed to listen) you would: ```elixir String.to_integer(System.get_env("PORT") || "8888") ``` Some of the environment variables are in JSON format and are base64 encoded. You would need to import a JSON parsing library such as [JSON](https://hexdocs.pm/json/readme.md) or [Poison](https://hexdocs.pm/poison/api-reference.md) to read those. (There is an example for doing this to decode the `PLATFORM_RELATIONSHIPS` environment variable in the section [below](#accessing-services-manually).) **Tip**: Remember ``config/prod.exs`` is evaluated at **build time** and has no access to runtime configuration. Use ``config/releases.exs`` to configure your runtime environment. ## Building and running the application If you are using Hex to manage your dependencies, you need to specify the `MIX_ENV` environment variable: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'elixir:1.18' variables: env: MIX_ENV: 'prod' ``` The `SECRET_KEY_BASE` variable is generated automatically based on the [`PLATFORM_PROJECT_ENTROPY` variable](https://docs.upsun.com../development/variables/use-variables.md#use-provided-variables). You can change it. Include in your build hook the steps to retrieve a local Hex and `rebar`, and then run `mix do deps.get, deps.compile, compile` on your application to build a binary. ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'elixir:1.18' hooks: build: | mix local.hex --force mix local.rebar --force mix do deps.get --only prod, deps.compile, compile ``` **Note**: That build hook works for most cases and assumes that your ``mix.exs`` file is located at [your app root](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory). Assuming `mix.exs` is present at your app root and your build hook matches the above, you can then start it from the `web.commands.start` directive. The following basic app configuration is sufficient to run most Elixir applications. ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'elixir:1.18' variables: env: MIX_ENV: 'prod' hooks: build: | mix local.hex --force mix local.rebar --force mix do deps.get --only prod, deps.compile, compile web: commands: start: mix phx.server locations: /: allow: false passthru: true ``` Note that there is still an Nginx proxy server sitting in front of your application. If desired, certain paths may be served directly by Nginx without hitting your application (for static files, primarily) or you may route all requests to the Elixir application unconditionally, as in the example above. ## Dependencies The recommended way to handle Elixir dependencies on Upsun is using Hex. You can commit a `mix.exs` file in your repository and the system downloads the dependencies in your `deps` section using the build hook above. ```elixir defp deps do [ {:platformshconfig, "~> 0.1.0"} ] end ``` ## Accessing Services You can access service credentials to connect to [managed services](https://docs.upsun.com/add-services/) from environment variables present in the application container. Consult each of the individual service documentation to see how to retrieve and surface credentials into your application. - [Chroma](https://docs.upsun.com/add-services/chroma.md#3-use-the-relationship-in-your-application) - [ClickHouse](https://docs.upsun.com/add-services/clickhouse.md#usage-example) - [Elasticsearch](https://docs.upsun.com/add-services/elasticsearch.md#use-in-app) - [Edgee (Edge Analytics)](https://docs.upsun.com/add-services/edgee.md#setup-edgee) - [Gotenberg](https://docs.upsun.com/add-services/gotenberg.md#usage-example) - [Headless Chrome](https://docs.upsun.com/add-services/headless-chrome.md#use-in-app) - [InfluxDB](https://docs.upsun.com/add-services/influxdb.md#use-in-app) - [Kafka](https://docs.upsun.com/add-services/kafka.md#use-in-app) - [MariaDB/MySQL](https://docs.upsun.com/add-services/mysql.md#use-in-app) - [Memcached](https://docs.upsun.com/add-services/memcached.md#use-in-app) - [Mercure](https://docs.upsun.com/add-services/mercure.md#use-in-app) - [MongoDB](https://docs.upsun.com/add-services/mongodb.md#use-in-app) - [Network Storage](https://docs.upsun.com/add-services/network-storage.md#usage-example) - [OpenSearch](https://docs.upsun.com/add-services/opensearch.md#use-in-app) - [PostgreSQL](https://docs.upsun.com/add-services/postgresql.md#use-in-app) - [Qdrant](https://docs.upsun.com/add-services/qdrant.md#4-use-the-relationship-in-your-application) - [RabbitMQ](https://docs.upsun.com/add-services/rabbitmq.md#use-in-app) - [Redis](https://docs.upsun.com/add-services/redis.md#use-in-app) - [Solr](https://docs.upsun.com/add-services/solr.md#use-in-app) - [Valkey](https://docs.upsun.com/add-services/valkey.md#use-in-app) - [Varnish](https://docs.upsun.com/add-services/varnish.md#usage-example) - [Vault KMS](https://docs.upsun.com/add-services/vault.md#use-vault-kms) ### Accessing Services Manually The services configuration is available in the environment variable `PLATFORM_RELATIONSHIPS`. Given a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) defined in `.upsun/config.yaml`: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'elixir:1.18' [...] # Relationships enable an app container's access to a service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: postgresql: ``` Assuming you have in `mix.exs` the Poison library to parse JSON: ```elixir defp deps do [ {:poison, "~> 3.0"} ] end ``` And assuming you use `ecto` you could put in `config/config.exs`: ```elixir relationships = Poison.decode!(Base.decode64!(System.get_env("PLATFORM_RELATIONSHIPS"))) [postgresql_config | _tail] = relationships["postgresql"] config :my_app, Repo, database: postgresql_config["path"], username: postgresql_config["username"], password: postgresql_config["password"], hostname: postgresql_config["host"] ``` and setup Ecto during the deploy hook: ```yaml {location=".upsun/config.yaml"} applications: myapp: hooks: deploy: | mix do ecto.setup ``` ## View application instance details {#view-application-instance-details} To understand how an application's instances are distributed, you can view the instance details in the project's `/run/peers.json` file. To learn more, see [View application instance details](https://docs.upsun.com/manage-resources/adjust-resources.md#view-application-instance-details) in the "Resource configuration" topic. --- # Source: https://docs.upsun.com/development/email.md # Send email You can configure your Upsun environments to send emails via an SMTP proxy. Emails aren't guaranteed to be deliverable and you can't white-label them. The SMTP proxy is intended as a zero-configuration, best-effort service. **Note**: All preview environments are limited to 12,000 email credits per calendar month. ## 1. Turn on outgoing email You can turn on outgoing email for each environment. By default, email is turned on for your Production environment and blocked for other environments. To turn it on for a specific environment, follow these steps: To turn on outgoing email, run the following command: ```bash {} upsun environment:info --environment enable_smtp true ``` To turn off outgoing email, replace ``true`` with ``false``. Changing the setting rebuilds the environment. ## 2. Recommended: Improve deliverability Improve deliverability of your email with [Sender Policy Framework (SPF)](https://www.twilio.com/docs/sendgrid/glossary/spf). If you don't have an SPF record, add the following `TXT` record to your domain's DNS records: ```txt v=spf1 include:sendgrid.net -all ``` Having several, conflicting `TXT` records isn't supported due to [rfc4408 section 3.1.2](https://datatracker.ietf.org/doc/html/rfc4408#section-3.1.2). If you already have an SPF record, please add SendGrid into your existing record. ## 3. (Optional) Validate your email You can request for DomainKeys Identified Mail (DKIM) to be enabled on your domain. DKIM improves your delivery rate as an email sender. Learn more about [how DKIM works](https://www.twilio.com/docs/sendgrid/glossary/dkim). To have DKIM enabled for your domain: 1. Open a [support ticket](https://docs.upsun.com/learn/overview/get-support.md) with the domain where you want DKIM. 2. Update your DNS configuration with the `CNAME` and `TXT` records that you get in the ticket. Checks for the expected DNS records run every 15 minutes before validation. The `TXT` record looks similar to the following: ```txt v=spf1 include:u17504801.wl.sendgrid.net -all ``` ## 4. Test the email service To test the email service, use the [CLI](https://docs.upsun.com../administration/cli.md) to connect to your app by running `upsun ssh`. Run the following command: ```bash printf "From: \nSubject: Test \nThis is a test message" | /usr/sbin/sendmail ``` Replace the variables with actual email addresses as in the following example: ```bash printf "From: someone@example.com\nSubject: Test \nThis is a test message" | /usr/sbin/sendmail someone@example.net ``` In a little while, the test message should arrive at the recipient address. **Note**: When sending emails from your project, **use a mail address that is on the same domain as your project** otherwise it will be flagged as spoofing attempt and not be sent. Also, **make sure to test with real email addresses**. If you send emails to fake domains (such as ``example.com``), they fail and hurt your sending reputation. Make sure your test emails are deliverable. ## 5. Send email from your app You can use `/usr/sbin/sendmail` on your app container to send emails as with the example in the previous step. Or use the `PLATFORM_SMTP_HOST` environment variable in your SMTP configuration. When outgoing emails are on, `PLATFORM_SMTP_HOST` is the address of the SMTP host that should be used. When outgoing emails are off, the variable is empty. When using `PLATFORM_SMTP_HOST`, send email through port 25 (often the default). Your emails are proxied through the Upsun SMTP host and encrypted over port 465 before being sent to the outside world. The precise way to send email depends on the language and framework you use. See some examples for given languages. JavaMail is a Java API used to send and receive email via SMTP, POP3, and IMAP. JavaMail is built into the [Jakarta EE](https://jakarta.ee/) platform, but also provides an optional package for use in Java SE. [Jakarta Mail](https://projects.eclipse.org/projects/ee4j.mail) defines a platform-independent and protocol-independent framework to build mail and messaging applications. The following example sends email using Jakarta Mail: ```java {} import sh.platform.config.Config; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; public class JavaEmailSender { private static final Logger LOGGER = Logger.getLogger(JavaEmailSender.class.getName()); public void send() { Config config = new Config(); String to = "";//change accordingly String from = "";//change accordingly String host = config.getSmtpHost(); //or IP address //Get the session object Properties properties = System.getProperties(); properties.setProperty("mail.smtp.host", host); Session session = Session.getDefaultInstance(properties); //compose the message try { MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress(from)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); message.setSubject("Ping"); message.setText("Hello, this is example of sending email "); // Send message Transport.send(message); System.out.println("message sent successfully...."); } catch (MessagingException exp) { exp.printStackTrace(); LOGGER.log(Level.SEVERE, "there is an error to send an message", exp); } } } ``` Guides on using JavaMail: - [Send email with HTML formatting and attachments](https://mkyong.com/java/java-how-to-send-email/) - [JavaMail API](https://javaee.github.io/javamail/) ## Alternative: Use a different email server If you need more options, use your own SMTP server or email delivery service provider. Bear in mind that TCP port 25 is blocked for security reasons. Use port 465 or 587 instead to send email to your own external email server. --- # Source: https://docs.upsun.com/environments.md # Manage Upsun Fixed environments An Upsun environment contains one instance of an app (or [group of apps](https://docs.upsun.com../create-apps/multi-app.md)) with all the services needed for it to run. Each project can include multiple environments, often divided into [environment types](https://docs.upsun.com../administration/users.md#environment-type-roles). If you have a live site, you have at least a production environment. You may also have additional environments of the Staging or Development [environment type](https://docs.upsun.com../administration/users.md#environment-type-roles), but there will only ever be one production environment. You can think of other environments as copies of your live site where you can run tests without worrying about damaging anything in production. Once you have completed your tests, you can merge your changes so that they're instantly and seamlessly deployed to production. You can create environments for development, testing, staging, review, and so on. To organize your environments, you can create [hierarchical relationships](#hierarchy). ## Create environments You can create new environments in one of two ways: - Push a local branch through Git or a [source integration](https://docs.upsun.com../integrations/source.md). - [Branch](https://docs.upsun.com/glossary.md#branch) existing environments using the [CLI](https://docs.upsun.com/administration/cli.md) or the [Console](https://docs.upsun.com../administration/web.md). When you branch an environment, you might want to create exact replicas of it. In this case, each new environment inherits all of the data and services from its parent environment. This includes databases, network storage, queues, and routing configurations. You can create Upsun environments on demand. Each environment is tied to a Git branch. If you use a source integration, you can even have environments created automatically for your pull requests and branches. You can also have branches that aren't tied to a running instance of your application. These are called [inactive environments](#environment-status). ## Default environment Your default environment comes from your default branch and is a [production environment](https://docs.upsun.com../administration/users.md#environment-type-roles). Your project must have a default environment, but you can [name it as you want](https://docs.upsun.com/environments/default-environment.md). This environment is your **live site**. You might want to give it a [custom domain name](https://docs.upsun.com../domains/steps.md). ## Environment status Your environments can have one of three statuses: - [Active](https://docs.upsun.com/glossary.md#active-environment): A deployed environment with services and data. - [Inactive](https://docs.upsun.com/glossary.md#inactive-environment): An environment that isn't deployed and has no services or data, only code. - [Paused](#paused-environments): An environment that hasn't been redeployed in 14 days or longer. You can see the status of your environments in the [Console](https://docs.upsun.com../administration/web.md) or the [CLI](https://docs.upsun.com/administration/cli.md). To check the status of all your environments, from your project directory run the ``upsun environments`` command. You can [change an environment's status](https://docs.upsun.com/environments/deactivate-environment.md) at any time. ## Organize your environments ### Hierarchy ![Environment hierarchy](https://docs.upsun.com/images/management-console/environments.png "0.5") In Upsun, your environments are organized in a hierarchy featuring parent and child environments. When you [branch](https://docs.upsun.com/glossary.md#branch) an environment, the parent of the new environment is the environment it was created from. You can [change the environment's parent](https://docs.upsun.com/environments/change-parent.md) after it's been created. When you push a branch through Git or a [source integration](https://docs.upsun.com../integrations/source.md), the parent environment of the new environment is your [default environment](#default-environment). Alternatively, you can [change the environment's parent](https://docs.upsun.com/environments/change-parent.md) after it's been created. Each child environment can [sync](https://docs.upsun.com/glossary.md#sync) code and/or data down from its parent and [merge](https://docs.upsun.com/glossary.md#merge) code up to its parent. You can use child environments for development, staging, and testing. ### Workflows Since you can customize your [environment hierarchy](#hierarchy), you can create your own workflows. You can decide which structure best fits your needs. #### Possible approaches You may want to take one of the following approaches when creating your workflows: - **Agile**: A child environment per sprint. Each story in the sprint can have its own environment as a child of the sprint environment. - **Developer-centric**: One QA environment and a few preview environments (*per developer*, *per task*, or similar). - **Testing**: An operational test environment, a user test environment, and a few unit test environments. - **Hotfix**: One environment for each bug, security issue, or hotfix that needs deployment. #### Example workflow Example Agile workflow: 1. An admin [branches](https://docs.upsun.com/glossary.md#branch) the Live (default) environment to create a Sprint environment. 2. The admin gives each developer permission to branch the Sprint environment to create new feature environments. ![Agile branches with Live as the top parent, Sprint 1 as a child, and Feature 1 and Feature 2 as children of Sprint](https://docs.upsun.com/images/workflow/branches.svg "0.2") 3. Feature 1 is developed and work is reviewed by accessing the deployed Feature 1 environment. 4. When the review is done, Feature 1 is [merged](https://docs.upsun.com/glossary.md#merge) into the Sprint environment. ![Feature 1 is merged into the Sprint 1 environment](https://docs.upsun.com/images/workflow/merge-feature.svg "0.25") 5. The remaining features [sync](https://docs.upsun.com/glossary.md#sync) with the Sprint environment. This ensures their working environment is up-to-date with the latest code. ![Features from the Sprint 1 environment are synced with the Feature 2 environment](https://docs.upsun.com/images/workflow/sync.svg "0.25") 6. When the sprint is complete and all features merged into the Sprint environment, the admin makes a backup of the live site. 7. The admin merges the Sprint environment into the Live environment. ![Features from the Sprint 1 environment are merged into the Live environment](https://docs.upsun.com/images/workflow/merge-live.svg "0.2") 8. The admin syncs the next sprint's environment with the Live environment to repeat and continue the development process. ![Features from the Live environment are synced with the Sprint 2 environment](https://docs.upsun.com/images/workflow/sync-live.svg "0.2") ### Naming conventions You can organize and work with your preview environments in many different ways. It can help to introduce a convention for how you name and structure your environments. For each environment, choose a name that represents what the environment is for. If you use Agile, for example, you can adopt a naming convention similar to the following: ```text {no-copy="true"} Live Sprint1 Feature1 Feature2 Feature3 Sprint2 Feature1 Feature2 ``` If you prefer splitting your environments per developer and having a specific environment for each task or ticket, you can adopt a naming convention similar to the following: ```text {no-copy="true"} Staging Developer1 Ticket-526 Ticket-593 Developer2 Ticket-395 ``` ## Paused environments [Preview environments](https://docs.upsun.com/glossary.md#preview-environment) are often used for a limited time and then abandoned. To prevent unnecessary consumption of resources, Upsun automatically pauses preview environments ([of both development and staging types](https://docs.upsun.com/glossary.md#environment-type)) that haven't been redeployed in 14 days. You can pause (and resume) an environment manually at any time. ### Pause an environment To pause an environment, follow these steps: - Navigate to your project and click Settings **Settings**. - Under **Environments**, select the environment you want to pause. - In the **General** tab, click **Pause environment**. ### Resume a paused environment Pushing new code or redeploying a paused environment automatically resumes it. You can also resume it manually at any time. - Navigate to the paused environment. - In the Activity tab, click **Resume environment**. - In the **Resume environment** window, click **Resume**. The environment is redeployed and becomes available for use again. ## Push options Git provides push options to pass a string to the server (see [the official Git documentation](https://git-scm.com/docs/git-push#Documentation/git-push.txt--oltoptiongt)). Upsun supports some of these push options, which allows you to push changes to your environment and trigger the following actions at the same time: | Action | Command | |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ----------------------------------------------------------------------------------------------------------------------- | | Activate the environment | `git push upsun -o "environment.status=active"` | | Set a title for the environment | `git push upsun -o "environment.title="` | | Set the parent environment | `git push upsun -o "environment.parent="` | | Clone the data from the parent environment | `git push upsun -o "environment.clone_parent_on_create=True"` | | Disable the cloning of the data from the parent environment | `git push upsun -o "environment.clone_parent_on_create=False"` | | Set the environment type (`development`, `staging`, or `production`) | `git push upsun -o "environment.type="` | | Define a [resource initialization strategy](https://docs.upsun.com/manage-resources/resource-init.md#specify-a-resource-initialization-strategy) (`default`, `manual`, `minimum`, or `parent`) | `git push upsun -o "resources.init="` | If your remote location isn't named `upsun`, make sure you adjust the commands accordingly. **Note**: You can’t use push options if you have a [source integration](https://docs.upsun.com/integrations/source.md) set up. The following example shows how, through a single `push`, you can activate your environment, set a title for it, set a parent environment for it, and clone the data from its parent into it. ```bash {location="Terminal"} git push upsun -o "environment.status=active" -o "environment.title=my-environment-title" -o "environment.parent=my-parent-environment" -o "environment.clone_parent_on_create=True" ``` --- # Source: https://docs.upsun.com/learn/tutorials/exporting.md # Exporting data As an Upsun user, your code and data belong to you. At any time, you can download your site's data for local development, to back up your data, or to change provider. ## Before you begin You need: - [Git](https://git-scm.com/downloads) - An Upsun account - Code in your project - Optional: the [Upsun CLI](https://docs.upsun.com/administration/cli.md) ## 1. Download your app's code Your app's code is maintained through the Git version control system. To download your entire app's code history: - Retrieve the project you want to back up by running the following command: ```bash {} upsun get ``` - In the [Console](https://console.upsun.com/), open your project and click **Code **. - Click **Git**. - To copy the command, click ** Copy**. The command is similar to the following: ```text {} git clone abcdefgh1234567@git.eu.upsun.com:abcdefgh1234567.git project-name ``` ## 2. Download your files Some files might not be stored in Git, such as data your app writes [in mounts](https://docs.upsun.com/create-apps/image-properties/mounts.md). You can download your files [using the CLI](https://docs.upsun.com/development/file-transfer.md#transfer-files-using-the-cli) or [using SSH](https://docs.upsun.com/development/file-transfer.md#transfer-files-using-an-ssh-client). ## 3. Download data from services The mechanism for downloading from each service (such as your database) varies. For services designed to hold non-persistent data, such as [Redis](https://docs.upsun.com/add-services/redis.md) or [Solr](https://docs.upsun.com/add-services/solr.md), it's generally not necessary to download data as it can be rebuilt from the primary data store. For services designed to hold persistent data, see each service's page for instructions: - [MySQL](https://docs.upsun.com/add-services/mysql.md#exporting-data) - [PostgreSQL](https://docs.upsun.com/add-services/postgresql.md#exporting-data) - [MongoDB](https://docs.upsun.com/add-services/mongodb.md#exporting-data) - [InfluxDB](https://docs.upsun.com/add-services/influxdb.md#export-data) ## 4. Get environment variables Environment variables can contain critical information such as tokens or additional configuration options for your app. Environment variables can have different prefixes: - Variables beginning with `env:` are exposed [as Unix environment variables](https://docs.upsun.com/development/variables.md#top-level-environment-variables). - Variables beginning with `php:` are interpreted [as `php.ini` directives](https://docs.upsun.com/development/variables.md#php-specific-variables). All other variables are [part of `$PLATFORM_VARIABLES`](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). To back up your environment variables: Note that you can also get all the environment variable values by running the following command: ```bash {} upsun ssh -- env ``` - Store the data somewhere secure on your computer. - In the [Console](https://console.upsun.com/), open your project and click **Settings**. - Click **Project Settings **. - Click **Variables** and access your variable’s values and settings. - Store the data somewhere secure on your computer. Note that in the Console, you can’t access the value of variables that have been [marked as sensitive](https://docs.upsun.com/development/variables/set-variables.md#variable-options). Use the CLI to retrieve these values. ## What's next - Migrate data from elsewhere [into Upsun](https://docs.upsun.com/learn/tutorials/migrating.md). - Migrate to [another region](https://docs.upsun.com/projects/region-migration.md). - To use data from an environment locally, export your data and set up your [local development environment](https://docs.upsun.com/development/local.md). --- # Source: https://docs.upsun.com/languages/php/extensions.md # Extensions **Note**: You can use the [Upsun composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) to install multiple runtimes and tools in your application container. When using the composable image, see how you can: - [Manage PHP extensions](https://docs.upsun.com/create-apps/app-reference/composable-image.md#php-extensions-and-python-packages) - [Modify your PHP runtime](https://docs.upsun.com/languages/php.md#modify-your-php-runtime-when-using-the-composable-image) PHP has a number of [extensions](https://pecl.php.net/) developed by members of the community. Some of them are available for Upsun containers. You can define the PHP extensions you want to enable or disable: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'php:8.5' runtime: extensions: - raphf - http - igbinary - redis disabled_extensions: - sqlite3 ``` You can also [include configuration options](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#extensions) for specific extensions. The following table shows all extensions that are available (Avail) and on by default (Def). You can turn on the available ones with the `extensions` key and turn off those on by default with the `disabled_extensions` key. (Extensions marked with `*` are built in and can't be turned off.) | Extension | 5.4 | 5.5 | 5.6 | 7.0 | 7.1 | 7.2 | 7.3 | 7.4 | 8.0 | 8.1 | 8.2 | 8.3 | 8.4 | 8.5 | | ``amqp`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``apc`` | Avail | ``apcu`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``apcu_bc`` | Avail Avail Avail Avail Avail | ``applepay`` | Avail Avail Avail Avail | ``bcmath`` | Def Def Def Def Def Def Def Def Def Def Def | ``blackfire`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``bz2`` | Avail Def Def Def Def Def Def Def Def Def Def | ``calendar`` | Def Def Def Def Def Def Def Def Def Def Def | ``ctype`` | Def Def Def Def Def Def Def Def Def Def Def | ``curl`` | Def Def Def Def Def Def Def Def Def Def Def Def Def Def | ``datadog-profiling`` | Avail Avail Avail Avail | ``dba`` | Def Def Def Def Def Def Def Def Def Def Def | ``dom`` | Def Def Def Def Def Def Def Def Def Def Def | ``enchant`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``event`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``exif`` | Def Def Def Def Def Def Def Def Def Def Def | ``ffi`` | Avail Avail Avail Avail Avail Avail Avail | ``fileinfo`` | Def Def Def Def Def Def Def Def Def Def Def | ``ftp`` | Def Def Def Def Def Def Def Def Def Def Def | ``gd`` | Def Def Def Def Def Def Def Def Def Def Def Def Def Def | ``gearman`` | Avail Avail Avail | ``geoip`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``gettext`` | Def Def Def Def Def Def Def Def Def Def Def | ``gmp`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``gnupg`` | Avail Avail Avail Avail Avail Avail | ``grpc`` | Avail | ``http`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``iconv`` | Def Def Def Def Def Def Def Def Def Def Def | ``igbinary`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``imagick`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail with``webp`` Avail with``webp`` Avail with``webp`` Avail with``webp`` Avail with``webp`` Avail with``webp`` | ``imap`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``interbase`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``intl`` | Def Def Def Def Def Def Def Def Def Def Def Def Def Def | ``ioncube`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``json`` | Avail Def Def Def Def Def Def * * * * * * | ``ldap`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``mailparse`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``mbstring`` | Def Def Def Def Def Def Def Def Def Def Def | ``mcrypt`` | Def Def Def Avail Avail | ``memcache`` | Avail Avail Avail | ``memcached`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``mongo`` | Avail Avail Avail | ``mongodb`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``msgpack`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``mssql`` | Avail Avail Avail | ``mysql`` | Def Def Def | ``mysqli`` | Def Def Def Def Def Def Def Def Def Def Def Def Def Def | ``mysqlnd`` | Def Def Def Def Def Def Def Def Def Def Def Def Def Def | ``newrelic`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``oauth`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``odbc`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``opcache`` | Def * * * * * * * * * * * * * | ``openswoole`` | Avail Avail Avail | ``opentelemetry`` | Avail Avail Avail Avail | ``pdo`` | Def Def Def Def Def Def Def Def Def Def Def Def Def Def | ``pdo_dblib`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``pdo_firebird`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``pdo_mysql`` | Def Def Def Def Def Def Def Def Def Def Def Def Def Def | ``pdo_odbc`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``pdo_pgsql`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``pdo_sqlite`` | Def Def Def Def Def Def Def Def Def Def Def Def Def Def | ``pdo_sqlsrv`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``pecl-http`` | Avail Avail | ``pgsql`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``phar`` | Def Def Def Def Def Def Def Def Def Def Def | ``pinba`` | Avail Avail Avail | ``posix`` | Def Def Def Def Def Def Def Def Def Def Def | ``propro`` | Avail Avail Avail | ``protobuf`` | Avail Avail Avail Avail Avail | ``pspell`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``raphf`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``rdkafka`` | Avail Avail Avail Avail Avail | ``readline`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``recode`` | Avail Avail Avail Avail Avail Avail Avail | ``redis`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``shmop`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``simplexml`` | Def Def Def Def Def Def Def Def Def Def Def | ``snmp`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``soap`` | Def Def Def Def Def Def Def Def Def Def Def | ``sockets`` | Def Def Def Def Def Def Def Def Def Def Def | ``sodium`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``sourceguardian`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``spplus`` | Avail Avail | ``sqlite3`` | Def Def Def Def Def Def Def Def Def Def Def Def Def Def | ``sqlsrv`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``ssh2`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``swoole`` | Avail Avail Avail | ``sybase`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``sysvmsg`` | Def Def Def Def Def Def Def Def Def Def Def | ``sysvsem`` | Def Def Def Def Def Def Def Def Def Def Def | ``sysvshm`` | Def Def Def Def Def Def Def Def Def Def Def | ``tideways`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``tideways_xhprof`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``tidy`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``tokenizer`` | Def Def Def Def Def Def Def Def Def Def Def | ``uuid`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``uv`` | Avail Avail | ``wddx`` | Avail Avail Avail Avail | ``xcache`` | Avail Avail | ``xdebug`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``xhprof`` | Avail Avail Avail | ``xml`` | Def Def Def Def Def Def Def Def Def Def Def | ``xmlreader`` | Def Def Def Def Def Def Def Def Def Def Def | ``xmlrpc`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``xmlwriter`` | Def Def Def Def Def Def Def Def Def Def Def | ``xsl`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``yaml`` | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail | ``zbarcode`` | Avail Avail Avail Avail | ``zip`` | Def Def Def Def Def Def Def Def Def Def Def Some built-in modules are always on: - `date` - `filter` - `hash` - `json` (from 8.0) - `libxml` - `openssl` - `pcntl` - `pcre` - `Reflection` - `session` - `SPL` - `standard` - `Zend OPcache` (from 5.5) - `zlib` To see a complete list of the compiled PHP extensions, run the following [CLI command](https://docs.upsun.com../../administration/cli/_index.md): ```bash upsun ssh "php -m" ``` ## Custom PHP extensions It's possible to use an extension not listed here, but it takes slightly more work: 1. Download the `.so` file for the extension as part of your build hook using `curl` or similar. It can also be added to your Git repository if the file isn't publicly downloadable, but committing large binary blobs to Git is generally not recommended. 2. Load the extension using an absolute path by [customizing the PHP settings](https://docs.upsun.com/languages/php.md#customize-php-settings) For example, if the extension is named `spiffy.so` and is in your [app root](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory), your configuration looks like the following: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'php:8.5' variables: php: extension: /app/spiffy.so ``` --- # Source: https://docs.upsun.com/integrations/fastly-cdn.md # Fastly CDN The Fastly CDN integration provides a centralized interface within the Upsun Console to oversee your edge traffic, manage cache, edit access control lists (ACLs), and tune performance without switching platforms. You can also manage dynamic configuration by using Edge Dictionaries. ## Install the Fastly CDN plugin 1. Go to https://console.upsun.com/-/add-plugin and click **Add plugin**. 1. Enter the plugin manifest URL https://fastsun.plugins.pltfrm.sh/manifest.json and click **Create**. **Tip:** You can also [click here](https://console.upsun.com/-/add-plugin?manifest=https%253A%252F%252Ffastsun.plugins.pltfrm.sh%252Fmanifest.json) to install directly in the Upsun console. ## Manage and monitor your CDN traffic The Fastly CDN integration provides a centralized interface within the Upsun Console to oversee your edge traffic, manage cache, and tune performance without switching platforms. ### Access the Fastly dashboard 1. In the Upsun [console](https://console.upsun.com), navigate to the project and environment you want to monitor. **Note:** To view summarized monthly _project-level_ traffic, including CDN bandwidth and CDN requests, see the **Traffic this month** section of a project page (make sure no environment is selected). 1. On the **Fastly CDN** tab, log in with your Fastly credentials (Service ID and API token). - If you have a Fastly subscription, you can retrieve your credentials directly from the Fastly interface. - If you purchased Fastly through Upsun, you can retrieve your credentials by running `upsun ssh "printenv | grep FASTLY"` in your terminal, or by [opening a support ticket](https://console.upsun.com/-/users/~/tickets/open). Your Fastly credentials are stored securely within your browser and are never transmitted to Upsun. ### Track real-time and historical performance The dashboard provides two levels of visibility into how your site is performing at the edge: - **Real-time metrics:** Monitor current traffic spikes, request rates, and global delivery status as it happens. - **Historical metrics:** Use the date picker to analyze trends over weeks or months. You can toggle specific metrics on the graph to isolate data like cache hit ratios, 4xx/5xx error rates, and total bandwidth. The image below shows a sample historical metrics tab for a selected environment: ![Image showing the Fastly CDN historical metrics tab in the Upsun console](https://docs.upsun.com/images/integrations/console-fastly.png "0.75") ## Manage dynamic configuration with Edge Dictionaries Edge Dictionaries allow you to store key-value pairs at the CDN level to control site behavior in real-time. This integration enables you to update configurations (such as feature flags, redirects, or header values) instantly, without a full code redeploy or VCL version change. This can be helpful, for example, to block a bot attack or quickly update a site banner. With this integration, you can: - **Update instantly:** Add, edit, or delete items via the UI or API for immediate effect. - **Secure secrets:** Use write-only dictionaries to store sensitive API keys that are accessible to your logic but hidden from view. - **Maintain consistency:** Leverage built-in validation and a management workflow that mirrors Fastly ACLs. ### Example: Use a Dictionary for a maintenance toggle Instead of hard-coding a maintenance mode in your application, you can use an Edge Dictionary (for example, named `site_config`) to toggle a "Maintenance Mode" page at the edge. 1. Define the dictionary: Create a dictionary named `site_config` and add a `maintenance_enabled` key with a value of `true` or `false`. 1. Add the VCL Logic: Add the following snippet to your Fastly configuration to check the dictionary value on every request: ``` sub vcl_recv { # Check if the 'maintenance_enabled' key is set to 'true' in the dictionary if (table.lookup(site_config, "maintenance_enabled") == "true") { # Send a 503 Service Unavailable response immediately error 601 "Maintenance"; } } sub vcl_error { if (obj.status == 601) { set obj.status = 503; set obj.response = "Service Unavailable"; synthetic {" We'll be back soon! Our site is currently undergoing scheduled maintenance. "}; return(deliver); } } ``` Related information: - [How to create a custom maintenance page in Fastly](https://devcenter.upsun.com/posts/fastly-maintenance/#create-fastly-configuration) - this Upsun Dev Center article also describes how to create a Fastly configuration. - [Fastly Next-Gen Web Application Firewall (WAF)](https://docs.upsun.com/security/fastly-waf.md) --- # Source: https://docs.upsun.com/domains/cdn/fastly.md # Set up your Fastly CDN You can [use a CDN](https://docs.upsun.com/domains/cdn.md) to deliver your site's content to users more quickly. To set up a Fastly CDN with your own Fastly subscription, follow the instructions on this page. ## Before you begin You need: - An up-and-running Upsun project - A [Fastly](https://www.fastly.com/) CDN subscription ## 1. Avoid double-caching To avoid stale content that can't be cleared, avoid using Fastly with [HTTP caching](https://docs.upsun.com/define-routes/cache.md). For routes where Fastly is used, disable HTTP caching using the following configuration: ```yaml {location=".upsun/config.yaml"} https://{default}/: type: upstream ... cache: enabled: false ``` ## 2. Set up your Fastly CDN To properly configure your Fastly CDN, see the Fastly official documentation on [how to get started](https://docs.fastly.com/en/guides/getting-started#_basics). Then set up a [custom domain](https://docs.upsun.com../steps.md). To get the [DNS challenge to succeed](https://docs.upsun.com../troubleshoot.md#ownership-verification), have your CDN point to your [project's target URL](https://docs.upsun.com../../domains/steps.md#1-get-the-target-for-your-project). ## 3. Handle apex domains To start routing client traffic through Fastly, [create `CNAME` records for your domain names](https://docs.upsun.com../../domains/steps/dns.md) through your DNS provider. `CNAME` records can't point to apex domains. As a workaround, Fastly offers [Anycast options](https://docs.fastly.com/en/guides/using-fastly-with-apex-domains). ## 4. Optional: Protect your site from on-path attacks An on-path attack occurs when a hacker intercepts or modifies the communication between a client and a server. This can lead to sensitive data leaks. To prevent such attacks, make sure all communication with your site is encrypted through HTTPS and can't be downgraded to HTTP. To do so, enable HTTP strict transport security (HSTS). HSTS forces clients to always communicate with your site over HTTPS. You can [enable HSTS](https://docs.fastly.com/en/guides/enabling-hsts-through-fastly#forcing-tls-and-enabling-hsts) in your Fastly account. All HTTP requests are then automatically redirected to HTTPS. --- # Source: https://docs.upsun.com/development/file-transfer.md # Transfer files to and from your app After your app is built, its file system is read-only. This means that the only way you can edit your app's code is through Git. However, you can transfer files to and from your built app without using Git. To do so, you need to configure mounts or use an SSH client. [Mounts](https://docs.upsun.com/create-apps/image-properties/mounts.md) let you set up directories that remain writable after the build is complete. You can then transfer files directly to and from mounts inside your app with a single command via the [Upsun CLI](https://docs.upsun.com../administration/cli.md). Alternatively, you can transfer files to and from your built app using an SSH client such as `scp` or `rsync`. ## Transfer files using the CLI ### View the mounts inside your app Before you start transferring files, you may want to view a list of all the mounts inside your app. To do so, run the following command: ```bash upsun mounts ``` The output is similar to the following: ```bash Mounts on abcdefgh1234567-main-abcd123--app@ssh.eu.upsun.com: +-------------------------+----------------------+ | Mount path | Definition | +-------------------------+----------------------+ | web/sites/default/files | source: storage | | | source_path: files | | private | source: storage | | | source_path: private | | tmp | source: tmp | | | source_path: temp | +-------------------------+----------------------+ ``` ### Transfer a file to a mount To transfer a file to a mount using the CLI, you can use the `mount:upload` command. For example, to upload the files contained in the local `private` directory to the `private` mount, run the following command: ```bash upsun mount:upload --mount private --source ./private ``` You get the following output: ```bash Uploading files from ./private to the remote mount private Are you sure you want to continue? [Y/n] sending incremental file list example.sh sent 2.35K bytes received 20 bytes 1.58K bytes/sec total size is 1.77M speedup is 745.09 ``` ### Transfer a file from a mount To transfer a file from a mount using the CLI, you can use the `mount:download` command. For example, to download a file from the `private` mount to your local `private` directory, run the following command: ```bash upsun mount:download --mount private --target ./private ``` You get the following output: ```bash Downloading files from the remote mount private to ./private Are you sure you want to continue? [Y/n] receiving incremental file list example.sh sent 2.35K bytes received 20 bytes 1.58K bytes/sec total size is 1.77M speedup is 745.09 ``` ## Transfer files using an SSH client Another way to transfer files to and from your built app is to use an SSH client such as [`scp`](file-transfer.md#scp), [`rsync`](file-transfer.md#rsync), or [`sftp`](file-transfer.md#sftp). ### scp You can use `scp` to copy files to and from a remote environment. For example, to download a `diagram.png` file from the `web/uploads` directory (relative to the [app root](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory)), run the following command: ```bash scp "$(upsun ssh --pipe)":web/uploads/diagram.png . ``` The `diagram.png` file is copied to the current local directory. To copy files from your local directory to the Upsun environment, reverse the order of the parameters: ```bash scp diagram.png "$(upsun ssh --pipe)":web/uploads ``` For other options, see the [`scp` documentation](https://www.man7.org/linux/man-pages/man1/scp.1.md). ### rsync You can use `rsync` to copy files to and from a remote environment. For example, to copy all the files in the `web/uploads` directory on the remote environment to the local `uploads` directory, run the following command: ```bash rsync -azP "$(upsun ssh --pipe)":web/uploads/ ./uploads/ ``` To copy files from your local directory to the Upsun environment, reverse the order of the parameters: ```bash rsync -azP uploads/ "$(upsun ssh --pipe)":web/uploads/ ``` Note that `rsync` is very sensitive about trailing `/` characters. If you're using UTF-8 encoded files on macOS, add the `--iconv=utf-8-mac,utf-8` flag to your `rsync` call. For more options, consult the [rsync documentation](https://man7.org/linux/man-pages/man1/rsync.1.md). ### sftp You can use `sftp` to copy files to and from a remote environment. **Note**: Upsun supports ``sftp``, but the following limitations apply: - You can only create ``sftp`` accounts with an existing Upsun user and an SSH key. Custom users and passwords aren’t supported. - ``sftp`` access cannot be limited to a specific directory. Instead, access is given to **the whole application directory** and its mounts. #### Open an `sftp` connection Run the following command: ```bash sftp "$(upsun ssh --pipe)" ``` When prompted, select the project and environment you want to connect to. The `sftp` connection is open once the `sftp>` prompt is displayed in your terminal. #### Download a file Say you want to download a `diagram.png` file from the `web/uploads` directory (relative to the [app root](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory)). To do so, run the following command: ``` sftp> get web/uploads/diagram.png ``` The `diagram.png` file is copied to the current local directory. #### Upload a file Say you want to upload a `diagram.png` file to the `web/uploads` directory (relative to the [app root](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory)). To do so, run the following command: ```bash sftp> put diagram.png web/uploads ``` For other options, see the [`sftp` documentation](https://man7.org/linux/man-pages/man1/sftp.1.md). --- # Source: https://docs.upsun.com/create-apps/image-properties/firewall.md # firewall A firewall dictionary that defines the outbound firewall rules for the application. Optional in [single-runtime](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](https://docs.upsun.com/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` | `string` array | `["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` | `string` array | | [Fully qualified domain names](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) to specify specific destinations by hostname. | | `ports` | `integer` array | | 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 {} applications: : type: 'python:3.14' source: root: "/" firewall: outbound: - ips: [ "0.0.0.0/0" ] ``` .upsun/config.yaml ```yaml {} applications: : type: "composable:25.11" source: root: "/" stack: runtimes: [ "python@3.14" ] 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 {} applications: : type: 'python:3.14' source: root: "/" firewall: outbound: - ips: [ "1.2.3.4/32" ] ports: [ 443 ] - ports: [ 80 ] ``` .upsun/config.yaml ```yaml {} applications: : type: "composable:25.11" source: root: "/" stack: runtimes: [ "python@3.14" ] 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 {} applications: : type: 'python:3.14' source: root: "/" 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 ] ``` .upsun/config.yaml ```yaml {} applications: : type: "composable:25.11" source: root: "/" stack: runtimes: [ "python@3.14" ] 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 ``` --- # Source: https://docs.upsun.com/increase-observability/logs/forward-logs.md # Forward Upsun Fixed and Blackfire logs You might use a service to analyze logs from various parts of your fleet. You might want to consolidate all your logs in one place that everyone has access to without needing to grant them access to each project individually. In such cases, forward your logs from Upsun and Blackfire to a third-party service. You can use a [service with an integration](#use-a-log-forwarding-integration) or any service that supports a [syslog endpoint](#forward-to-a-syslog-endpoint) or [HTTP endpoint](#forward-to-an-http-endpoint). To enable log forwarding in a project, you need to be a [project admin](https://docs.upsun.com../../administration/users.md). For pricing information for real-time logs forwarding, refer to the **Observability and performance monitoring** section of the [Upsun pricing page](https://upsun.com/pricing/). ### Which logs are forwarded? When log forwarding is enabled, Upsun forwards logs sent to journald. By default, Upsun sends the following logs to journald: - `stdout` and `stderr` logs from your application Note: You can configure your application to use syslog to send these (or additional) messages to journald. - MariaDB/MySQL slow query logs - Redis logs (all except command-level operations and low-level internals) Logs in files are not forwarded to journald. ## Use a log forwarding integration Certain services have a specific integration for forwarding logs. If your third-party service isn't supported, you can forward to a [syslog endpoint](#forward-to-a-syslog-endpoint). ### Integrated third-party services Upsun supports forwarding logs not only to custom remote syslog endpoints but also directly to a set of popular third‑party log management and observability services. These integrations allow you to centralize logs from applications, services, and infrastructure into your existing monitoring stack: - **[Sumo Logic](https://www.sumologic.com/)** – Cloud-based log management and analytics. - **[New Relic](https://newrelic.com/)** – Unified observability platform with logs and metrics. - **[Splunk](https://www.splunk.com/)** – Searchable log platform for monitoring and operational intelligence. - **[Datadog](https://www.datadoghq.com/)** – Observability suite with log collection and processing. - **[Loggly](https://www.loggly.com/)** – Cloud-native log monitoring, aggregation, and alerting. - **[LogDNA (Mezmo)](https://www.mezmo.com/)** – Centralized log management and analysis in real time. - **[Papertrail](https://www.papertrail.com/)** – Real-time log aggregation via syslog. - **[Logz.io](https://logz.io/)** – ELK-based log analytics and monitoring. ### Enable a log forwarding integration #### Using the CLI To enable log forwarding for a specific project using the [Upsun CLI](https://docs.upsun.com/administration/cli.md), follow the steps for your selected service. View your logs in the **Logs** dashboard. - In Splunk, get an Event Collector token on [Splunk Platform](https://docs.splunk.com/Documentation/Splunk/latest/Data/UsetheHTTPEventCollector#Create_an_Event_Collector_token_on_Splunk_Cloud_Platform) or [Splunk Enterprise](https://docs.splunk.com/Documentation/Splunk/latest/Data/UsetheHTTPEventCollector#Create_an_Event_Collector_token_on_Splunk_Enterprise). - Determine your host, which is the Splunk instance that’s collecting data. - Choose an index name. - Create the integration with the following command: ```bash {} upsun integration:add --type splunk --url https://http-inputs..splunkcloud.com/services/collector/event --index --token ``` View your logs in the **Apps->Search & Reporting** dashboard. Filter by the index name to find the relevant events. - In Sumo Logic, [configure an HTTP source](https://www.sumologic.com/help/docs/send-data/hosted-collectors/http-source/logs-metrics/#configure-an-httplogs-and-metrics-source). Make sure to copy the Source Category and collector URL. - Create the integration with the following command: ```bash {} upsun integration:add --type sumologic --url --category ``` View your logs in the **Log Search** tab. To start forwarding logs, [trigger a redeploy](https://docs.upsun.com../../development/troubleshoot.md#force-a-redeploy). #### In the Console To enable log forwarding for a specific project from the Console, follow these steps: 1. Navigate to your project. 2. Click Settings **Settings**. 3. Click **Integrations**. 4. Click **Add Integration**. 5. Select the integration you want to enable. 6. In the **Configure your integration** window, specify your configuration options. 7. Click **Add Integration**. The new integration overview is displayed, and you can view your logs in the **Activity** section. ## Forward to a syslog endpoint Syslog is a standard protocol for transferring log messages. Many third-party services offer endpoints for ingesting syslog events. You can forward your Upsun and Blackfire logs to any of those endpoints. ``type``, ``syslog-host``, and ``syslog-port`` are the only properties required for all endpoints. The following table shows the other available properties: | Property | Type | Default | Description | | ``auth-token`` | ``string`` | | The token to authenticate with the given service. | | ``auth-mode`` | ``string`` | ``prefix`` | The mode for authentication with the given service. Can be ``prefix`` or ``structured_data``. Defaults to ``prefix``. | | ``facility`` | ``string`` | ``1`` (user) | A [syslog facility code](https://en.wikipedia.org/wiki/Syslog#Facility) to attach with each log to identify the source. Can be a number from 0 to 23. | | ``message-format`` | ``string`` | ``rfc5424`` | The standard to use for the message format. Can be ``rfc5424`` or ``rfc3164``. | | ``protocol`` | ``string`` | ``tls`` | The network protocol to use in the connection. Can be one of ``tls``, ``tcp``, or ``udp``. Defaults to ``tls``. | | ``verify-tls`` | ``boolean`` | ``true`` | Whether to verify Transport Layer Security (TLS) certification when using the TLS protocol. | To include a property, add it as a flag, for example ``--protocol tcp``. This should let you connect to any service that has syslog endpoints. To start forwarding logs, once you’ve added the service [trigger a redeploy](https://docs.upsun.com/development/troubleshoot.md#force-a-redeploy). To enable log forwarding to a syslog endpoint for a specific project using the [Upsun CLI](https://docs.upsun.com/administration/cli.md), follow these steps: - Navigate to your project. - Click Settings **Settings**. - Click **Integrations**. - Click **Add Integration**. - Select the syslog integration. - In the **Configure your integration** window, specify your configuration options. - Click **Add Integration**. The new integration overview is displayed, and you can view your logs in the **Activity** section. ## Forward to an HTTP endpoint Some third-party services, such as [Elasticsearch](https://docs.upsun.com../../add-services/elasticsearch.md) and [OpenSearch](https://docs.upsun.com../../add-services/opensearch.md), support ingesting log messages through an HTTP endpoint. You can use HTTP forwarding to forward Upsun and Blackfire logs to such third-party services. HTTP forwarding makes a `POST` HTTP request with an `application/json` body while forwarding the log messages to the endpoint. As an example, to forward logs to Elasticsearch using HTTP log forwarding, run the following command: ``` upsun integration:add --type httplog --url "https:////_doc" --header "Authorization: Basic " --header "Content-Type: application/json" ``` `type` and `url` are the only properties required for all endpoints. Optionally, you can use the `headers` property to pass additional headers in the HTTP requests. Note that if your endpoint URL includes a `PORT`, that can also be included in the `--url` flag: ``` upsun integration:add --type httplog --url "https://://_doc" --header "Authorization: Basic " --header "Content-Type: application/json" ``` Once you've [added the service](https://docs.upsun.com../../add-services.md), to start forwarding logs [trigger a redeploy](https://docs.upsun.com../../development/troubleshoot.md#force-a-redeploy). ### Excluding services from HTTP log forwarding All log forwarding integrations support an `excluded_services` property. This allows you to prevent logs from specific applications or services (including workers) from being forwarded to an external logging provider. This is useful for reducing noise, limiting log volume, or excluding non-critical services. The exclusion list is defined at the project level and applies to all environments. #### Supported integrations The `excluded_services` property is supported by all log forwarder types, including: - Syslog - Sumologic - Splunk - HTTP log forwarding - New Relic - OTLP #### Excluding apps or services By default, logs from all apps and services are forwarded. To exclude specific services, define them using `excluded_services`: ```yaml {location=".upsun/config.yaml"} logs_forwarders: - type: httplog endpoint: https://logs.example.com excluded_services: - cache - debug-worker ``` In this example, logs from the `cache` service and the `debug-worker` worker are not forwarded. **Note**: Note that the same exclusion list applies to all environments. If a listed app or service does not exist in an environment, it is silently ignored. No error is raised. **Note**: ``excluded_services`` removes the specified apps or services from log forwarding while all other apps and services continue to forward logs as normal. Note that these exclusions apply globally across environments. ### Naming consistency When defining exclusions, you can list: - Apps (for example - `app`, `api`) - Services (for example - `cache`, `database`) - Workers (for example - `debug-worker`) Make sure to use the `service` or `app` name **exactly as defined in your project configuration**. #### Including services explicitly You can optionally define an `included_services` list to control exactly which services are forwarded. If `included_services` is set, only the listed services are forwarded. ```yaml {location=".upsun/config.yaml"} logs_forwarders: - type: syslog host: syslog.example.com included_services: - app - api ``` #### Combining include and exclude rules You can use both `included_services` and `excluded_services` together. The following rules apply: - If `included_services` is not set, all services are included by default - If `included_services` is set, only those services are included - `excluded_services` always removes services from the active set ```yaml {location=".upsun/config.yaml"} logs_forwarders: - type: syslog host: syslog.example.com included_services: - app - api - worker - cache excluded_services: - cache ``` Result: logs from `app`, `api`, and `worker` are forwarded. **Note**: Note that a service cannot appear in both lists. Configurations that include the same service in both lists are invalid. ## Log levels Your app may output logs with distinct severity levels. But as Upsun only reads logs from `stdout`, this distinction is lost and everything gets logged at `INFO` level. To preserve the original log level, use a language-specific syslog module/package for logging. The following example code snippets show how logs can be written to Syslog: Using the logging module: ```python {} import logging import logging.handlers logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) handler = logging.handlers.SysLogHandler(address="/dev/log") logger.addHandler(handler) logger.info("Operation started") logger.error("Operation failed") ``` Using the Syslog module: ```python {} import syslog syslog.openlog(logoption=syslog.LOG_PID, facility=syslog.LOG_LOCAL0) syslog.syslog(syslog.LOG_INFO, "Operation started") syslog.syslog(syslog.LOG_ERR, "Operation failed") syslog.closelog() ``` Using the log package: ```go {} package main import ( "log" "log/syslog" ) func main() { logger, err := syslog.NewLogger(syslog.LOG_LOCAL0|syslog.LOG_INFO, log.LstdFlags) if err != nil { panic(err) } logger.Println("Operation started...") logger.Fatalln("Operation failed") } ``` Using the Syslog package: ```go {} package main import ( "fmt" "log" "log/syslog" ) func main() { syslogWriter, err := syslog.Dial("", "", syslog.LOG_LOCAL0|syslog.LOG_INFO, "") if err != nil { log.Fatal(err) } defer syslogWriter.Close() fmt.Fprintf(syslogWriter, "Operation has started") syslogWriter.Err("Operation failed") } ``` --- # Source: https://docs.upsun.com/languages/php/fpm.md # PHP-FPM sizing p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. PHP-FPM helps improve your app's performance by maintaining pools of workers that can process PHP requests. This is particularly useful when your app needs to handle a high number of simultaneous requests. By default, Upsun automatically sets a maximum number of PHP-FPM workers for your app. This number is calculated based on three parameters: - The container memory: the amount of memory you can allot for PHP processing depending on [your defined application resources](https://docs.upsun.com/manage-resources.md). - The request memory: the amount of memory an average PHP request is expected to require. - The reserved memory: the amount of memory you need to reserve for tasks that aren't related to requests. The number is calculated as follows: ![The sum of container memory minus reserved memory divided by request memory](https://docs.upsun.com/images/php/PHP-FPM-Workers-Calculation.png "0.2") Note that when the resulting number is a decimal, it's rounded up to set the maximum number of workers. Also, the minimum number of PHP-FPM workers is 2. To adjust the maximum number of PHP-FPM workers depending on your app's needs, follow the instructions on this page. ## Before you begin You need: - An up-and-running web app in PHP, complete with [PHP-FPM](https://www.php.net/manual/en/install.fpm.php) - The [Upsun CLI](https://docs.upsun.com../../administration/cli.md) Note that the memory settings mentioned on this page are different from the [`memory_limit` PHP setting](https://docs.upsun.com/languages/php.md). The `memory_limit` setting is the maximum amount of memory a single PHP process can use before it's automatically terminated. ## 1. Estimate the optimal request memory for your app To determine what the optimal request memory is for your app, you can refer to your PHP access logs. Run a command similar to: ```bash upsun log --lines 5000 php.access | awk '{print $6}' | sort -n | uniq -c ``` This command takes into account the last 5,000 requests that reached PHP-FPM. You can adjust this number depending on the amount of traffic on your site. In the output, you can see how many requests used how much memory, in KB. For example: ```bash 2654 2048 431 4096 584 8192 889 10240 374 12288 68 46384 ``` The output shows that: - The majority of requests peaked at 2,048 KB of memory. - Most other requests used up to around 10 MB of memory. - A few requests used up to around 12 MB of memory. - Only 68 requests peaked at around 46 MB of memory. In this situation, you might want to be cautious and [set your request memory](#2-adjust-the-maximum-number-of-php-fpm-workers) to 12 MB. Setting a lower request memory presents a risk of allowing more concurrent requests. This can result in memory swapping and latencies. ## 2. Adjust the maximum number of PHP-FPM workers By default, the request memory is set to 45 MB and the reserved memory is set to 70 MB. These values allow most programs to run, but you can amend them to fit your needs. To do so, adjust your [app configuration](https://docs.upsun.com../../create-apps.md). Under `runtime` in the [`sizing_hints` setting](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#sizing-hints), set the values for `reserved_memory` and `request_memory`. For example, if you estimate your [optimal request memory](#1-estimate-the-optimal-request-memory-for-your-app) to be 110 MB and your reserved memory to be 80 MB, you can use: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'php:8.5' runtime: sizing_hints: request_memory: 110 reserved_memory: 80 ``` Note that the minimum value for the `request_memory` key is 10 MB and the minimum value for the `reserved_memory` key is 70 MB. If you set lower values, they're automatically overridden with those minimums. To check the maximum number of PHP-FPM workers available to your app, run the following command, where `children` refers to PHP-FPM workers: ```bash upsun ssh "grep -e '^pm.max_children' /etc/php/*/fpm/php-fpm.conf" ``` You get output similar to the following: ```bash pm.max_children = 5 ``` --- # Source: https://docs.upsun.com/languages/php/frankenphp.md # FrankenPHP [FrankenPHP](https://frankenphp.dev/) is a modern PHP application server designed as a high-performance alternative to traditional PHP-FPM setups. It combines a native PHP runtime with an HTTP server, reducing orchestration overhead while enabling new execution models that can significantly improve performance. FrankenPHP is particularly well-suited for modern PHP frameworks and applications that want faster request handling, simpler infrastructure, and optional support for long-running workers. ## Why FrankenPHP? Traditional PHP deployments rely on multiple moving parts: a web server, PHP-FPM, and external process management. FrankenPHP simplifies this architecture by embedding PHP execution directly into the server. Some key features include: - Faster startup times and reduced per-request overhead compared to [PHP-FPM](https://docs.upsun.com/languages/php/fpm.md). - A modern architecture that works for contemporary PHP runtimes and frameworks. - Fewer services to configure and maintain. - Support for a worker-based execution model that avoids re-booting the application on every request. ### Execution modes FrankenPHP supports two distinct execution modes. Choosing the right mode depends on your application’s architecture and tolerance for stateful execution. #### Classic mode Classic mode behaves similarly to [PHP-FPM](https://docs.upsun.com/languages/php/fpm.md) and is the recommended default for most applications. - Each request runs in a clean, isolated environment - No application state is shared between requests - Lifecycle expectations are identical to PHP-FPM - Safe for existing PHP applications without modification In this mode, FrankenPHP provides performance and architectural improvements while preserving the [stateless](#stateless-execution-php-fpm-and-classic-mode) execution model. #### Worker mode Worker mode enables long-running PHP worker processes that handle multiple requests over their lifetime. - The application is booted once and kept in memory - Subsequent requests reuse the already-loaded application - Significantly reduced cold-start overhead - Higher throughput and faster response times This mode introduces [stateful](#stateful-execution-worker-mode) execution. ### Understanding Worker modes #### Stateless execution (PHP-FPM and Classic mode) In traditional PHP execution models every request starts from a clean slate, the application boots, handles the request, then shuts down and there are no variables, objects, or internal state persist between requests. This guarantees isolation and predictability, but it comes with unavoidable overhead as the full boot and teardown cycle happens on every request. #### Stateful execution (Worker mode) With Stateful execution in Worker mode, the application is booted once. It remains in memory and handles many requests and internal state persists unless explicitly reset. This improves performance dramatically, but introduces new risks. For example, in a stateful environment: - Mutated variables may leak into later requests - Static properties and singletons persist - Cached data may become stale or invalid - Connection pools or services may behave unexpectedly These issues do not occur in stateless PHP-FPM setups. **Note**: Aplications not explicitly designed for long-running workers may require manual state resets between requests, careful handling of static properties and global variables, explicit cleanup logic and auditing of caching and service lifecycles. Tools like [Laravel Octane](https://laravel.com/docs/master/octane) or the [Symfony FrankenPHP Runtime](https://github.com/php-runtime/frankenphp-symfony) are designed to manage this environment safely. They often serve clones of the application or reset the container state between requests to prevent variables from leaking. ### Observability and profiling FrankenPHP is well supported by [Blackfire](https://docs.upsun.com/increase-observability/application-metrics/blackfire.md), making it easy to profile and monitor performance in both Classic and Worker modes. **Note**: You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. ### Classic mode configuration ```yaml {location=".upsun/config.yaml"} applications: app: type: "composable:25.11" source: root: "/" stack: runtimes: - "php@8.4": extensions: - apcu - blackfire - ctype - iconv - mbstring - pdo_pgsql - sodium - xsl - "nodejs@22" packages: - "frankenphp" variables: php: opcache.preload: config/preload.php env: APP_RUNTIME: 'Runtime\\FrankenPhpSymfony\\Runtime' # composer require runtime/frankenphp-symfony web: upstream: socket_family: tcp protocol: http commands: start: frankenphp php-server --listen=localhost:$PORT --root=$PLATFORM_DOCUMENT_ROOT index.php locations: "/": root: "public" expires: 1h passthru: true allow: true scripts: true request_buffering: enabled: false ``` ### Worker mode configuration ```yaml {location=".upsun/config.yaml"} applications: app: type: "composable:25.11" source: root: "/" stack: runtimes: - "php@8.4": extensions: - apcu - blackfire - ctype - iconv - mbstring - pdo_pgsql - sodium - xsl - "nodejs@22" packages: - "frankenphp" variables: php: opcache.preload: config/preload.php env: APP_RUNTIME: 'Runtime\\FrankenPhpSymfony\\Runtime' # composer require runtime/frankenphp-symfony web: upstream: socket_family: tcp protocol: http commands: start: frankenphp php-server --worker $PLATFORM_DOCUMENT_ROOT/index.php --listen=localhost:$PORT --root=$PLATFORM_DOCUMENT_ROOT locations: "/": root: "public" expires: 1h passthru: true allow: true scripts: true request_buffering: enabled: false ``` ### Using the latest FrankenPHP version You can request FrankenPHP from the Nix unstable channel to access the latest available version. ```yaml {location=".upsun/config.yaml"} stack: packages: - package: frankenphp channel: unstable ``` ### Choosing the right mode - Use [Classic mode](#classic-mode) if you want safety, predictability, and drop-in compatibility with existing PHP applications. - Use [Worker mode](#worker-mode) if you need maximum performance and are prepared to manage application state explicitly. Both modes are fully supported on Upsun, allowing you to choose the execution model that best fits your application. ## Related content - [Blackfire FrankenPHP documentation](https://docs.blackfire.io/php/integrations/frankenphp) - [Up(Sun) and running with FrankenPHP](https://upsun.com/blog/upsun-and-running-with-frankenphp/) - [How we scaled live connections for 1200 developers at SymfonyCon](https://devcenter.upsun.com/posts/how-we-scaled-live-connections-for-1200-developers-at-symfonycon/#starting-with-frankenphp-the-documentation-gap) --- # Source: https://docs.upsun.com/learn/overview/get-support.md # Get support Find out how to get help if you’re experiencing issues with Upsun. ## Create a support ticket If you're experiencing issues related to the proper functioning of the Upsun infrastructure, application container software, build processes, have found possible bugs, have general questions or wish to submit a feature request, open a support ticket: 1. [Open the Console](https://console.upsun.com/). 1. In the upper right-hand corner, click **Help** and select **Support** from the menu. 1. In the **Support tickets** section, click **New ticket**. 1. Complete the **Create a ticket** form and then click **Submit**. Or use these shortcuts to [access all support tickets](https://console.upsun.com/-/users/~/tickets) or [open a new ticket](https://console.upsun.com/-/users/~/tickets/open). Once you submit a ticket, you see it in a list of all tickets created, for all projects you have access to, within your organization. **Note**: Note that once you submit the ticket, you can’t modify or delete the submission. If you have any additional information, you can select the submitted ticket and write a message. **Upgrade to the Organization Support add-on**: The Upsun Organization Support add-on provides tiered support options tailored to organizational needs. All organizations are automatically enrolled in the Standard support tier. To upgrade to either the Premium or Advanced support tier, visit the [add-on subscriptions page](https://docs.upsun.com/administration/billing/add-on-subscription.md#organization-support-add-on). ## Community To talk about app development or framework-related questions, join other customers and engineers in the [Discord](https://discord.gg/upsun). Also, the [Upsun Community forum](https://community.platform.sh/) has how-to guides with suggestions on how to get the most out of Upsun. Join us on Discord Ask a question on the forum .cta-container { display: flex; flex-wrap: wrap; justify-content: center; gap: 1rem; margin-top: 3rem; } .start-cta, .info-cta { text-decoration: none !important; font-size: 16px !important; font-weight: 700 !important; letter-spacing: 0.48px !important; border-radius: 80px !important; padding: 10px 16px !important; white-space: nowrap; } .start-cta { color: white !important; background: #6046FF !important; border: none; } .start-cta:hover { background: #4D38CC !important; color: white !important; } .info-cta { color: #191C1E !important; background: white !important; border: 2px solid #191C1E !important; } .info-cta:hover { background: #191C1E !important; color: white !important; } @media (max-width: 600px) { .cta-container { flex-direction: column; align-items: center; } .start-cta, .info-cta { width: 80%; text-align: center; } } ## Contact Sales If you have questions about pricing or need help figuring out if Upsun is the right solution for your team, get in touch with [Sales](https://upsun.com/register/). ## Delete your account To permanently delete your Upsun account, follow these steps: **Warning**: Deleting your Upsun account automatically deletes all your linked Ibexa Cloud, Pimcore PaaS, and Shopware PaaS accounts. 1. [Open the Console](https://console.upsun.com/). 2. Open the user menu (your name or profile picture) and select **My Profile**. 3. Click **Delete account**. 4. Check that the pre-filled information is correct and click **Submit**. 5. Read the consequences of account deletion and click **Submit request** to confirm. Your request is now submitted and will be handled by Support shortly. --- # Source: https://docs.upsun.com/integrations/source/github.md # Integrate with GitHub If you have code in a GitHub repository, you might want to connect it to a Upsun project. This means you can keep your GitHub workflows and treat the GitHub repository as the source of truth for your code. Your Upsun project becomes a mirror of your GitHub repository. This means you shouldn't push code directly to Upsun. Any changes you push directly get overwritten by the integration when changes happen in the GitHub repository. When you set up an integration with GitHub, it automates the following processes for you: - Creating a new environment when a branch is created or a pull request is opened. - Rebuilding the environment when new code is pushed to GitHub. - Deleting the environment when a pull request is merged. ## Before you begin To manage source integrations, you need to be a [project admin](https://docs.upsun.com../../administration/users.md). You also need a GitHub repository with working code. ## 1. Generate a token To integrate your Upsun project with an existing GitHub repository, you need to [generate a new token](https://github.com/settings/tokens/new). You can generate a classic personal access token, or a [fine-grained personal access token](https://github.blog/changelog/2022-10-18-introducing-fine-grained-personal-access-tokens/) for even greater control over the permissions you grant. For the integration to work, your GitHub user needs to have permission to push code to the repository. When you set up or update an integration, it also needs permission to manage its webhooks. This means your user needs to be a repository admin to create the integration. You can remove this permission after setup. Make sure you give your token a description. If you're generating a classic personal access token, ensure the token has the appropriate scopes based on what you want to do: | Scope | Purpose | | --------------------- | ---------------------------------------------------------------------- | | `admin:repo_hook` | To create webhooks for events in repositories. Always needed. | | `public_repo` | To integrate with public repositories. | | `repo` | To integrate with your private repositories. | | `repo` and `read:org` | To integrate with private repositories in organizations you belong to. | If you're generating a fine-grained personal access token, ensure the token has the right [repository permissions](https://docs.github.com/en/rest/overview/permissions-required-for-fine-grained-personal-access-tokens?apiVersion=2022-11-28) for the integration to work: | Permission | Access level | | ------------------| ----------------| | `Commit statuses` | Read and write | | `Contents` | Read and write | | `Metadata` | Read-only | | `Pull request` | Read and write | | `Webhooks` | Read and write | After you've set the needed scopes or permissions, generate and copy your token. ## 2. Enable the integration To enable the integration, use either the [CLI](https://docs.upsun.com/administration/cli.md) or the [Console](https://docs.upsun.com/administration/web.md). - ``PROJECT_ID`` is the ID of your Upsun project. - ``OWNER/REPOSITORY`` is the name of your repository in GitHub. - ``GITHUB_ACCESS_TOKEN`` is the [token you generated](#1-generate-a-token). - ``GITHUB_URL`` is the base URL for your GitHub server if you self-host. If you use the public ``https://github.com``, omit the ``--base-url`` flag when running the command. For example, if your repository is located at ``https://github.com/platformsh/platformsh-docs``, the command is similar to the following: ```bash {} upsun integration:add \ --project abcdefgh1234567 \ --type github \ --repository platformsh/platformsh-docs \ --token abc123 ``` - Select the project where you want to enable the integration. - Click **Settings Settings**. - Under **Project settings**, click **Integrations**. - Click **+ Add integration**. - Under **GitHub**, click **+ Add**. - Add the [token you generated](#1-generate-a-token). - Optional: If your GitHub project isn’t hosted at ``github.com``, enter your GitHub custom domain. - Click **Continue**. - Choose the repository to use for the project. - Check that the other options match what you want. - Click **Add integration**. In both the CLI and Console, you can choose from the following options: | CLI flag | Default | Description | | ---------------- | ------- | ------------------------------------------------------------------------- | | `fetch-branches` | `true` | Whether to mirror and update branches on Upsun and create inactive environments from them. When enabled, merging on an Upsun environment isn't possible. That is, merging environments must be done on the source repository rather than on the Upsun project. See note below for details related to this flag and synchronizing code from a parent environment. | | `prune-branches` | `true` | Whether to delete branches from Upsun that don’t exist in the GitHub repository. When enabled, branching (creating environments) must be done on the source repository rather than on the Upsun project. Branches created on Upsun that are not on the source repository will not persist and will be quickly pruned. Automatically disabled when fetching branches is disabled. | | `build-pull-requests` | `true` | Whether to track all pull requests and create active environments from them, which builds the pull request. | | `build-draft-pull-requests` | `true` | Whether to also track and build draft pull requests. Automatically disabled when pull requests aren’t built. | | `pull-requests-clone-parent-data` | `true` | Whether to clone data from the parent environment when creating a pull request environment. | | `build-pull-requests-post-merge`| `false` | Whether to build what would be the result of merging each pull request. Turning it on forces rebuilds any time something is merged to the target branch. | | `resources-init` | `false` | To [specify a resource initialization strategy](https://docs.upsun.com/manage-resources/resource-init.md#first-deployment) for new containers. Once set, the strategy applies to **all** the deployments you launch through your source integration. See more information on [available resource initialization strategies](https://docs.upsun.com/manage-resources/resource-init.md#specify-a-resource-initialization-strategy). | To [keep your repository clean](https://docs.upsun.com/learn/bestpractices/clean-repository.md) and avoid performance issues, make sure you enable both the `fetch-branches` and `prune-branches` options. ## 3. Validate the integration Verify that your integration is functioning properly [using the CLI](https://docs.upsun.com../overview.md#validate-integrations): ```bash upsun integration:validate ``` ### Add the webhook manually If the integration was added with the correct permissions, the necessary webhook is added automatically. If you see a message that the webhook wasn't added, add one manually. To configure a webhook on a GitHub repository, you need to have Admin [user permissions](https://docs.github.com/en/organizations/managing-user-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role). 1. Get the webhook URL by running this command: `upsun integration:get --property hook_url`. 1. Copy the returned URL. 1. In your GitHub repository, click **Settings** > **Webhooks** > **Add webhook**. 1. In the **Payload URL** field, paste the URL you copied. 1. For the content type, select **application/json**. 1. Select **Send me everything**. 1. Click **Add webhook**. You can now start pushing code, creating new branches, and opening pull requests directly in your GitHub repository. Your Upsun environments are automatically created and updated. ## Environment parent and status When a **branch** is created in GitHub, an environment is created in Upsun with the default branch as its parent. It starts as an [inactive environment](https://docs.upsun.com/glossary.md#inactive-environment) with no data or services. When a **pull request** is opened in GitHub, an environment is created in Upsun with the pull request's target branch as its parent. It starts as an [active environment](https://docs.upsun.com/glossary.md#active-environment) with a copy of its parent's data. ## Source of truth When you add an integration, your GitHub repository is considered to be the source of truth for the project. Your Upsun project is only a mirror of that repository and you can only push commits to GitHub. To clone your code, follow these steps: - In the Console, open the project you want to clone. - Click **Code**. - Click **Git**. - Run the command you find using Git. When you do this, you're cloning from your integrated GitHub repository, if you have the [appropriate access to do so](https://docs.upsun.com/integrations/source/troubleshoot.md). ### Sync, fetch, and prune An integration from GitHub to Upsun establishes that: - GitHub is the source of truth, where Git operations occur - Upsun is a mirror of that repository - provisioning infrastructure according to configuration, and orchestrating environments according to the branch structure of the GitHub repository Actions that take place on Upsun don't affect commits on GitHub. Because of this, the GitHub integration enables both `fetch-branches` (track branches on GitHub) and `prune-branches` (delete branches that don't exist on GitHub) by default. You can change these settings but it is recommend to keep them. When enabled by default, you are limited by design as to what actions can be performed within the context of a Upsun project with a GitHub integration: | Action | Observation | Recommendation | | :---------------- | :---------------- | :------- | | Branch from parent | Running [`environment:branch`](https://docs.upsun.com/administration/cli/reference#environmentbranch) with the CLI, or selecting **Branch** in Console produces a new child environment, but it's deleted shortly after automatically. | Contribute to the GitHub repository itself by creating a branch and pull request. When the PR has been opened, a new environment will be provisioned for it. | | Merge in parent | Running [`environment:merge`](https://docs.upsun.com/administration/cli/reference#environmentmerge) with the CLI fails locally, and the **Merge** option in Console is not clickable. | Review and merge pull requests and/or branches on the GitHub repository. | | Merge into child (sync code) | Running [`environment:synchronize`](https://docs.upsun.com/administration/cli/reference#environmentsynchronize) with the CLI fails locally, and the **Sync** option in Console won't allow me to include `code` in that sync. | Perform the merge locally from a matching branch on GitHub. For example, clone the most recent parent (`git pull origin parent-branch`), switch to the pull request branch (`git checkout ga-staging`), and then merge the parent into the current branch (`git merge main`). | ## Pull request URLs When a pull request is deployed, the integration reports the primary URL for the deployed environment. So you get a link to the deployed environment right in the pull request. If you have multiple routes, ensure the correct one is reported by [specifying the primary route](https://docs.upsun.com/define-routes.md#route-configuration-reference). --- # Source: https://docs.upsun.com/integrations/source/gitlab.md # Integrate with GitLab If you have code in a GitLab repository, you might want to connect it to a Upsun project. This means you can keep your GitLab workflows and treat the GitLab repository as the source of truth for your code. Your Upsun project becomes a mirror of your GitLab repository. This means you shouldn't push code directly to Upsun. Any changes you push directly get overwritten by the integration when changes happen in the GitLab repository. When you set up an integration with GitLab, it automates the following processes for you: - Creating a new environment when a branch is created or a merge request is opened. - Rebuilding the environment when new code is pushed to GitLab. - Deleting the environment when a merge request is merged. ## Before you begin To manage source integrations, you need to be a [project admin](https://docs.upsun.com../../administration/users.md). You also need a GitLab repository with working code. **Note**: If your GitLab instance is not accessible from the public internet, configure a [GitLab CI/CD pipeline](#optional-use-a-gitlab-cicd-pipeline) that pushes code to Upsun and manages environments via the Upsun API. This method provides full deployment control while keeping your GitLab instance isolated. ## 1. Generate a token To integrate your Upsun project with an existing GitLab repository, generate a [project access token](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.md#create-a-project-access-token). Ensure the token has the following scopes: - `api` to access your API - `read_repository` to read the repository For the integration to work, your GitLab user needs push access to the repository and to configure a webhook on a GitLab repository, you need to have Maintainer or Owner user permissions. Copy the token. **Note**: To create a project access token, you need to have a [sufficient GitLab license tier](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.md). If you don’t see **Access Tokens** under **Settings**, upgrade your GitLab tier. Alternatively, you can create a [personal access token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.md), but that’s attached to a specific user rather than the project as a whole and grants more permissions. ## 2. Enable the integration To enable the integration, use either the [CLI](https://docs.upsun.com/administration/cli.md) or the [Console](https://docs.upsun.com/administration/web.md). - ``PROJECT_ID`` is the ID of your Upsun project. - ``PROJECT/SUBPROJECT`` is the name of your repository in GitLab. - ``GITLAB_ACCESS_TOKEN`` is the [token you generated](#1-generate-a-token). - ``GITLAB_URL`` is the base URL for your GitLab server if you self-host. If you use the public ``https://gitlab.com``, omit the ``--base-url`` flag when running the command. For example, if your repository is located at ``https://gitlab.com/platformsh/platformsh-docs``, the command is similar to the following: ```bash {} upsun integration:add \ --project abcdefgh1234567 \ --type gitlab \ --server-project platformsh/platformsh-docs \ --token abc123 ``` - Select the project where you want to enable the integration. - Click **Settings Settings**. - Under **Project settings**, click **Integrations**. - Click **+ Add integration**. - Under **GitLab**, click **+ Add**. - Add the [token you generated](#1-generate-a-token). - Optional: If your GitLab project isn’t hosted at ``gitlab.com``, enter your GitLab custom domain. - Click **Continue**. - Choose the repository to use for the project. - Check that the other options match what you want. - Click **Add integration**. In both the CLI and Console, you can choose from the following options: | CLI flag | Default | Description | | ---------------- | ------- | ------------------------------------------------------------------------- | | `fetch-branches` | `true` | Whether to mirror and update branches on Upsun and create inactive environments from them. When enabled, merging on an Upsun environment isn't possible. That is, merging environments must be done on the source repository rather than on the Upsun project. See note below for details related to this flag and synchronizing code from a parent environment. | | `prune-branches` | `true` | Whether to delete branches from Upsun that don’t exist in the GitLab repository. When enabled, branching (creating environments) must be done on the source repository rather than on the Upsun project. Branches created on Upsun that are not on the source repository will not persist and will be quickly pruned. Automatically disabled when fetching branches is disabled. | | `build-merge-requests` | `true` | Whether to track all merge requests and create active environments from them, which builds the merge request. | | `build-wip-merge-requests` | `true` | Whether to also track and build draft merge requests. Automatically disabled when merge requests aren’t built. | | `merge-requests-clone-parent-data` | `true` | Whether to clone data from the parent environment when creating a merge request environment. | | `resources-init` | `false` | To [specify a resource initialization strategy](https://docs.upsun.com/manage-resources/resource-init.md#first-deployment) for new containers. Once set, the strategy applies to **all** the deployments you launch through your source integration. See more information on [available resource initialization strategies](https://docs.upsun.com/manage-resources/resource-init.md#specify-a-resource-initialization-strategy). To [keep your repository clean](https://docs.upsun.com/learn/bestpractices/clean-repository.md) and avoid performance issues, make sure you enable both the `fetch-branches` and `prune-branches` options. ## 3. Validate the integration Verify that your integration is functioning properly [using the CLI](https://docs.upsun.com../overview.md#validate-integrations): ```bash upsun integration:validate ``` ### Add the webhook manually If the integration was added with the correct permissions, the necessary webhook is added automatically. If you see a message that the webhook wasn't added, add one manually. To configure a webhook on a GitLab repository, you need to have Maintainer or Owner [user permissions](https://docs.gitlab.com/ee/user/permissions.md). 1. Get the webhook URL by running this command: `upsun integration:get --property hook_url`. 1. Copy the returned URL. 1. In your GitLab repository, click **Settings** > **Webhooks**. 1. In the **URL** field, paste the URL you copied. 1. Under **Trigger**, select **Push events** and **Merge request events**. 1. Click **Add webhook**. You can now start pushing code, creating new branches, and opening merge requests directly in your GitLab repository. Your Upsun environments are automatically created and updated. ## Environment parent and status When a **branch** is created in GitLab, an environment is created in Upsun with the default branch as its parent. It starts as an [inactive environment](https://docs.upsun.com/glossary.md#inactive-environment) with no data or services. When a **merge request** is opened in GitLab, an environment is created in Upsun with the merge request's target branch as its parent. It starts as an [active environment](https://docs.upsun.com/glossary.md#active-environment) with a copy of its parent's data. ## Source of truth When you add an integration, your GitLab repository is considered to be the source of truth for the project. Your Upsun project is only a mirror of that repository and you can only push commits to GitLab. To clone your code, follow these steps: - In the Console, open the project you want to clone. - Click **Code**. - Click **Git**. - Run the command you find using Git. When you do this, you're cloning from your integrated GitLab repository, if you have the [appropriate access to do so](https://docs.upsun.com/integrations/source/troubleshoot.md). ### Sync, fetch, and prune An integration from GitLab to Upsun establishes that: - GitLab is the source of truth, where Git operations occur - Upsun is a mirror of that repository - provisioning infrastructure according to configuration, and orchestrating environments according to the branch structure of the GitLab repository Actions that take place on Upsun don't affect commits on GitLab. Because of this, the GitLab integration enables both `fetch-branches` (track branches on GitLab) and `prune-branches` (delete branches that don't exist on GitLab) by default. You can change these settings but it is recommend to keep them. When enabled by default, you are limited by design as to what actions can be performed within the context of a Upsun project with a GitLab integration: | Action | Observation | Recommendation | | :---------------- | :---------------- | :------- | | Branch from parent | Running [`environment:branch`](https://docs.upsun.com/administration/cli/reference#environmentbranch) with the CLI, or selecting **Branch** in Console produces a new child environment, but it's deleted shortly after automatically. | Contribute to the GitLab repository itself by creating a branch and pull request. When the PR has been opened, a new environment will be provisioned for it. | | Merge in parent | Running [`environment:merge`](https://docs.upsun.com/administration/cli/reference#environmentmerge) with the CLI fails locally, and the **Merge** option in Console is not clickable. | Review and merge pull requests and/or branches on the GitLab repository. | | Merge into child (sync code) | Running [`environment:synchronize`](https://docs.upsun.com/administration/cli/reference#environmentsynchronize) with the CLI fails locally, and the **Sync** option in Console won't allow me to include `code` in that sync. | Perform the merge locally from a matching branch on GitLab. For example, clone the most recent parent (`git pull origin parent-branch`), switch to the pull request branch (`git checkout ga-staging`), and then merge the parent into the current branch (`git merge main`). | ## Merge request URLs When a merge request is deployed, the integration reports the primary URL for the deployed environment. So you get a link to the deployed environment right in the merge request. If you have multiple routes, ensure the correct one is reported by [specifying the primary route](https://docs.upsun.com/define-routes.md#route-configuration-reference). ## Optional: use a GitLab CI/CD pipeline If your GitLab instance is not accessible from the internet (e.g. air-gapped or behind a firewall), the GitLab integration process outlined above, based on incoming webhooks, might not be the best option to use. Instead, [set up a push-based GitLab CI/CD pipeline](https://devcenter.upsun.com/posts/gitlab-push-solution/) that pushes code to Upsun and manages environments using the Upsun API. This setup allows you to: - Deploy to production on `main` branch updates - Create preview environments for Merge Requests - Clean up environments when branches or MRs are removed - Keep your GitLab instance fully private **Detailed walkthrough**: For a detailed tutorial of how this works, with code samples and rationale, see this blog post: [Synchronize your air-gapped GitLab](https://devcenter.upsun.com/posts/gitlab-push-solution/). You can also find a complete working example of how this works in the Upsun [GitHub snippets repository](https://github.com/upsun/snippets/tree/main/examples/gitlab-ci). --- # Source: https://docs.upsun.com/glossary.md # Glossary ## Active environment An environment that's deployed. See how to [activate an environment](https://docs.upsun.com../environments/deactivate-environment.md#reactivate-an-environment). ## Apex domain An apex domain is a domain name that doesn't include a subdomain. For example, `example.com` is an apex domain and `www.example.com` is a subdomain. ## Branch Branching an environment means creating a new branch in the Git repository and an exact copy of that environment. The new environment includes all of the parent environment's: - Code - Running services and their configuration (only copies, not the data) - Data that's stored on disk (databases, uploaded files, and so on) This means that when you branch an environment, you also branch the complete infrastructure. When you branch an environment, three things happen: - A new branch is created in Git. - Your apps are rebuilt on the new branch, if necessary. (This is skipped if the same code with the same [variables](https://docs.upsun.com../development/variables.md) has been built for any environment.) - The new branch is deployed. To create a new branch from an existing environment: Run: ```bash {} upsun branch ``` To define the environment type for the branch, include ``--type ``. For example, to create the branch ``develop`` as a [preview environment](#preview-environment) ([development type](#environment-type)) from the branch ``main``, run: ```bash {} upsun branch develop main --type development ``` **Warning**: If you’re using a [source integration](https://docs.upsun.com/integrations/source.md), running this command results in an error stating that the operation is not available. This is because when a source integration is enabled, all branching and merging must be managed through the upstream repository to avoid merge conflicts. ## Cluster Every active environment is deployed as a cluster, which is a collection of independent containers representing the different services that make up your web application. That may include a database container, an Elasticsearch container, a container for your application, and more. They're always deployed together as a single unit. ## Deprecated versions Older versions of languages and services eventually reach the end of their lives. This means they stop getting security and other updates and may have security vulnerabilities. When that happens, the versions in Upsun are deprecated. This means you can still use them in your project, but they aren't fully secure. It's also possible they'll stop working at some point. If you're using a deprecated version, you should upgrade to a supported version as soon as possible. ## Drush Drush is a command-line shell and scripting interface for Drupal. ## Drush aliases Drush site aliases allow you to define short names that let you run Drush commands on specific local or remote Drupal installations. The Upsun CLI configures Drush aliases for you on your local environment (via `upsun get` or `upsun drush-aliases`). You can also configure them manually. ## Endpoint An endpoint is a named set of credentials to give access to other apps and services in your project. ## Environment An [environment](https://docs.upsun.com../environments.md) is a standalone copy of your site, complete with code, data, and running services. Your production environment comes from the [default branch](https://docs.upsun.com../environments.md#default-environment) and you can set up any other branch as a testing environment. ## Environment type Upsun offers three environment types: - Your **production environment** is your live site. - A **development environment** is an isolated environment where you can safely develop new features without affecting production. - A **staging environment** has a similar configuration to your production environment (but usually with less resources for cost optimization). It is useful to perform user acceptance testing in a production-like setting. The phrase "[preview environment](#preview-environment)" can apply to both a development or staging environment, as it merely describes a non-production environment. Find out more about [user roles on each environment type](https://docs.upsun.com../administration/users.md#environment-type-roles). ## First Project Incentive To help you get started Upsun offers a monthly $19 USD perk called the First Project Incentive. ### How do I apply this perk? Whether you are a new or existing customer, **_no action is needed_**. Just visit the billing section of your organization to see it applied. ### Why don't I see the full amount applied to my bill? There are two reasons why you may not see the full amount applied to your bill. 1. The First Project Incentive is prorated. If your billing cycle has started mid-month, it will be reflected in the amount applied to your bill. 2. Your bill can never be less than $0. For example, if your total bill for the month is $10, the First Project Incentive will only apply up to $10. ## Inactive environment An environment that isn't deployed. It has no data of its own and no running services. If you reactivate it, it copies data from its parent. See how to [deactivate an environment](https://docs.upsun.com../environments/deactivate-environment.md). ## Live environment A publicly accessible environment that's deployed from the Production branch under a production plan. ## MB MB stands for megabyte, which means 1,000,000 bytes. This unit is based on powers of 10. Some reporting tools, such as those used by the [CLI](https://docs.upsun.com../administration/cli.md), use binary megabytes, also known as mebibytes and abbreviated as MiB. This unit is based on powers of 2 and so 1 MiB equals 10242 or 1,048,576 bytes. So 1 MB is less than 1 MiB. So you may see differences in the numbers you configure for a disk (in MB) and the values reported when you check disk size with tools that report in MiB. ## Merge Merging an environment means copying any code changes from that environment into its parent environment and redeploying the parent. When you merge an environment, three things happen: - Any code changes are merged via Git to the parent branch. - Your apps rebuilt on the parent branch, if necessary. (This is skipped if the same code with the same [variables](https://docs.upsun.com../development/variables.md) has been built for any environment.) - The parent branch is deployed. ## PaaS A Platform as a Service is an end-to-end hosting solution that includes workflow tools, APIs, and other functionality above and beyond basic hosting. The best example is Upsun(although we're a little biased). ## Preview environment *Related terms: [Environment type](#environment-type)* A preview environment is a non-production environment you can use to develop and/or test changes without affecting production. A preview environment can either be a development environment or a staging environment. Preview environments have an identical software configuration to your production hardware but reduced hardware specs. They are useful to perform user acceptance testing. To learn more, see [Branch](#branch) also in this glossary. ## Production plan ## Project A [project](https://docs.upsun.com../projects.md) is the site that you’re working on. Each project corresponds to one Git repository. A project can contain multiple apps that run in their own isolated containers. Each branch of a project can be deployed in its own environment. ## Route {#route} A _route_ is information that tells the Upsun [_router_](#router) how incoming web requests should be handled and which app container (or destination) should respond. Routes are defined in the `.routes` top-level key in your project’s configuration file (for example, .upsun/config.yaml), and they map specific URLs or domains to one of the following actions: Routes map specific URLs or domains to one of the following actions: - `upstream` sends the request to a specific application container - `redirect` sends the request to another route or URL (for example, redirecting `www` to non-www) - `proxy` forwards requests to an external service outside the project See the [examples](https://docs.upsun.com/define-routes.md#examples) in the "Define routes" topic. ## Router {#router} The _router_ is the traffic director of your Upsun environment: it handles routing logic, basic caching, and traffic entry, and directs traffic to the correct container or containers based on the [_routes_](#route) that you define in your `.upsun/config.yaml` file. ## Sync Synchronizing an environment means copying changes from a parent into a child environment and then redeploying the child environment. You can synchronize only the code, only the data (databases, files), or both. Be aware that sync has the same process and same concerns as [backups](https://docs.upsun.com../environments/backup.md#backups-and-downtime). Sync is only available if your branch has no unmerged commits and can be fast-forwarded. It's good practice to take a backup of your environment before synchronizing it. ## Transport Layer Security (TLS) TLS is the successor of Secure Socket Layer (SSL). It provides the cryptographic "S" in HTTPS. It's often still referred to as SSL even though it has mostly replaced SSL for online encrypted connections. ## Trial When you create your first organization on Upsun, you are also activating your trial for that organization. This trial grants you a certain amount of time and resources to try out the Upsun platform, and comes with the following restrictions: 1. A trial lasts for **15 days**, which starts automatically from creating your first organization. 1. A trial allows for **one (1)** active [project](#project) at a time. 1. For a trial project, the trial allows for **two (2)** [active environments](#active-environment). 1. At the organization level, there is a limit on the amount of [resources available to your project](https://docs.upsun.com/manage-resources/_index.md): - 4.5 CPU - 12 GB RAM - 20 GB storage If your trial ends before adding payment details, there are additional things to keep in mind: - When a trial expires, both the organization and the project are suspended. - Projects where no code has been pushed are deleted **1 day** after a trial expires. - Projects where code _has_ been pushed are deleted **5 days** after the trial expires. - Even with the trial expiration, organizations and user accounts are preserved, [rather than deleted](https://docs.upsun.com/learn/overview/get-support.md#delete-your-account). --- # Source: https://docs.upsun.com/languages/go.md # Go p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. Upsun supports building and deploying applications written in Go using Go modules. They’re compiled during the Build hook phase, and support both committed dependencies and download-on-demand. ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 1.25 - 1.24 ### Specify the language To use Go, specify `golang` as your [app's `type`](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#types): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. : type: 'golang:' ``` For example: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'golang:1.25' ``` ### Deprecated versions The following versions are [deprecated](https://docs.upsun.com/glossary.md#deprecated-versions). They're available, but they don't receive security updates from upstream and aren't guaranteed to work. They'll be removed in the future – consider migrating to a [supported version](#supported-versions). - 1.23 - 1.22 - 1.21 - 1.20 - 1.19 - 1.18 - 1.17 - 1.16 - 1.15 - 1.14 - 1.13 - 1.12 - 1.11 - 1.10 ## Go toolchain auto download Even though you select a specific version of Go, starting in Go 1.21, the `go` command will automatically download and use a different toolchain version as requested by the `toolchain` directive in `go.mod`, or the `GOTOOLCHAIN` environmental variable (see [Go Toolchains](https://go.dev/doc/toolchain)). **Note**: Still, it is important to keep your chosen version of Go updated in your yaml configuration file. This will ensure that you are using the most up to date software for your projects. ## Go modules The recommended way to handle Go dependencies on Upsun is using Go module support in Go 1.11 and later. That allows the build process to use `go build` directly without any extra steps, and you can specify an output executable file of your choice. (See the examples below.) ## Building and running the application Assuming your `go.mod` and `go.sum` files are present in your repository, your application can be built with the command `go build`, to produce a working executable. You can then start it from the `web.commands.start` directive. Note that the start command _must_ run in the foreground. If the program terminates for any reason it is automatically restarted. The following basic `.upsun/config.yaml` file is sufficient to run most Go applications. ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'golang:1.25' hooks: build: | # Modify this line if you want to build differently or # use an alternate name for your executable. go build -o bin/app web: upstream: socket_family: tcp protocol: http commands: # If you change the build output in the build hook above, update this line as well. start: ./bin/app locations: /: # Route all requests to the Go app, unconditionally. allow: false passthru: true ``` Note that there is still an Nginx proxy server sitting in front of your application. If desired, certain paths may be served directly by Nginx without hitting your application (for static files, primarily) or you may route all requests to the Go application unconditionally, as in the example above. ## Accessing services To access various [services](https://docs.upsun.com../add-services.md) with Go, see the following examples. The individual service pages have more information on configuring each service. You can access service credentials to connect to [managed services](https://docs.upsun.com/add-services/) from environment variables present in the application container. Consult each of the individual service documentation to see how to retrieve and surface credentials into your application. - [Chroma](https://docs.upsun.com/add-services/chroma.md#3-use-the-relationship-in-your-application) - [ClickHouse](https://docs.upsun.com/add-services/clickhouse.md#usage-example) - [Elasticsearch](https://docs.upsun.com/add-services/elasticsearch.md#use-in-app) - [Edgee (Edge Analytics)](https://docs.upsun.com/add-services/edgee.md#setup-edgee) - [Gotenberg](https://docs.upsun.com/add-services/gotenberg.md#usage-example) - [Headless Chrome](https://docs.upsun.com/add-services/headless-chrome.md#use-in-app) - [InfluxDB](https://docs.upsun.com/add-services/influxdb.md#use-in-app) - [Kafka](https://docs.upsun.com/add-services/kafka.md#use-in-app) - [MariaDB/MySQL](https://docs.upsun.com/add-services/mysql.md#use-in-app) - [Memcached](https://docs.upsun.com/add-services/memcached.md#use-in-app) - [Mercure](https://docs.upsun.com/add-services/mercure.md#use-in-app) - [MongoDB](https://docs.upsun.com/add-services/mongodb.md#use-in-app) - [Network Storage](https://docs.upsun.com/add-services/network-storage.md#usage-example) - [OpenSearch](https://docs.upsun.com/add-services/opensearch.md#use-in-app) - [PostgreSQL](https://docs.upsun.com/add-services/postgresql.md#use-in-app) - [Qdrant](https://docs.upsun.com/add-services/qdrant.md#4-use-the-relationship-in-your-application) - [RabbitMQ](https://docs.upsun.com/add-services/rabbitmq.md#use-in-app) - [Redis](https://docs.upsun.com/add-services/redis.md#use-in-app) - [Solr](https://docs.upsun.com/add-services/solr.md#use-in-app) - [Valkey](https://docs.upsun.com/add-services/valkey.md#use-in-app) - [Varnish](https://docs.upsun.com/add-services/varnish.md#usage-example) - [Vault KMS](https://docs.upsun.com/add-services/vault.md#use-vault-kms) --- # Source: https://docs.upsun.com/add-services/gotenberg.md # Gotenberg Gotenberg is a stateless API for converting various document formats into PDF files. For more information, see the [Gotenberg documentation](https://gotenberg.dev/docs/getting-started/introduction). ## Supported versions - 8 You can select the major version. But the latest compatible minor version is applied automatically and can’t be overridden. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "host": "gotenberg.internal", "hostname": "rssjaxyeoorjje6axcq35xu5gq.gotenberg.service._.eu-5.platformsh.site", "cluster": "p2f2xrzyq7a6k-main-bvxea6i", "service": "gotenberg", "rel": "http", "scheme": "http", "port": "3000", "type": "gotenberg:8", "instance_ips": [ "249.45.240.83" ], "ip": "169.254.137.3", "url": "http://gotenberg.internal:3000" } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_GOTENBERG_HOST=="$(echo $RELATIONSHIPS_JSON | jq -r '.gotenberg[0].host')" ``` ## Usage example ### 1. Configure the service To define the service, use the `gotenberg` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: gotenberg: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. ### 2. Define the relationship To define the relationship, use the ``http`` endpoint: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: http ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. With the above definition, Upsun uses the `http` endpoint, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the _name_ of that service. The `http` endpoint uses port `3000` by default. ### Example configuration ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: gotenberg: services: # The name of the service container. Must be unique within a project. gotenberg: type: gotenberg:8 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: gotenberg: service: gotenberg endpoint: http services: # The name of the service container. Must be unique within a project. gotenberg: type: gotenberg:8 ``` ## Generate a PDF using Gotenberg As an example, to generate a PDF file of the Upsun website, run the following cURL command: ```bash {location="Terminal"} curl \ --request POST http://yduimhaby523ase4lju3qhimre.gotenberg8.service._.eu-3.platformsh.site/forms/chromium/convert/url \ --form url=https://upsun.com \ --form landscape=true \ --form marginTop=1 \ --form marginBottom=1 \ -o my.pdf ``` --- # Source: https://docs.upsun.com/development/headers.md # HTTP Headers Upsun adds a number of HTTP headers to both inbound and outbound messages. We don’t modify or block existing headers on either request or response. ## Request headers Upsun adds the following HTTP headers in the router to give the application information about the connection. These are stable and may be examined by the application as necessary. * `X-Forwarded-Proto`: The protocol forwarded to the application, for example: `http`, `https`. * `X-Client-IP`: The remote IP address of the request. * `X-Client-SSL`: Set "on" only if the client is using SSL connection, otherwise the header isn't added. * `X-Original-Route`: The route in `.upsun/config.yaml` which is used currently, for example: `https://{default}/`. ## Response headers Upsun adds a number of response headers automatically to assist in debugging connections. These headers should be treated as a semi-private API. Do not code against them, but they may be inspected to help determine how Upsun handled the request to aid in debugging. - `X-Platform-Cache`: Either `HIT` or `MISS` to indicate if the router in your cluster served the response from its own cache or if the request was passed through to the application. - `X-Platform-Cluster`: The ID of the cluster that received the request. The cluster name is formed from the project ID and environment ID. - `X-Platform-Processor`: The ID of the container that generated the response. The container ID is the cluster ID plus the container name. - `X-Platform-Router`: The ID of the router that served the request. The router ID is the processor ID of the router container, specifically. - `X-Debug-Info`: This is a header added by the edge layer. It doesn't contain any sensitive information or anything that could be misused. It has no relation to the PHP debugging tool [Xdebug](https://xdebug.org). ## Classification data headers Upsun sends classification data to your backend system through the following HTTP headers. | HTTP header | Type | Description | | -------------------- | ------- | --------------------------------------------------------------------------------------------------------- | | `Client-Cdn` | string | When a CDN that is supported by Upsun is used, this header displays its name (Fastly, Cloudflare, or Cloudfront). | | `Client-Country` | string | The two-character ISO 3166-1 country code of the end-client IP (after CDN handling for the CDNs that Upsun supports). The geolocation data sent through this header is provided by [MaxMind GeoLite2](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data).| | `Client-Abuse-Score` | integer | The abuse score of the end-client IP. A score >= 100 indicates a near certainty that the request comes from an abusive IP. The abuse data sent through this header is provided by [AbuseIPDB](https://www.abuseipdb.com/). | | `Client-Asn` | integer | The Autonomous System number of the end-client IP. The geolocation data sent through this header is provided by [MaxMind GeoLite2](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data).| ## Custom headers Apart from those listed above, your application is responsible for setting its own response headers. You can also [add headers to static files](https://docs.upsun.com../create-apps/web/custom-headers.md). --- # Source: https://docs.upsun.com/add-services/headless-chrome.md # Headless Chrome Headless Chrome is a headless browser that can be configured on projects like any other service on Upsun. You can interact with the `chrome-headless` service container using Puppeteer, a Node.js library that provides an API to control Chrome over the DevTools Protocol. Puppeteer can be used to generate PDFs and screenshots of web pages, automate form submission, and test your project's UI. You can find out more information about using Puppeteer on [GitHub](https://github.com/GoogleChrome/puppeteer) or in their [documentation](https://pptr.dev/). ## Supported versions You can select the major version. But the latest compatible minor version is applied automatically and can’t be overridden. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 120 ## Deprecated versions The following versions are still available in your projects, but they're at their end of life and are no longer receiving security updates from upstream. - 113 - 95 - 91 - 86 - 84 - 83 - 81 - 80 - 73 To ensure your project remains stable in the future, switch to a [supported version](#supported-versions). ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "service": "chrome-headless", "ip": "123.456.78.90", "hostname": "azertyuiopqsdfghjklm.chrome-headless.service._.eu-1.platformsh.site", "cluster": "azertyuiop-main-7rqtwti", "host": "chrome-headless.internal", "rel": "http", "scheme": "http", "type": "chrome-headless:120", "port": 9222 } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_HEADLESSCHROME_HOST=="$(echo "$RELATIONSHIPS_JSON" | jq -r '.chrome-headless[0].host')" ``` ## Requirements Puppeteer requires at least Node.js version 6.4.0, while using the async and await examples below requires Node 7.6.0 or greater. If your app container uses a language other than Node.js, upgrade the Node.js version before using Puppeteer. See how to [manage your Node.js version](https://docs.upsun.com../languages/nodejs/node-version.md). ## Usage example ### 1. Configure the service To define the service, use the `chrome-headless` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: chrome-headless: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. ### 2. Define the relationship To define the relationship, use the following configuration: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: http ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). ### Example configuration ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: chrome-headless: services: # The name of the service container. Must be unique within a project. chrome-headless: type: chrome-headless:120 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: chrome-headless: service: chrome-headless endpoint: http services: # The name of the service container. Must be unique within a project. chrome-headless: type: chrome-headless:120 ``` ### Use in app After configuration, include [Puppeteer](https://www.npmjs.com/package/puppeteer) as a dependency: ```bash {} pnpm add puppeteer ``` ```bash {} yarn add puppeteer ``` Configuration for a project looks similar to the following: ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" type: "nodejs:24" [...] # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: chrome-headless: services: # The name of the service container. Must be unique within a project. chrome-headless: type: chrome-headless:120 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" type: "nodejs:24" [...] # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: chrome-headless: service: chrome-headless endpoint: http services: # The name of the service container. Must be unique within a project. chrome-headless: type: chrome-headless:120 ``` This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory. `myapp` has access to the `chrome-headless` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship) (as per [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships). From this, `myapp` can retrieve access credentials to the service through the [relationship environment variable](https://docs.upsun.com/add-services/elasticsearch.md#relationship-reference). ```bash {location="myapp/.environment"} # Set environment variables for individual credentials, # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. export CHROME_IP="${CHROME_HEADLESS_IP}" export CHROME_PORT="${CHROME_HEADLESS_PORT}" # Combine into a single base URL to be used within app. export CHROME_BASEURL="http://${CHROME_IP}:${CHROME_PORT}" ``` The above file — `.environment` in the `myapp` directory — is automatically sourced by Upsun into the runtime environment, so that the variable `CHROME_BASEURL` can be used within the application to connect to the service. Note that `CHROME_BASEURL` and all Upsun [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) like `CHROME_HEADLESS_HOST`, are environment-dependent. Unlike the build produced for a given commit, they can't be reused across environments and only allow your app to connect to a single service instance on a single environment. A file very similar to this is generated automatically for your when using the `upsun ify` command to [migrate a codebase to Upsun](https://docs.upsun.com/get-started.md). Puppeteer allows your application to [create screenshots](https://pptr.dev/#?product=Puppeteer&version=v13.0.1&show=api-pagescreenshotoptions), [emulate a mobile device](https://pptr.dev/#?product=Puppeteer&version=v13.0.1&show=api-pageemulateoptions), [generate PDFs](https://pptr.dev/#?product=Puppeteer&version=v13.0.1&show=api-pagepdfoptions), and much more. --- # Source: https://docs.upsun.com/create-apps/hooks/hooks-and-dependencies.md # Use hooks with dependencies If you use a specific package in a hook, you may want to manage dependencies for it. For example, you may want to compile Sass files as part of your build process. You can set dependencies along with hooks in your [app configuration](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#dependencies). The following example assumes you have some Sass source files, such as a `index.scss` file. You also need a script to compile the files, such as the following: ```json {location="package.json"} { "scripts": { "build-css": "sass index.scss css/index.css" }, } ``` Set your app configuration to have Sass available globally and use it: ```yaml {location=".upsun/config.yaml"} applications: myapp: # Ensure sass is available globally dependencies: nodejs: sass: "^1.47.0" hooks: # Run the script defined in package.json build: | npm run build-css ``` --- # Source: https://docs.upsun.com/create-apps/hooks/hooks-comparison.md # Comparison of hooks The following table presents the main differences among the three available hooks: | Hook name | Failures stop build | Variables available | Services available | Timeout | Run on `worker` instances | Writable directories | Blocks requests | Runs on all redeploys\* | | ------------- | ------------------- |-------------------- | ------------------ | ------- | ------------------------- |--------------------------------------------------------| --------------- | --------------- | | `build` | Yes | Build variables | No | 1 hour | Yes | `$PLATFORM_APP_DIR`, `$PLATFORM_CACHE_DIR`, and `/tmp` | No | No | | `deploy` | No | Runtime variables | Yes | None | No | [Mounts](https://docs.upsun.com/create-apps/image-properties/mounts.md) | Yes | No | | `post_deploy` | No | Runtime variables | Yes | None | No | [Mounts](https://docs.upsun.com/create-apps/image-properties/mounts.md) | No | Yes | \* All of the hooks run with changes to the code or environment. This column indicates which hooks run on a redeploy without any code changes. ## Build hook The `build` hook is run after any [build flavor](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#build). During this hook, no services (such as a database) or any persistent file mounts are available as the application hasn't yet been deployed. The `build` hook can access only the variables that are available at build time: - Variables provided by Upsun, as listed in [this table](https://docs.upsun.com../../development/variables/use-variables.md#use-provided-variables) (see the **Build** column) - User-defined project-level or environment-specific build-time variables (**Available during buildtime** is set in the console or the `--visible-build=true` option was set by using the CLI) During the `build` hook, there are three writeable directories: - `$PLATFORM_APP_DIR`: This is where your code is checked out and is the working directory when the `build` hook starts. The contents of this directory after the build hook is the application that gets deployed. - `$PLATFORM_CACHE_DIR`: This directory persists between builds, but isn't deployed as part of your application. It's a good place for temporary build artifacts that can be reused between builds. It's shared by all builds on all branches. - `/tmp`: The temp directory is also useful for writing files that aren't needed in the final application, but it's wiped between each build. Note that `$PLATFORM_CACHE_DIR` is mapped to `/tmp` and together they offer about 8 GB of free space. The only constraint on what can be downloaded during a `build` hook is the disk space available for builds. This is _not_ the disk specified by your [resources configuration](https://docs.upsun.com/manage-resources.md). If you exceed this limit, you receive a `No space left on device` error. See how to [troubleshoot this error](https://docs.upsun.com../troubleshoot-disks.md#no-space-left-on-device). The `build` hook runs only when the app or its runtime (variables and such) have changed. Redeploys with no changes trigger only the `post_deploy` hook. If you need the `build` hook to run, [manually trigger a build](https://docs.upsun.com../../development/troubleshoot.md#manually-trigger-builds). 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 deploy still happens. ### Timeout Build hooks automatically time out if they run for 1 hour. So if you accidentally add an unbroken loop, it gets cut off and you can continue with other activities. ## Deploy hook The `deploy` hook is run after the app container has been started but before it has started accepting requests. Note that the deploy hook only runs on [`web` instances](https://docs.upsun.com/create-apps/image-properties/mounts.md), not [`worker` instances](https://docs.upsun.com/create-apps/image-properties/mounts.md). You can access other services at this stage (such as MySQL, Solr, Redis). The disk where the application lives is read-only at this point. This hook should be used when something needs to run once when new code is deployed. It isn't run when a host is restarted (such as during region maintenance), so anything that needs to run each time an instance of an app starts (regardless of whether there's new code) should go in the `pre_start` key in [your `web` configuration](https://docs.upsun.com/create-apps/image-properties/web.md#web-commands). For example, clearing the cache. Be aware: The deploy hook blocks the site accepting new requests. If your `deploy` hook is only a few seconds, incoming requests in that time are paused and continue when the hook is finished. So it effectively appears as if the site just took a few extra seconds to respond. If the hook takes too long, requests can't be held and appear as dropped connections. Only run tasks in your deploy hook that have to be run exclusively, such as database schema updates or some types of cache clear (those where the code must match what's on the disk). A task that can safely run concurrently with new incoming requests should be run as a `post_deploy` hook instead. After a Git push, in addition to the log shown in the activity log, the execution of the `deploy` hook is logged in the [deploy log](https://docs.upsun.com../../increase-observability/logs/access-logs.md#container-logs). For example: ```bash [2026-03-01 08:27:25.495579] Launching command 'bash export-config.sh'. 🔥 Successfully cleared configuration 🚀 Added new configuration details ``` Your `deploy` hook is tied to commits in the same way as your builds. Once a commit has been pushed and a new build image has been created, the result of both the `build` and `deploy` hooks are reused until there is a new git commit. Redeploys with no changes trigger only the `post_deploy` hook. If you need the `deploy` hook to run, [manually trigger a build](https://docs.upsun.com../../development/troubleshoot.md#manually-trigger-builds). ## Post-deploy hook The `post_deploy` hook functions exactly the same as the `deploy` hook, but after the container is accepting connections. It runs concurrently with normal incoming traffic. That makes it well suited to any updates that don't require exclusive database access. What's "safe" to run in a `post_deploy` hook vs. in a `deploy` hook varies by the application. Often times content imports, some types of cache warmups, and other such tasks are good candidates for a `post_deploy` hook. In addition to the activity log, the `post_deploy` hook logs to the [post-deploy log](https://docs.upsun.com../../increase-observability/logs/access-logs.md#container-logs). The `post_deploy` hook is the only hook that runs during a redeploy. **Make sure the scripts in your `post_deploy` hook are written to be idempotent** (safe to run multiple times) or have checks against duplication. --- # Source: https://docs.upsun.com/create-apps/hooks.md # Source: https://docs.upsun.com/create-apps/image-properties/hooks.md # hooks A hooks dictionary that defines which commands run at different stages in the build and deploy process. Optional in [single-runtime](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](https://docs.upsun.com/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](https://docs.upsun.com/create-apps/image-properties/workers.md), while [web instances](https://docs.upsun.com/create-apps/image-properties/web.md) run all three. The process is ordered as: - Variables accessible at build time become available. - The ``build`` hook is run. - The file system is changed to read only, except for any [mounts](https://docs.upsun.com/create-apps/image-properties/mounts.md). - The app container starts. Variables accessible at runtime and services become available. - The ``deploy`` hook is run. - The app container begins accepting requests. - 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](https://docs.upsun.com/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 8 GB 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 Upsun 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. --- # Source: https://docs.upsun.com/environments/http-access-control.md # Configure HTTP access control When developing your site, you might want to hide your preview environments from outside viewers. Or you may find you have performance issues from [excessive bot access](https://support.platform.sh/hc/en-us/community/posts/16439634723858). You can control access with a username and password **or** by allowing/denying specific IP addresses or networks. This setting applies to the entire environment. The settings for a specific environment are inherited by all of its children. So if you have a `staging` environment and you [branch environments from it](https://docs.upsun.com/glossary.md#branch), all of the environments branched from it inherit the same authentication information. Changing access control triggers a new deploy of the current environment. The changes don't propagate to child environments until they're [redeployed manually](https://docs.upsun.com../development/troubleshoot.md#force-a-redeploy). ## Use a username and password You can set up one or more combinations of a username and password. To add a username and password, follow these steps: Run the following command: ```bash {} upsun environment:http-access -e --auth : ``` For example, to add the username ``name`` with the password ``12321`` to the ``test`` environment, run: ```bash {} upsun environment:http-access -e test --auth name:12321 ``` ## Filter IP addresses Alternatively, you can control access to environments by allowing or denying specific IP addresses or ranges of IP addresses. The addresses should be in the [CIDR format](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing). Both`4.5.6.7` and `4.5.6.0/8` are accepted formats. Note that `allow` entries should come before `deny` entries in case they both match. For example, the following configuration allows only the IP `198.51.100.0` to access your website. ```txt 198.51.100.0 allow 0.0.0.0/0 deny ``` **Pick your authentication method**: When you set up IP filtering authentication, make sure no [username and password are defined](#use-a-username-and-password) for your environment. Otherwise, your environment will remain accessible through the defined username and password combination, regardless of your IP filtering settings. To control access based on IP address, follow these steps: Run the following command: ```bash {} upsun environment:http-access -e --access allow: --access deny: ``` --- # Source: https://docs.upsun.com/learn/bestpractices/http-caching.md # HTTP caching You can configure HTTP caching for your site on Upsun in several ways. Which one you should use depends on your specific use case. You should use only one of these at a time and disable any others. Mixing them together most likely results in stale cache that can't be cleared. ## The Upsun router cache Every project includes a router instance that includes [optional HTTP caching](https://docs.upsun.com/define-routes/cache.md). It's reasonably configurable and obeys HTTP cache directives, but doesn't support push-based clearing. If you're uncertain what caching tool to use, start with this one. It's enough for most uses. ## A Content Delivery Network (CDN) Upsun is compatible with most commercial CDNs. CDNs generally offer the best performance as they're the only option that includes multiple geographic locations. But they do tend to be the most expensive option. See more on setting up [Fastly](https://docs.upsun.com/domains/cdn/fastly.md) and [Cloudflare](https://docs.upsun.com/domains/cdn/cloudflare.md). The methods for other CDNs are similar. ## Varnish Upsun offers a [Varnish service](https://docs.upsun.com/add-services/varnish.md) that you can insert between the router and your app. It has roughly the same performance as the router cache. Varnish is more configurable, but it requires you to be comfortable with Varnish Configuration Language (VCL). Upsun doesn't help with VCL configuration and a misconfiguration may be difficult to debug. Varnish supports [clearing cache with a push](https://docs.upsun.com/add-services/varnish.md#clear-cache-with-a-push), but access control is complicated by the inability to have [circular relationships](https://docs.upsun.com/add-services/varnish.md#circular-relationships). Generally speaking, you should use Varnish only if your application requires push-based clearing or relies on Varnish-specific business logic. ## App-specific caching Many web apps and frameworks include a built-in web cache layer that mimics what Varnish or the Router cache would do. Most of the time they're slower than a dedicated caching service as they still require invoking the app server and only serve as a fallback for users that don't have a dedicated caching service available. Generally speaking, use app-specific web cache only when it includes app-specific business logic you depend on, such as app-sensitive selective cache clearing or partial page caching. Note that this refers only to HTTP caching. Many apps have an internal app cache for data objects and similar information. That should remain active regardless of the HTTP cache in use. ## Cookies and caching HTTP-based caching systems generally default to including cookie values in cache keys to avoid serving authenticated content to the wrong user. While this is a safe default, it means that *any* cookie effectively disables the cache, including mundane cookies like analytics. The solution is to set which cookies should impact the cache and limit them to session cookies. For the router cache, see [cookies in HTTP caching](https://docs.upsun.com/define-routes/cache.md#cookies). For other cache systems, consult their documentation. --- # Source: https://docs.upsun.com/increase-observability/metrics/http-metrics.md # HTTP metrics The HTTP metrics dashboard provides Upsun users with network-related metrics. Those insights are designed to help them better understand the state of their applications. Those metrics can be accessed by clicking the **HTTP metrics** tab on the environment page within the console. The HTTP metrics dashboard can help you: - Verify if there were any recent spikes in error responses - Check bandwidth consumption to determine if there were any service interruptions - Identify specific URLs causing site-wide issues - Prioritize performance optimization (see [application metrics](https://docs.upsun.com../application-metrics.md)) ## HTTP requests status graph The **HTTP requests** graph provides an aggregated view of the health of HTTP requests made to the application. It reflects the status responses (e.g. 1XX, 2XX, 3XX, 4XX, 5XX) of HTTP requests across a defined time frame. This graph helps identify surge of error responses or periods of elevated request activity. ## Bandwidth usage graph The **Bandwidth** graph displays the data transfer volume. It represents incoming (data the app receives) and outgoing (data the app sends) bandwidth usage over time. This graph helps identify bandwidth bottlenecks, optimize resource allocation, and track bandwidth usage. ## Top 10 most impactful URLs The **Top 10 URL Impact** graph and list pinpoint high-traffic or resource-intensive URLs for targeted optimization or investigation. It showcases the evolution over time of the top-10 most impactful URLs during a given time frame. This graph helps identify potential trouble spots, understand user behavior, and prioritize areas for optimization. **Note**: For security and privacy reasons, all URLs undergo the following sanitization measures: - All query parameters (``?param=value``) are sanitized to prevent leakage of sensitive information. - URLs exceeding 2048 characters are truncated to adhere to security best practices. - Specific sensitive URL paths are proactively scrubbed and anonymized. --- # Source: https://docs.upsun.com/define-routes/https.md # HTTPS Using HTTPS for your site helps ensure your users' information remains secure. HTTPS provides enhanced security thanks to the following characteristics: - With HTTPS, data is encrypted so user activity can't be tracked and user information can't be stolen. - HTTPS prevents the corruption of files transferred from a web server to a website and vice-versa. - HTTPS also authenticates websites, which helps build trust with your users. To enable HTTPS on your site, you need [Transport Layer Security (TLS) certificates](#tls-certificates). ## TLS certificates Upsun automatically provides TLS certificates for all sites and environments. These certificates are issued at no charge by [Let's Encrypt](https://letsencrypt.org/) and cover most needs. They're valid for 90 days and automatically renewed 28 days before expiration. To use them, you only need to [specify HTTPS routes](https://docs.upsun.com../define-routes/https.md#enable-https). Note that [limitations](https://docs.upsun.com../define-routes/https.md#lets-encrypt-limitations) apply. If you encounter issues with the TLS certificates provided by Upsun, check that [TLS encryption is up-and-running](https://docs.upsun.com../domains/troubleshoot.md#verify-ssltls-encryption). If you don't want to use the TLS certificates provided by Upsun, configure your own [third-party TLS certificates](https://docs.upsun.com../domains/steps/tls.md). ### Let's Encrypt limitations When you use the Let's Encrypt [TLS certificates](#tls-certificates) provided by Upsun, the following limitations apply. Let's Encrypt allows a maximum of 100 hostnames per certificate. You can have 1 Let's Encrypt certificate for each of your environments. If you define both a `{default}` and a `www.{default}` route for each domain you use, you can add up to 50 hostnames. Going over this limitation results in a warning on deploy and no new TLS certificates are issued. If you need more hostnames, you can obtain additional certificates or a wildcard certificate from a [third-party issuer](https://docs.upsun.com../domains/steps/tls.md). Alternatively, consider splitting your project up into multiple Upsun projects. Please note that when using multiple domains, the Common Name (CN) to which the certificate is issued to is not guaranteed to be the same on each certificate renewal. ### Certificate renewals When you use the [TLS certificates](#tls-certificates) provided by Upsun, certificate renewals occur automatically. These automatic renewals trigger a redeployment, and the following events occur, which can affect the duration of the redeployment: - Any required security and system upgrades are applied to your containers. - The `post_deploy` hook is invoked. **Make sure the scripts in your `post_deploy` hook are written to be idempotent** (safe to run multiple times) or have checks against duplication. ## Enable HTTPS **Before adding routes to your Upsun project, you must configure your DNS records** so that each route’s hostname resolves to the project’s assigned target (for example, via CNAME or appropriate DNS records). If DNS doesn’t point to your project, certificate renewal will fail. To enable HTTPS, add a routing configuration similar to the following: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": type: upstream upstream: "myapp:http" "https://www.{default}/": type: redirect to: "https://{default}/" ``` All traffic to your domain is then sent to your app. The `www` subdomain redirects to the [default domain](https://docs.upsun.com../define-routes.md#default). This also includes redirecting requests from HTTP to HTTPS. For more information, see how to [define routes](https://docs.upsun.com../define-routes.md). ## Optional: Configure TLS connections When you [specify HTTPS routes](#enable-https), you can use the `tls` setting to further configure your TLS connections. ### Enforce TLS 1.3 Although you can still use TLS 1.2, TLS 1.3 is faster and more secure. To instruct your web server to automatically reject TLS 1.2 connections, enforce TLS 1.3 using the `min_version` setting: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": # ... tls: min_version: TLSv1.3 ``` Note that TLS versions older than 1.2 are deprecated and are rejected by default. ### Enable HTTP Strict Transport Security (HSTS) [HSTS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security) forces clients to always communicate with your site over HTTPS. To enable HSTS, use `strict_transport_security` in a configuration similar to the following: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": # ... tls: strict_transport_security: enabled: true include_subdomains: true preload: true ``` The following table presents the possible properties for `strict_transport_security`: | Name | Type | Default | Description | |----------------------|-----------|---------|------------------------------------------------------------------------------------------------| | `enabled` | `boolean` | `null` | If set to `true`, HSTS is enabled for 1 year. If set to `false`, other properties are ignored. | | `include_subdomains` | `boolean` | `false` | To specify whether HSTS applies to all subdomains. | | `preload` | `boolean` | `false` | To add your website to the [HSTS preload list](https://hstspreload.org/). Thanks to this list, most browsers are informed that your site requires HSTS before an HSTS header response is even issued. | Note that when you enable or disable HSTS, the entire domain is affected. Make sure you only add the HSTS configuration to a single route. Having different routes with conflicting HSTS configurations can cause issues. ### Enable mTLS Standard TLS connections are useful to verify the identity of web servers and their certificates. But you can also instruct your web server to verify the identity of clients and their certificates. This allows you to restrict access to trusted users. To do so, enable mTLS by adding the following configuration: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": # ... tls: client_authentication: "require" ``` By default, all valid TLS certificates issued by a legitimate certificate authority are accepted. But you can instruct your web server to only accept TLS certificates issued by specific or even custom certificate authorities. To do so, add a configuration similar to the following: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": # ... tls: client_authentication: "require" client_certificate_authorities: - !include type: string path: root-ca1.crt - !include type: string path: root-ca2.crt ``` In this case, the certificate files are resolved relative to the `.upsun` directory. Alternatively, you can specify the certificates inline in the file: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": # ... tls: client_authentication: "require" client_certificate_authorities: - | -----BEGIN CERTIFICATE----- ### Several lines of characters here ### -----END CERTIFICATE----- - | -----BEGIN CERTIFICATE----- ### Several lines of different characters here ### -----END CERTIFICATE----- ``` If you want to request a client certificate without _requiring_ the client to send one, you can set this by using `request` as a value for `client_authentication`: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": # ... tls: client_authentication: "request" # ... ``` Requests on routes with mTLS configured that are passed through to your app will contain additional headers such as `X-Client-Verify` (with values like `Success` or `None` depending on whether a client certificate was presented and validated or not) and `X-Client-Cert` (with information about the client certificate that was used) that your application can use as required. --- # Source: https://docs.upsun.com/create-apps/image-properties.md # Image properties **Note:** The properties below are available in **both** [single-runtime image](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#) and [composable image](https://docs.upsun.com/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](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#) topic or the primary application properties described in the [composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md#) topic. --- # Source: https://docs.upsun.com/increase-observability.md # Increase observability Observability refers to the capability to evaluate the current state of an application and its architecture by analyzing metrics, traces and logs. Observability is key to the success of your Upsun projects by empowering you with: - **Optimized performance**: monitor how your applications perform in real-time and identify bottlenecks or inefficiencies - **Resource efficiency**: Better understand your application's resource utilization and make informed decisions to correctly scale them. - **Rapid troubleshooting**: swiftly pinpoint issues in your projects by identifying their root causes. - **Synthetic monitoring**: Automatically runs performance tests on all your branch and proactively identify and fix any performance regression. --- # Source: https://docs.upsun.com/add-services/influxdb.md # InfluxDB (Database service) InfluxDB is a time series database optimized for high-write-volume use cases such as logs, sensor data, and real-time analytics. It exposes an HTTP API for client interaction. See the [InfluxDB documentation](https://docs.influxdata.com/influxdb) for more information. ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 2.7 - 2.3 ## Deprecated versions The following versions are still available in your projects, but they're at their end of life and are no longer receiving security updates from upstream. - 2.2 - 2.1 - 2.0 - 1.8 - 1.7 - 1.3 - 1.2 To ensure your project remains stable in the future, switch to a [supported version](#supported-versions). See more information on [how to upgrade to version 2.3 or later](#upgrade-to-version-23-or-later). ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "host": "influxdb.internal", "hostname": "azertyuiopqsdfghjklm.influxdb.service._.eu-1.platformsh.site", "cluster": "azertyuiopqsdf-main-bvxea6i", "service": "influxdb", "type": "influxdb:2.7", "rel": "influxdb", "scheme": "http", "username": "admin", "password": "ChangeMe", "port": 8086, "path": null, "query": { "org": "main", "bucket": "main", "api_token": "azertyuiopqsdfghjklm1234567890" }, "fragment": null, "public": false, "host_mapped": false, "ip": "123.456.78.90" } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_INFLUXDB_HOST="$(echo $RELATIONSHIPS_JSON | jq -r '.influxdb[0].host')" ``` ## Usage example ### 1. Configure the service To define the service, use the `influxdb` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: influxdb: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. ### 2. Define the relationship To define the relationship, use the following configuration: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: influxdb ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). ### Example configuration ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: influxdb: services: # The name of the service container. Must be unique within a project. influxdb: type: influxdb:2.7 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: influxdb: service: influxdb endpoint: influxdb services: # The name of the service container. Must be unique within a project. influxdb: type: influxdb:2.7 ``` ### Use in app To use the configured service in your app, add a configuration file similar to the following to your project. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" [...] # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: influxdb: service: influxdb: type: influxdb:2.7 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" [...] # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: influxdb: service: influxdb endpoint: influxdb service: influxdb: type: influxdb:2.7 ``` This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory. `myapp` has access to the `influxdb` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship) (as per [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships). From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference). ```bash {location="myapp/.environment"} # Set environment variables for common InfluxDB credentials. # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. export INFLUX_USER="${INFLUXDB_USERNAME}" export INFLUX_HOST="${INFLUXDB_HOST}" export INFLUX_ORG="$(echo "$INFLUXDB_QUERY" | jq -r '.org')" export INFLUX_TOKEN="$(echo "$INFLUXDB_QUERY" | jq -r '.api_token')" export INFLUX_BUCKET="$(echo "$INFLUXDB_QUERY" | jq -r '.bucket')" ``` The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``INFLUX_HOST`` can be used within the application to connect to the service. Note that ``INFLUX_HOST``, and all [Upsun-service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) like ``INFLUXDBDATABASE_HOST``, are environment-dependent. Unlike the build produced for a given commit, they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment. A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](https://docs.upsun.com/get-started.md). ## Export data To export your data from InfluxDB, follow these steps: 1. Install and set up the [`influx` CLI](https://docs.influxdata.com/influxdb/cloud/tools/influx-cli/). 2. Connect to your InfluxDB service with the [Upsun CLI](https://docs.upsun.com../administration/cli/_index.md): ```bash upsun tunnel:single ``` This opens an SSH tunnel to your InfluxDB service on your current environment and produces output like the following: ```bash SSH tunnel opened to at: http://127.0.0.1:30000 ``` 3. Get the username, password and token from the [relationship](#relationship-reference) by running the following command: ```bash upsun relationships -P ``` 4. Adapt and run [InfluxDB's CLI export command](https://docs.influxdata.com/influxdb/v2.3/reference/cli/influx/backup/). ```bash influx backup --host --token ``` ## Upgrade to version 2.3 or later ### From a previous 2.x version From version 2.3 onward, the structure of relationships changes. If you're using a prior 2.x version, your app might currently rely on pulling the `bucket`, `org`, `api_token`, or `user` values available in the [`PLATFORM_RELATIONSHIPS` environment variable](#relationship-reference). If so, to ensure your upgrade is successful, make the following changes to your connection logic: - Rename the `user` key to `username`. - Move the `org`, `bucket` and `api_token` keys so they're contained in a dictionary under the `query` key. If you're relying on any other attributes connecting to InfluxDB, they remain accessible as environment variable from the [service environment variable](#relationship-reference), aside from those addressed above: ### From a 1.x version From version 2.3 onward, InfluxDB includes an upgrade utility that can convert databases from previous versions to version 2.3 or later. To upgrade from a 1.x version to 2.3 or later, change the service version in your `.upsun/config.yaml` file and push your project. Any existing data you had in your 1.x system is automatically upgraded for you into the 2.3+ system. **Note**: During an upgrade from a 1.x version to a 2.3 version or later, a new admin password and a new admin API token are automatically generated. Previous credentials can’t be retained. You can retrieve your new credentials through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). --- # Source: https://docs.upsun.com/integrations.md # Integrations --- # Source: https://docs.upsun.com/languages/java.md # Java p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. Java is a general-purpose programming language, and one of the most popular in the world today. Upsun supports Java runtimes that can be used with build management tools such as Gradle, Maven, and Ant. ## Supported versions You can select the major version. But the latest compatible minor version is applied automatically and can’t be overridden. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. ### OpenJDK versions: - 21 - 17 These versions refer to the headless packages of OpenJDK. To save space and reduce potential vulnerabilities, they don't contain GUI classes, which can't be used on the server. ### Specify the language To use Java, specify `java` as your [app's `type`](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#types): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. : type: 'java:' ``` For example: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'java:21' ``` ## Support build automation Upsun supports the most common project management tools in the Java ecosystem, including: * [Gradle](https://gradle.org/) * [Maven](https://maven.apache.org/) * [Ant](https://ant.apache.org/) ### Manage Maven versions Java containers come with a version of Maven already installed. You may need to use a specific different version to manage your project. If the version you need differs from the version on your container, you can install the specific version that you need. Add something like the following to your [app configuration](https://docs.upsun.com../../create-apps/_index.md): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'java:21' variables: env: MAVEN_VERSION: hooks: build: | curl -sfLO "https://dlcdn.apache.org/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz" tar -zxf apache-maven-$MAVEN_VERSION-bin.tar.gz export PATH="$PWD/apache-maven-$MAVEN_VERSION/bin:$PATH" mvn --version mvn clean package ``` ## Other JVM languages It’s worth remembering that the JVM by its specification [doesn't read Java code](https://docs.oracle.com/javase/specs/jvms/se8/html/index.md), but bytecode. So within the JVM, it’s possible to [run several languages](https://en.wikipedia.org/wiki/List_of_JVM_languages). Upsun supports several of them, such as Kotlin, Groovy, and Scala, so long as that language works with any build automation that Upsun supports. | Article | Link | | ------------------------------------------------------------ | ------------------------------------------------------------ | | [Kotlin and Spring](https://devcenter.upsun.com/posts/ready-to-have-fun-try-kotlin-and-spring/) | [Source](https://github.com/platformsh-templates/spring-kotlin) | | [Scala and Spring](https://dzone.com/articles/spring-scala-cloud-psh) | [Source](https://github.com/platformsh-examples/scala) | **Note**: While the table above shows examples for Upsun Fixed rather than for Upsun, the same rules apply with only slight changes in configuration. ## Accessing services You can access service credentials to connect to [managed services](https://docs.upsun.com/add-services/) from environment variables present in the application container. Consult each of the individual service documentation to see how to retrieve and surface credentials into your application. - [Chroma](https://docs.upsun.com/add-services/chroma.md#3-use-the-relationship-in-your-application) - [ClickHouse](https://docs.upsun.com/add-services/clickhouse.md#usage-example) - [Elasticsearch](https://docs.upsun.com/add-services/elasticsearch.md#use-in-app) - [Edgee (Edge Analytics)](https://docs.upsun.com/add-services/edgee.md#setup-edgee) - [Gotenberg](https://docs.upsun.com/add-services/gotenberg.md#usage-example) - [Headless Chrome](https://docs.upsun.com/add-services/headless-chrome.md#use-in-app) - [InfluxDB](https://docs.upsun.com/add-services/influxdb.md#use-in-app) - [Kafka](https://docs.upsun.com/add-services/kafka.md#use-in-app) - [MariaDB/MySQL](https://docs.upsun.com/add-services/mysql.md#use-in-app) - [Memcached](https://docs.upsun.com/add-services/memcached.md#use-in-app) - [Mercure](https://docs.upsun.com/add-services/mercure.md#use-in-app) - [MongoDB](https://docs.upsun.com/add-services/mongodb.md#use-in-app) - [Network Storage](https://docs.upsun.com/add-services/network-storage.md#usage-example) - [OpenSearch](https://docs.upsun.com/add-services/opensearch.md#use-in-app) - [PostgreSQL](https://docs.upsun.com/add-services/postgresql.md#use-in-app) - [Qdrant](https://docs.upsun.com/add-services/qdrant.md#4-use-the-relationship-in-your-application) - [RabbitMQ](https://docs.upsun.com/add-services/rabbitmq.md#use-in-app) - [Redis](https://docs.upsun.com/add-services/redis.md#use-in-app) - [Solr](https://docs.upsun.com/add-services/solr.md#use-in-app) - [Valkey](https://docs.upsun.com/add-services/valkey.md#use-in-app) - [Varnish](https://docs.upsun.com/add-services/varnish.md#usage-example) - [Vault KMS](https://docs.upsun.com/add-services/vault.md#use-vault-kms) --- # Source: https://docs.upsun.com/add-services/kafka.md # Kafka (Message queue service) Apache Kafka is an open-source stream-processing software platform. It is a framework for storing, reading and analyzing streaming data. See the [Kafka documentation](https://kafka.apache.org/documentation) for more information. ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 3.7 ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``. Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) directly rather than hard coding any values. For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "service": "kafka", "ip": "123.456.78.90", "hostname": "azertyuiopqsdfghjklm.kafka.service._.eu-1.platformsh.site", "cluster": "azertyuiop-main-7rqtwti", "host": "kafka.internal", "rel": "kafka", "scheme": "kafka", "type": "kafka:3.7", "port": 9092 } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_KAFKA_HOST="$(echo "$RELATIONSHIPS_JSON" | jq -r '.kafka[0].host')" ``` ## Usage example ### 1. Configure the service To define the service, use the ``kafka`` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: kafka: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. ### 2. Define the relationship To define the relationship, use the following configuration: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container (````) now has [access to the service](https://docs.upsun.com/add-services/kafka.md#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: kafka ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). ### Example configuration ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: kafka: services: # The name of the service container. Must be unique within a project. kafka: type: kafka:3.7 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: kafka: service: kafka endpoint: kafka services: # The name of the service container. Must be unique within a project. kafka: type: kafka:3.7 ``` ### Use in app To use the configured service in your app, add a configuration file similar to the following to your project. ```ruby {} ## With the ruby-kafka gem # Producer require "kafka" kafka = Kafka.new(["kafka.internal:9092"], client_id: "my-application") kafka.deliver_message("Hello, World!", topic: "greetings") # Consumer kafka.each_message(topic: "greetings") do |message| puts message.offset, message.key, message.value end ``` --- # Source: https://docs.upsun.com/languages.md # Languages --- # Source: https://docs.upsun.com/development/local.md # Set up your local development environment To make changes to your app's code and test them without affecting your production environment, set up a local development environment on your computer. For the most effective testing, you want your local environment to match your Upsun environments. The best way to do this is to use a cross-platform tool based on Docker. This ensures the changes you make locally appear as they would on your Upsun environments. It also means you don't have to worry about configuring your machine with the various dependencies, certificates, and connections your app needs to run. The **recommended tool** for local development with Upsun is **[DDEV](https://docs.upsun.com/development/local/ddev.md)**. The integration with DDEV is maintained by Upsun to ensure it works smoothly. If you choose to use DDEV, follow the steps [on its page](https://docs.upsun.com/development/local/ddev.md). Otherwise, follow these steps to run your app on your computer. ## Before you begin You need to have: - A Upsun account: new users can [register here](https://upsun.com/register/) - A working project - [Git](https://git-scm.com/downloads) - The [Upsun CLI](https://docs.upsun.com../../administration/cli.md) ## 1. Get your code If you don't have your app code on your computer, download a copy. 1. Get your project ID by running `upsun projects`. 2. Get the code by running the following command: ```bash upsun get ``` Or pull from your [integrated Git repository](https://docs.upsun.com../../integrations/source.md). You can now access your code from the project directory on your computer. The CLI created a `.upsun/config.yaml/local` directory that's excluded from Git. It contains builds and local metadata about your project. You can now make changes to your project without pushing to Upsun each time to test them. Instead, you can locally build your application using the Upsun CLI. Note that if your app contains services, you need to open an SSH tunnel to connect to them. For more information, see how to [connect services](https://docs.upsun.com../../add-services#2-define-the-relationship). ## 2. Connect to services If your app requires services to run, you have two options for developing locally: - [Tethered local development](https://docs.upsun.com/development/local/tethered.md) involves running your app on a local web server but keeping all other services on Upsun and connecting to them over an SSH tunnel. - [Untethered local development](https://docs.upsun.com/development/local/untethered.md) involves running your entire site locally, including all services. Choose the option that works for you and get your services running. --- # Source: https://docs.upsun.com/increase-observability/logs.md # Consume logs --- # Source: https://docs.upsun.com/domains/cdn/managed-fastly.md # Managed Fastly CDN Instead of starting your own Fastly subscription and [managing your CDN yourself](https://docs.upsun.com/domains/cdn/fastly.md), you can take advantage of a Fastly CDN provided by Upsun. These CDNs are exclusively set up and managed by Upsun. To modify any settings for a managed Fastly CDN, open a [support ticket](https://docs.upsun.com/learn/overview/get-support.md). To add a managed Fastly CDN to your project, [contact sales](https://upsun.com/contact-us/). **Note**: Upsun does not write nor debug any custom VCL on Managed Fastly CDN services. **Monitor CDN metrics**: You can access a summary of your monthly traffic usage under the “Traffic this month” section at the Project level inside [Console](https://console.upsun.com/). This will help you monitor your monthly bandwidth and requests consumption. In this summary, you will find specific details about: - **Origin Bandwidth:** Data transferred from origin servers (in TB). - **Origin Requests:** Requests served by origin servers (in millions of requests). - **CDN Bandwidth & CDN Requests:** Shown if you have Fastly CDN enabled. This data is updated daily and will reflect your traffic usage throughout the billing period. **Set up traffic alerts**: You can also set up consumption alerts for your resource usage. Click the Alert button in the “Traffic this month” block within [Console](https://console.upsun.com/) to configure usage thresholds. For more information, head to the [Pricing docs page](https://docs.upsun.com/administration/pricing.md). ## How Managed Fastly works Upsun’s Managed Fastly CDN routes incoming traffic through the Fastly edge network before requests reach your application. This enables global caching, edge logic (VCL), performance optimisation, and optional security features. The Fastly CDN must be provisioned and managed by Upsun. Features such as the Upsun Web Application Firewall (WAF), edge rate limiting, and image optimization depend on this managed integration and cannot be used with a customer-managed Fastly account. Once enabled, Fastly operates as the first point of contact for all HTTP requests, allowing requests to be cached, filtered, transformed, or blocked entirely at the edge. **Feature dependencies**: - The Upsun WAF requires the Upsun Managed Fastly CDN. - Customers cannot attach the WAF to an existing third-party Fastly service. - Advanced Fastly features such as virtual patching and per-project logging require a configurable Fastly workspace. ### Domain control validation When you request for a new domain to be added to your Fastly service, Upsun [support](https://docs.upsun.com/learn/overview/get-support.md) provides you with a [`CNAME` record](https://docs.upsun.com/domains/steps/dns.md) for [domain control validation](https://docs.upsun.com/domains/troubleshoot.md#ownership-verification). To add this `CNAME` record to your domain settings, see how to [configure your DNS provider](https://docs.upsun.com/domains/steps.md#2-configure-your-dns-provider). ### Transport Layer Security (TLS) certificates By default, two [TLS certificates](https://docs.upsun.com/glossary.md#transport-layer-security-tls) are included: an apex and a wildcard one. This allows for encryption of all traffic between your users and your app. If you use a Fastly CDN provided by Upsun, you can provide your own third-party TLS certificates for an additional fee. To do so, if you don't have one, set up a [mount](https://docs.upsun.com/create-apps/image-properties/mounts.md) that isn't accessible to the web. Use an environment with access limited to Upsun support and trusted users. [Transfer](https://docs.upsun.com/development/file-transfer.md) each certificate, its unencrypted private key, and the intermediate certificate to the mount. To notify Upsun that a certificate is to be added to your CDN configuration, open a [support ticket](https://docs.upsun.com/learn/overview/get-support.md). If you need an Extended Validation TLS certificate, you can get it from any TLS provider. To add it to your CDN configuration, open a [support ticket](https://docs.upsun.com/learn/overview/get-support.md). Note that when you add your own third-party TLS certificates, you are responsible for renewing them in due time. Failure to do so may result in outages and compromised security for your site. ### Retrieve your Fastly API token The API token for your managed Fastly CDN is stored in the `FASTLY_API_TOKEN` or the `FASTLY_KEY` environment variables. This variable is usually set in the `/master/settings/variables` folder of your project, and you can access it [from a shell](https://docs.upsun.com/development/variables/use-variables.md#access-variables-in-a-shell) or directly [in your app](https://docs.upsun.com/development/variables/use-variables.md#access-variables-in-your-app). ## Dynamic ACL and rate limiting For details about updating an access control list (ACL) and applying rate limiting, check out the [Working with Upsun rate-limiting implementation](https://support.platform.sh/hc/en-us/articles/29528777071890-Upsun-Fastly-Rate-Limiting-How-it-works-how-to-tune-it) article in the Upsun Community. ## Edge-level rate limiting Upsun provides edge-level rate limiting through Fastly, allowing you to control how many requests a single IP address or network can make within a given time window. Rate limiting is applied at the edge, before requests reach your application, helping to reduce load and mitigate abusive traffic patterns. ### What Edge-level rate limiting can do - Protect sensitive endpoints such as `/login`, `/admin`, or checkout paths - Limit request floods from a single IP or IP range - Reduce application load during traffic spikes - Enable Upsun Support to better handle attacks or high-traffic events by throttling traffic at the edge Edge-level rate limiting is available as a standalone add-on (without the WAF). ### Configuration and defaults There are no default rate-limiting rules applied automatically. Rate limiting is configured during onboarding, or by request via Upsun [Support](https://docs.upsun.com/learn/overview/get-support.md). Rules can be scoped by: - Request path - Request type - IP address or network - Custom thresholds and actions (block, allow, log) ### Limitations Edge-level rate limiting is a rule-based control mechanism, not an automated bot-detection system. It does not: - Identify bots automatically - Present CAPTCHA or JavaScript challenges - Provide AI-driven mitigation For advanced bot and scraper protection, Upsun offers separate third-party integrations. --- # Source: https://docs.upsun.com/development/sanitize-db/mariadb.md # Sanitizing databases: MariaDB and Drupal Databases of live websites often contain personally identifiable information (PII) such as full names, mailing addresses, and phone numbers. To ensure people reviewing code changes can't access information they shouldn't, sanitize your databases of any PII that they may contain. This example goes through the process for a MySQL database using Drupal. ## Before you begin You need: - A project with a [MySQL database](https://docs.upsun.com../../add-services/mysql.md). - A command interface installed: - If doing it manually, the [Upsun CLI](https://docs.upsun.com../../administration/cli.md). - Otherwise, make sure [Drush](https://www.drush.org/latest/install/) is installed in your environment. This guide is about sanitizing MySQL databases. This guide doesn't address: - Sanitizing NoSQL Databases (such as [MongoDB](https://docs.upsun.com../../add-services/mongodb.md)) - Input validation and input sanitization, which both help prevent security vulnerabilities ## Sanitize the database Make sure that you only sanitize preview environments and **never** the production environment. Otherwise you may lose most or even all of the relevant data stored in your database. First, take a [database dump](https://docs.upsun.com../../add-services/mysql.md#exporting-data) of your preview environment. This is just a safety precaution. Production data isn't altered. To get a database dump, run the following command: ``upsun db:dump -e ``. You see output like the following: ```sql {} +----+------------+---------------+---------------------------+---------------+ | ID | first_name | last_name | user_email | display_name | +----+------------+---------------+---------------------------+---------------+ | 1 | admin | admin | admin@yourcompany.com | admin | | 2 | john | doe | john.doe@gmail.com | john | | 3 | jane | doe | janedoe@ymail.com | jane | +----+------------+---------------+---------------------------+---------------+ ``` - Change the fields where PII is contained with the [UPDATE](https://mariadb.com/kb/en/update/). For example, to change the display name of users with an email address not in your company’s domain to a random value, run the following query: ```sql {} UPDATE users SET display_name==substring(md5(display_name||'$PLATFORM_PROJECT_ENTROPY') for 8); WHERE email NOT LIKE '%@yourcompany%' ``` Adapt and run that query for all fields that you need to sanitize. If you modify fields that you shouldn’t alter, [you can restore them](https://docs.upsun.com/environments/restore.md) from the dump you took in step 1. You can create a script to automate the sanitization process to be run automatically on each new deployment. Once you have a working script, add your script to sanitize the database to [a ](https://docs.upsun.com/create-apps/hooks/hooks-comparison.md#deploy-hook): .upsun/config.yaml ```yaml {} applications: myapp: # ... hooks: deploy: | # ... cd /app/public if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then # Do whatever you want on the production site. else # The sanitization of the database should happen here (since it's non-production) sanitize_the_database.sh fi ``` To sanitize your database and get rid of sensitive, live information, use the ``drush sql:sanitize`` command. Add your script to sanitize the database to [a ](https://docs.upsun.com/create-apps/hooks/hooks-comparison.md#deploy-hook) for preview environments: .upsun/config.yaml ```yaml {} applications: myapp: hooks: deploy: | # ... cd /app/public if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then # Do whatever you want on the production site. else drush -y sql:sanitize fi drush -y updatedb ``` More options are available. These are described in the [Drush documentation](https://www.drush.org/latest/commands/sql_sanitize/). To sanitize only on the initial deploy and not all future deploys, use [Drush state](https://www.drush.org/latest/commands/state_set/) as in the following example: .upsun/config.yaml ```yaml {} applications: myapp: hooks: deploy: | # ... cd /app/public if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ] || [ "$(drush state:get --format=string mymodule.sanitized)" != yes ]; then # Do whatever you want on the production site. else drush -y sql:sanitize drush state:set --input-format=string mymodule.sanitized yes fi ``` ## What's next You learned how to remove sensitive data from a database. To replace sensitive data that with other meaningful data, you can add a `faker` to the process. A `faker` is a program that generates fake data that looks real. Having meaningful PII-free data allows you to keep your current Q&A, external reviews, and other processes. To add a faker, adapt your sanitizing queries to replace each value that contains PII with a new value generated by the faker. You might also want to make sure that you [implement input validation](https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.md#goals-of-input-validation). If your database contains a lot of data, consider using the [`OPTIMIZE TABLE` statement](https://mariadb.com/kb/en/optimize-table/) to reduce its size and help improve performance. --- # Source: https://docs.upsun.com/add-services/memcached.md # Memcached (Object cache) Memcached is a simple in-memory object store well-suited for application level caching. See the [Memcached documentation](https://memcached.org) for more information. Both Memcached and Redis can be used for application caching. As a general rule, Memcached is simpler and thus more widely supported while Redis is more robust. Upsun recommends using Redis if possible but Memcached is fully supported if an application favors that cache service. ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 1.6 ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "service": "memcached", "ip": "123.456.78.90", "hostname": "azertyuiopqsdfghjklm.memcached.service._.eu-1.platformsh.site", "cluster": "azertyuiopqsdf-main-afdwftq", "host": "memcached.internal", "rel": "memcached", "scheme": "memcached", "type": "memcached:1.6", "port": 11211 } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_MEMCACHED_HOST="$(echo "$RELATIONSHIPS_JSON" | jq -r '.memcached[0].host')" ``` ## Usage example ### 1. Configure the service To define the service, use the ``memcached`` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: memcached: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. ### 2. Define the relationship To define the relationship, use the following configuration: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ":memcached" ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). For PHP, enable the [extension](https://docs.upsun.com/languages/php/extensions.md) for the service: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # PHP extensions. runtime: extensions: - memcached # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # PHP extensions. runtime: extensions: - memcached # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ":memcached" ``` For Python, include the proper dependency: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Build dependencies per runtime. dependencies: python: python-memcached: '*' # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Build dependencies per runtime. dependencies: python: python-memcached: '*' # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ":memcached" ``` ### Example configuration ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: memcached: services: # The name of the service container. Must be unique within a project. memcached: type: memcached:1.6 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: memcached: "memcached:memcached" services: # The name of the service container. Must be unique within a project. memcached: type: memcached:1.6 ``` ### Use in app To use the configured service in your app, add a configuration file similar to the following to your project. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" # PHP extensions. runtime: extensions: - memcached [...] # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: memcached: service: memcached: type: memcached:1.6 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" # PHP extensions. runtime: extensions: - memcached [...] # Relationships enable access from this app to a given service. # See the Application reference for all options for defining relationships and endpoints. relationships: memcached: service: memcached endpoint: memcached service: memcached: type: memcached:1.6 ``` This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory. `myapp` has access to the `influxdb` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship) (as per [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships). From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference). ```bash {location="myapp/.environment"} # Surface a Memcached connection string for use in app. # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. export CACHE_URL="${MEMCACHED_HOST}:${MEMCACHED_PORT}" ``` The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``CACHE_URL`` can be used within the application to connect to the service. Note that ``CACHE_URL``, and all Upsun [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) like ``MEMCACHEDCACHE_HOST``, are environment-dependent. Unlike the build produced for a given commit, they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment. A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](https://docs.upsun.com/get-started.md). ## Accessing Memcached directly To access the Memcached service directly you can use `netcat` as Memcached doesn't have a dedicated client tool. Assuming your Memcached relationship is named `memcached`, the host name `MEMCACHED_HOST` and port number `MEMCACHED_PORT` obtained from the [service environment variable](#relationship-reference) would be `memcached.internal` and `11211`. Open an [SSH session](https://docs.upsun.com/development/ssh.md) and access the Memcached server as follows: ```bash {location="Terminal"} netcat memcached.internal 11211 ``` You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``. Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) directly rather than hard coding any values. --- # Source: https://docs.upsun.com/add-services/mercure.md # Mercure [Mercure](https://mercure.rocks/) is a real-time communication protocol and hub designed for modern web apps. It allows servers to instantly push updates to browsers, mobile clients, and backend workers through Server-Sent Events (SSE). Built for simplicity and performance, Mercure is widely used in the Symfony ecosystem and beyond for reactive UIs, real-time notifications, and live data streaming. ## Supported versions You can select the major version. The latest compatible minor version is applied automatically and can’t be overridden. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 0 ## JWT Token Secret The service generates the JSON Web Token (JWT) token secret. It's available in the `password` field of the Mercure relationship in the `PLATFORM_RELATIONSHIPS` environment variable. ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "mercure": [ { "username": null, "fragment": null, "ip": "123.456.78.90", "cluster": "sample-cluster-id-12345", "host": "mercure.internal", "path": null, "query": {}, "relationships_env_var_extra": {}, "port": 3000, "host_mapped": false, "password": "ChangeMe", "service": "mercure", "hostname": "sample-hostname.mercure.service.platformsh.site", "epoch": 0, "instance_ips": [ "123.456.789.001" ], "rel": "mercure", "scheme": "http", "type": "mercure:0", "public": false } ] } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_MERCURE_HOST="$(echo $RELATIONSHIPS_JSON | jq -r '.mercure[0].host')" ``` ## Usage example ### 1. Configure the service To define the service, use the `mercure` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: mercure:0 disk: 256 ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. ### 2. Define the route To access the service URL, add an entry to the `.routes` key as shown below, replacing with the name of your app: ```yaml {location=".upsun/config.yaml"} routes: "https://mercure.{default}/": type: upstream upstream: ":mercure" ``` ### 3. Define the relationship Define the relationship to the app as shown below: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : "mercure:mercure" ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: mercure ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). ### Example configuration ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mercure: services: # The name of the service container. Must be unique within a project. mercure: type: mercure:0 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mercure: "mercure:mercure" services: # The name of the service container. Must be unique within a project. mercure: type: mercure:0 ``` ### Use in app To use the configured service in your app, add a configuration file similar to the following to your project. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" [...] # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mercure: services: mercure: type: mercure:0 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" [...] # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mercure: service: mercure endpoint: mercure services: mercure: type: mercure:0 ``` This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory. `myapp` has access to the `mercure` service via a relationship whose name is [identical to the service name](#3-define-the-relationship) (as per [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships). From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference). ```bash {location="myapp/.environment"} # Set environment variables for common Mercure credentials. # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. export MERCURE_USER="${MERCURE_USERNAME}" export MERCURE_HOST="${MERCURE_HOST}" export MERCURE_QUERY="${$MERCURE_QUERY}" ``` The ``.environment`` shown above in the ``myapp`` directory is automatically sourced by Upsun into the runtime environment, so that the variable ``MERCURE_HOST`` can be used within the application to connect to the service. Note that all [Upsun service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) such as ``MERCURE_HOST`` are environment-dependent. Unlike the build produced for a given commit, they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment. A file very similar to this is generated automatically for your when using the ``upsun project:init`` [command](https://docs.upsun.com/administration/cli/reference.md#projectinit) to migrate a codebase to Upsun. --- # Source: https://docs.upsun.com/increase-observability/metrics.md # Infrastructure metrics Upsun projects are accompanied by live infrastructure metrics that provide an overview of resource usage for environments. Within the Console, metrics can be found for an environment under **Resources**. The information under **Resources** shows usage metrics for: Upsun environments: your service, app, and worker containers. These metrics are available for all of your environments. ## Default thresholds All of the graphs show color-coded lines for the following thresholds: - Usage up to _100%_ results. - Usage that crosses _80%_ results. - Usage that crosses _90%_ results. - Usage that crosses _50%_ results. ### Recommendations The default thresholds aim to give you an idea of when your hosts or containers are close to running out of resources. The impact differs based on your specific apps and service. If the resources are hovering close to the 100% threshold, you might want to consider: * [Optimizing your code](https://docs.upsun.com../application-metrics.md) (if possible) * [Changing your app size or service size](https://docs.upsun.com/manage-resources.md) ## Time intervals Measurements are taken for each metric every 1 minute. You can select a time frame over which to see these measurements for the entire **Resources** view. In the primary three views, averages are shown over larger intervals. | View | Time between measurements | Example | | :-------------------------------------------------------------------- | :-------------------------------------------- | :--------------------------- | | The last 15 minutes (*15m*) | 1 minute | 10:00, 10:01, 10:02 | | The last hour (*1hr*) | 1 minute | 10:00, 10:01, 10:02 | | The last 8 hours (*8hr*) | 10 minutes | 10:00, 10:10, 10:20, 11:00 | To zoom in on smaller intervals, select specific ranges in a graph. The interval between measurements then changes based on the range you choose. | View | Time between measurements | | :----------- | :------------------------ | | < 2 hours | 1 minute | | 2 to 5 hours | 5 minutes | | 5+ hours | 20 minutes | ### Longer time intervals You can access historical data for up to 30 days. These data should help you understand trends over time and whether a given measurement is normal, something that occurs occasionally, or a true anomaly. To see data over a given time frame, use the date picker to select the range to display. ## Deployments Sometimes deployment activities (pushes, merges, syncs) can influence the underlying infrastructure. You don't want to confuse a spike caused by a successful deploy with an issue that needs your attention. To see how deployment activity influences the infrastructure, turn on **Deployments** on your metrics. Each deployment activity appears as a line on each graph corresponding to the time the activity finished. - To see information about the deployment activity, hover over the line. - To see the build log for a specific deployment activity, click the line. --- # Source: https://docs.upsun.com/administration/security/mfa.md # Multifactor Authentication (MFA) **Feature Availability** This feature is available as part of the Advanced User Management add-on. You can [upgrade your organization to this add-on](https://docs.upsun.com/administration/billing/add-on-subscription.md#upgrade-to-the-advanced-user-management-add-on) in the Console. For details about the other features included in this add-on, see the [Advanced User Management add-on](https://docs.upsun.com/administration/billing/add-on-subscription.md#advanced-user-management-add-on) help topic section; for pricing information, see the [Upsun pricing](https://upsun.com/pricing/) page. Multifactor Authentication (MFA) enhances security by protecting both your organization and every user account that interacts with it through SSH or the Upsun API. When MFA is enforced within an organization, every project contributor **must** enable MFA on their user account so they can run Git commands, SSH into an environment, or trigger actions through the Upsun API. ## Enable MFA on your user account To access an organization that enforces MFA or any of its projects, you **must** enable MFA on your user account. Failure to do so results in forbidden access to the organization from the Console or API, and an [error message](https://docs.upsun.com/development/ssh/troubleshoot-ssh.md#mfa-related-error-message) when trying to SSH into its environments. To enable MFA on your user account, follow these steps: 1. In the Console, open the user menu (your name or profile picture). 1. Click **My profile**. 1. On the **Authentication Settings** tab, click **Set up application**. 1. Follow the instructions for the chosen authentication app. 1. Click **Verify & save**. 1. Refresh your SSH credentials by running `upsun login -f` in the CLI. ## Enforce MFA within your organization Prerequisites: - You must be an **organization owner** or **admin user**. - Your organization must have the [Advanced User Management add-on](https://docs.upsun.com/administration/billing/add-on-subscription.md#advanced-user-management-add-on). - You must first [enable MFA on _your own_ user account](#enable-mfa-on-your-user-account) as described above. To enforce MFA within your organization, follow these steps: 1. In the Console, select an organization from the organization menu in the upper left of the page. 1. Click the organization name again, and from the expanded menu, click **Security**. On the **Security** tab, in the **User security settings** section, you can see which users in your organization have [activated MFA for their user accounts](#enable-mfa-on-your-user-account). 1. In the **MFA required** section, click the **Enable MFA** toggle to the on position. ### Send email reminders To send email reminders to users who haven't enabled MFA on their account: 1. In the Console, select an organization from the organization menu in the upper left of the page. 2. Click the organization name again, and from the expanded menu, click **Security**. 3. On the **Security** tab, in the **User security settings** section, complete the steps below based on the action you want to take. - To send an email reminder to an individual user, click **More More** beside the user's name and then click **Remind**. - To send an email reminder to multiple users at once, select the checkbox beside the names of the users you want to remind. To remind _all_ of the users who do not have MFA enabled, select the **Name** checkbox at the top of the list. Then, near the **Name** checkbox, click **Remind**. An email is sent to the user with instructions on how to enable MFA on their user account. --- # Source: https://docs.upsun.com/learn/tutorials/migrating.md # Convert to Upsun Fixed Learn how you can convert your site from another hosting solution to Upsun. --- # Source: https://docs.upsun.com/languages/java/migration.md # Moving a Java application to Upsun Fixed p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. It is common to have a Java application that you want to migrate to Upsun. Upsun supports several styles of Java application, such as monolith, microservices, stateful, and stateless. ## Minimum Requirement To run a Java application at Upsun you need: * [A supported Java version](https://docs.upsun.com/languages/java.md#supported-versions) * [A build management tool](https://docs.upsun.com/languages/java.md#support-build-automation) * [Gradle](https://docs.gradle.org/current/userguide/gradle_wrapper.md) * [Maven](https://maven.apache.org/) * [Maven Wrapper](https://www.baeldung.com/maven-wrapper) * [Ant](https://ant.apache.org/) * A Git Repository: * [GitHub](https://docs.upsun.com/integrations/source/github.md) * [BitBucket](https://docs.upsun.com/integrations/source/bitbucket.md) * [GitLab](https://docs.upsun.com/integrations/source/gitlab.md) * The default Git repository provided by Upsun **Note**: A container application can’t be bigger than **8 GB** of memory. For more details, see [tuning](https://docs.upsun.com/languages/java/tuning.md). ## Monolith/Single Application To start a Java application, you need to understand the [Upsun structure](https://docs.upsun.com/learn/overview/structure.md). You will need to configure your [application](https://docs.upsun.com../../create-apps/_index.md), [routes](https://docs.upsun.com../../define-routes.md), and [services](https://docs.upsun.com../../add-services.md). ### Application ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'java:' hooks: build: [2] web: commands: start: [3] ``` 1. [A Java version](https://docs.upsun.com/languages/java.md#supported-versions), e,g.: `java:21` 2. [Hooks define what happens when building the application](https://docs.upsun.com../../create-apps/hooks.md). This build process typically generates an executable file such as a uber-jar. For example, `mvn clean package`. 3. [The commands key defines the command to launch the application](create-apps/image-properties/web.md#web-commands). For example, `java -jar file.jar`. 4. In the start's command needs to receive the port where the application will execute thought the `PORT` environment. That's best when your app follows the port bind principle. For example, `java -jar jar --port=$PORT`. **Note**: Be aware that after the build, it creates a read-only system. You have the [mount option to create a writable folder](https://docs.upsun.com/create-apps/image-properties/mounts.md). ### Route ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": type: upstream upstream: "myapp:http" [1] "https://www.{default}/": type: redirect to: "https://{default}/" applications: myapp: type: 'java:' hooks: build: [2] web: commands: start: [3] ``` 1. It defines the application will link in the route. For example,`"myapp:http"`. **Note**: Application instances have a limited amount of memory at build time, which has a maximum of 8 GB. At runtime that limit depends on [the resources you have defined for your application container](https://docs.upsun.com/manage-resources.md) using ``upsun resources:set``. A stateless application can be scaled horizontally to multiple application instances with ``upsun resources:set`` or by using Varnish in a [load balancer](https://support.platform.sh/hc/en-us/community/posts/16439676899474) configuration. ## Microservices You have the option to use several languages in microservices. If you're using Java there are several options to aggregate these services into a microservices: * [Maven Modules](https://maven.apache.org/guides/mini/guide-multiple-modules.md) * [Gradle Multi-project](https://guides.gradle.org/creating-multi-project-builds/) * [Git submodules](https://docs.upsun.com/development/submodules.md) [Upsun supports multiple applications](https://docs.upsun.com../../create-apps/multi-app.md) and there are two options: * One application YAML file to each application * Aggregate all applications in a single file with an `.upsun/config.yaml` file | Article | Content | | ------------------------------------------------------------ | ------------------------------------------------------------ | | [Microservices in the cloud, part two](https://devcenter.upsun.com/posts/microservices-in-the-cloud-part-two/) | [Source](https://github.com/EventosJEspanol/latin-america-micro-profile) | | [Microservices in the cloud, part one](https://upsun.com/blog/) | [Source](https://github.com/EventosJEspanol/latin-america-micro-profile) | | [Multiple Applications](https://support.platform.sh/hc/en-us/community/posts/16439649733010) | [Source](https://github.com/platformsh-examples/tomcat-multi-app) | | [Configure multi-applications with `.upsun/config.yaml`](https://support.platform.sh/hc/en-us/community/posts/16439676928274) | [Source](https://github.com/platformsh-examples/tomcat-multi-app-applications) | **Note**: You can load balance to some or [all applications in the project cluster](https://support.platform.sh/hc/en-us/community/posts/16439662235026). While the table above shows examples for Upsun Fixed rather than for Upsun Flex, the same rules apply with only slight changes in configuration. ## Access to managed services Upsun provides [managed services](https://docs.upsun.com/add-services.md) such as databases, cache and search engines. However, you can use a database or any services such as a transition process, just be aware of the [firewall](https://docs.upsun.com/create-apps/image-properties/firewall.md). When applications need to access a service, it is important to include the [`relationships` key](https://docs.upsun.com/create-apps/image-properties/relationships.md). By default an application may not talk to any other container without a `relationship` explicitly allowing access. To connect to a service from your deployed application, you need to pass the relationships information into your application's configuration. The way to do so varies with the application. The most common mechanisms are listed below. ### Overwrite If you are using a framework that follows the [Twelve-Factor App](https://12factor.net/) methodology, particularly the [third point](https://12factor.net/config), you can configure the application directly from environment variables. Examples of such frameworks include Spring, Eclipse MicroProfile Config, Quarkus, and Micronauts. Service credentials are available within the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables), or the [`PLATFORM_RELATIONSHIPS` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). ```bash {} export DB_HOST="$POSTGRESQL_HOST" ``` This sets environment variables with the names your app needs, and the values from [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). This variable is a base64-encoded JSON object with keys of the relationship name and values of arrays of relationship endpoint definitions. Upsun supports the [jq](https://stedolan.github.io/jq/), which allows to extract information from this JSON. .environment ```bash {} export DB_HOST="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode | jq -r '.postgresql[0].host')" ``` This sets environment variables with names your app needs and the values from [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). | Article | Source | | ------------------------------------------------------------ | ------------------------------------------------------------ | | [Spring Data MongoDB](https://support.platform.sh/hc/en-us/community/posts/16439654854802) | [Source](https://github.com/platformsh-examples/java-overwrite-configuration/tree/master/spring-mongodb) | | [Jakarta EE/MicroProfile Config](https://support.platform.sh/hc/en-us/community/posts/16439700735122) | [Source](https://github.com/platformsh-examples/java-overwrite-configuration/tree/master/jakarta-nosql) | | [Spring Data JPA](https://support.platform.sh/hc/en-us/community/posts/16439669562130) | [Source](https://github.com/platformsh-examples/java-overwrite-configuration/tree/master/spring-jpa) | | [Payara JPA](https://support.platform.sh/hc/en-us/community/posts/16439658290194) | [Source](https://github.com/platformsh-examples/java-overwrite-configuration/blob/master/payara/README.md) | **Note**: While the table above shows examples for Upsun Fixed rather than for Upsun Flex, the same rules apply with only slight changes in configuration. To reduce the number of lines in the application file and to make it cleaner, you have the option to move the variable environment to another file: a [`.environment` file](https://docs.upsun.com../../development/variables/set-variables.md#set-variables-via-script). **Example:** You can obtain relationship information through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [`PLATFORM_RELATIONSHIPS` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). Say your application has a relationship named ``postgresql`` to a database service named `postgresql`: ```bash {} export DB_HOST="${POSTGRESQL_HOST}" export DB_PASSWORD="${POSTGRESQL_PASSWORD}" export DB_USER="${POSTGRESQL_USERNAME}" export DB_DATABASE="${POSTGRESQL_PATH}" export JDBC="jdbc:postgresql://${HOST}/${DATABASE}" export JAVA_MEMORY="-Xmx$(jq .info.limits.memory /run/config.json)m" export JAVA_OPTS="$JAVA_MEMORY -XX:+ExitOnOutOfMemoryError" ``` This sets environment variables with the names your app needs, and the values from [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables).This ``PLATFORM_RELATIONSHIPS`` variable is a base64-encoded JSON object with keys of the relationship name and values of arrays of relationship endpoint definitions. Upsun supports the [jq](https://stedolan.github.io/jq/), which allows to extract information from this JSON. .environment ```bash {} export DB_HOST="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode | jq -r ".postgresql[0].host')" export DB_PASSWORD="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode | jq -r ".postgresql[0].password')" export DB_USER="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode | jq -r ".postgresql[0].username')" export DB_DATABASE="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode | jq -r ".postgresql[0].path')" export JDBC="jdbc:postgresql://${HOST}/${DATABASE}" export JAVA_MEMORY="-Xmx$(jq .info.limits.memory /run/config.json)m" export JAVA_OPTS="$JAVA_MEMORY -XX:+ExitOnOutOfMemoryError" ``` This sets environment variables with names your app needs and the values from [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). This `.environment` file can interact to each application file. **Example:** ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'java:21' hooks: build: ./mvnw package -DskipTests -Dquarkus.package.uber-jar=true relationships: postgresql: web: commands: start: java -jar $JAVA_OPTS $CREDENTIAL -Dquarkus.http.port=$PORT jarfile.jar ``` --- # Source: https://docs.upsun.com/add-services/mongodb.md # MongoDB (Database service) MongoDB is a cross-platform, document-oriented database.For more information on using MongoDB, see [MongoDB’s own documentation](https://www.mongodb.com/docs/manual/). ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 7.0 ### Deprecated versions The following versions are [deprecated](https://docs.upsun.com/glossary.md#deprecated-versions). They're available, but they don't receive security updates from upstream and aren't guaranteed to work. They'll be removed in the future – consider migrating to a [supported version](#supported-versions). - 6.0 - 5.0 - 4.4 - 4.2 - 4.0 ### Enterprise edition **Premium Service**: MongoDB Enterprise isn’t included in any Upsun plan. You need to add it separately at an additional cost. To add MongoDB Enterprise, [contact Sales](https://upsun.com/contact-us/). ### Legacy edition Previous non-Enterprise versions are available in your projects (and are listed below), but they're at their [end of life](https://www.mongodb.com/support-policy/legacy) and are no longer receiving security updates from upstream. **Warning**: Downgrades of MongoDB aren’t supported. MongoDB updates its own data files to a new version automatically but can’t downgrade them. If you want to experiment with a later version without committing to it use a preview environment. ### Deprecated versions The following versions are [deprecated](https://docs.upsun.com/glossary.md#deprecated-versions). They're available, but they don't receive security updates from upstream and aren't guaranteed to work. They'll be removed in the future – consider migrating to a [supported version](#supported-versions). - 3.6 - 3.4 - 3.2 - 3.0 ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "username": "main", "scheme": "mongodb", "service": "mongodb", "ip": "123.456.78.90", "hostname": "azertyuiopqsdfghjklm.mongodb.service._.eu-1.platformsh.site", "cluster": "azertyuiop-main-7rqtwti", "host": "mongodb.internal", "rel": "mongodb", "query": { "is_master": true }, "path": "main", "password": null, "type": "mongodb-enterprise:7.0", "port": 27017 } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_MONGODBDATABASE_HOST="$(echo "$RELATIONSHIPS_JSON" | jq -r '.mongodb[0].host')" ``` ## Usage example ### Enterprise edition example #### 1. Configure the service To define the service, use the ``mongodb-enterprise`` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: mongodb-enterprise: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. #### 2. Define the relationship To define the relationship, use the following configuration: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container (````) now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: mongodb ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). For PHP, enable the [extension](https://docs.upsun.com/languages/php/extensions.md) for the service: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # PHP extensions. runtime: extensions: - mongodb # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # PHP extensions. runtime: extensions: - mongodb # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: mongodb ``` #### Example configuration ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # PHP extensions. runtime: extensions: - mongodb # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mongodb-enterprise: services: # The name of the service container. Must be unique within a project. mongodb-enterprise: type: mongodb-enterprise:7.0 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # PHP extensions. runtime: extensions: - mongodb # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mongodb-enterprise: service: mongodb-enterprise endpoint: mongodb services: # The name of the service container. Must be unique within a project. mongodb-enterprise: type: mongodb-enterprise:7.0 ``` ### Legacy edition example #### 1. Configure the service To define the service, use the ``mongodb`` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: mongodb: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. #### 2. Define the relationship To define the relationship, use the following configuration: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container (````) now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: mongodb ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). For PHP, enable the [extension](https://docs.upsun.com/languages/php/extensions.md) for the service: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # PHP extensions. runtime: extensions: - mongodb # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # PHP extensions. runtime: extensions: - mongodb # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: mongodb ``` #### Example configuration ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # PHP extensions. runtime: extensions: - mongodb # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mongodb: services: # The name of the service container. Must be unique within a project. mongodb: type: mongodb:4.0.3 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # PHP extensions. runtime: extensions: - mongodb # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mongodb: service: mongodb endpoint: mongodb services: # The name of the service container. Must be unique within a project. mongodb: type: mongodb:4.0.3 ``` ### Use in app To use the configured service in your app, add a configuration file similar to the following to your project. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" # PHP extensions. runtime: extensions: - mongodb [...] # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mongodb: service: mongodb: type: mongodb-enterprise:7.0 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" # PHP extensions. runtime: extensions: - mongodb [...] # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mongodb: service: mongodb endpoint: mongodb service: mongodb: type: mongodb-enterprise:7.0 ``` This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory. `myapp` has access to the `mongodb` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship) (as per [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships). From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference). ```bash {location="myapp/.environment"} # Set environment variables for individual credentials. # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. export DB_CONNECTION=="${MONGODB_SCHEME}" export DB_USERNAME="${MONGODB_USERNAME}" export DB_PASSWORD="${MONGODB_PASSWORD}" export DB_HOST="${MONGODB_HOST}" export DB_PORT="${MONGODB_PORT}" export DB_DATABASE="${MONGODB_PATH}" # Surface connection string variable for use in app. export DATABASE_URL="${DB_CONNECTION}://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE}" ``` The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``DATABASE_URL`` can be used within the application to connect to the service. Note that ``DATABASE_URL``, and all Upsun [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) like ``MONGODB_HOST``, are environment-dependent. Unlike the build produced for a given commit, they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment. A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](https://docs.upsun.com/get-started.md). ## Access the service directly You can access MongoDB from you app container via [SSH](https://docs.upsun.com../development/ssh.md). Get the `host` from your [relationship](#relationship-reference). Then run the following command: ```bash mongosh ``` With the example value, that would be the following: ```bash mongosh mongodb.internal ``` You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``. Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) directly rather than hard coding any values. ## Exporting data The most straightforward way to export data from a MongoDB database is to open an SSH tunnel to it and export the data directly using MongoDB's tools. First, open an SSH tunnel with the Upsun CLI: ```bash upsun tunnel:open ``` That opens an SSH tunnel to all services on your current environment and produce output like the following: ```bash SSH tunnel opened on port 30000 to relationship: mongodb ``` The port may vary in your case. You also need to obtain the user, password, and database name from the relationships array, as above. Then, connect to that port locally using `mongodump` (or your favorite MongoDB tools) to export all data in that server: ```bash mongodump --port 30000 -u main -p main --authenticationDatabase main --db main ``` (If necessary, vary the `-u`, `-p`, `--authenticationDatabase` and `--db` flags.) As with any other shell command it can be piped to another command to compress the output or redirect it to a specific file. For further references, see the [official `mongodump` documentation](https://www.mongodb.com/docs/database-tools/mongodump/). ## Upgrading To upgrade to 6.0 from a version earlier than 5.0, you must successively upgrade major releases until you have upgraded to 5.0. For example, if you are running a 4.2 image, you must upgrade first to 4.4 and then upgrade to 5.0 before you can upgrade to 6.0. For more details on upgrading and how to handle potential application backward compatibility issues, see the [MongoDB release notes](https://www.mongodb.com/docs/manual/release-notes/). **Note**: Make sure you first test your migration on a separate branch. Also, be sure to take a backup of your production environment **before** you merge this change. Downgrading isn't supported. If you want, for whatever reason, to downgrade you should create a mongodump, remove the service, recreate the service, and import your dump. --- # Source: https://docs.upsun.com/create-apps/image-properties/mounts.md # mounts Directories that are writable even after the app is built. Allocated disk for mounts is defined with a separate resource configuration call using `upsun resources:set`. Optional in [single-runtime](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](https://docs.upsun.com/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, Upsun 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](https://docs.upsun.com/environments/backup.md), the mounts on that environment are also backed up. ### Define a mount To define a mount, use the following configuration: ```yaml {} applications: : type: nodejs:24 source: root: "/" mounts: '': source: source_path: ``` .upsun/config.yaml ```yaml {} applications: : type: "composable:25.11" source: root: "/" stack: runtimes: [ "nodejs@24" ] mounts: '': source: source_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](https://docs.upsun.com../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; set to 8 GB. 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](https://docs.upsun.com/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**. - 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`, Upsun uses the 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](#change-name) 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](https://docs.upsun.com/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](https://docs.upsun.com/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 `tmp` mount from your `.upsun/config.yaml` 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 {} applications: : type: "nodejs@24" source: root: "/" 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 ``` .upsun/config.yaml ```yaml {} applications: : type: "composable:25.11" source: root: "/" stack: runtimes: [ "nodejs@24" ] 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 {#change-name} Changing the name of your mount affects the default `source_path`. Suppose you have a `/my/cache/` mount with an undefined `source_path`: ```yaml {} applications: : type: "nodejs@24" mounts: '/my/cache/': source: tmp ``` .upsun/config.yaml ```yaml {} applications: : type: "composable:25.11" 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 must explicitly define the `source_path` as the previous name of the mount, without leading or trailing slashes: ```yaml {} applications: : type: "nodejs@24" mounts: '/cache/files/': source: tmp source_path: /my/cache ``` .upsun/config.yaml ```yaml {} applications: : type: "composable:25.11" mounts: '/cache/files/': source: tmp source_path: /my/cache ``` The `/cache/files/` mount now points 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](https://docs.upsun.com/create-apps/image-properties/mounts.md) are shared **between different instances of the same app**, which enables [horizontal scaling](https://docs.upsun.com/manage-resources.md). In a [multi-application context](https://docs.upsun.com/create-apps/multi-app.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 {} applications: app1: type: "nodejs@24" mounts: '': source: storage source_path: app2: type: "nodejs@24" mounts: '': source: storage service: app1 source_path: ``` .upsun/config.yaml ```yaml {} applications: app1: type: "composable:25.11" mounts: '': source: storage source_path: app2: type: "composable:25.11" mounts: '': source: storage service: app1 source_path: ``` - and 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**. #### Example Suppose you have a `backend` app and a `frontend` app, and you want both apps to share data from the same mount. To achieve this, complete the following steps: 1. In your `backend` app configuration, define a `storage` mount: ```yaml {} applications: backend: type: "nodejs@24" 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. ``` .upsun/config.yaml ```yaml {} applications: backend: type: "composable:25.11" 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 {} applications: backend: type: "nodejs@24" mounts: var/uploads: source: storage source_path: backend/uploads frontend: type: "nodejs@24" 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. ``` .upsun/config.yaml ```yaml {} applications: backend: type: "composable:25.11" mounts: var/uploads: source: storage source_path: backend/uploads frontend: type: "composable:25.11" 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 that another way to share data between apps through a mount is by explicitly [defining a Network Storage service](https://docs.upsun.com/add-services/network-storage.md). ### Composable image only: Local mounts If you need a local mount (i.e. unique per container), Upsun 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](https://docs.upsun.com/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 Upsun 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 {location=".upsun/config.yaml"} 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 {location=".upsun/config.yaml"} 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. --- # Source: https://docs.upsun.com/create-apps/multi-app.md # Set up multiple apps in a single project You can create multiple apps within a single project so they can share data. This can be useful if you have several apps that are closely related, such as a backend-only CMS and a frontend system for content delivery and display. No matter how many apps you have in one project, they're all served by a single [router for the project](https://docs.upsun.com/create-apps/multi-app/routes.md). To allow your apps to communicate with each other, [create relationships](https://docs.upsun.com/create-apps/multi-app/relationships.md). Each app separately defines its relationships to [services](https://docs.upsun.com/add-services.md), so apps can share services or have their own. --- # Source: https://docs.upsun.com/add-services/mysql/mysql-readonly-replication.md # MariaDB read-only replication You can improve the performance of read-heavy applications by defining read-only replicas of your MariaDB database and then connecting your applications to those replicas. Examples of read-heavy applications include: - Listing pages or dashboards - Reporting or analytics jobs - Background jobs that frequently query data **Note**: - **Replication is asynchronous**: Delays of a few milliseconds might occur between writes on the primary database and reads on the replica database. - **Replicas are read-only**: This restriction ensures data consistency and integrity. Attempts to modify data will result in an SQL error. ### Read-only vs. external replicas Read-only replicas are used primarily to improve application performance by distributing database read requests from read-heavy applications. Other common use cases for read-only replicas include: - Cross-region backup: Replicating data to different geographical regions - Data warehousing: Extracting data from production to analytics projects [External replicas](https://docs.upsun.com/add-services/mysql/mysql-replication.md) reside on remote servers and have different use cases, including disaster recovery. ### Replica scope and sharing services {#replica-scope-sharing-services} MariaDB services (which provide access to databases and replicas) defined in a project cannot be accessed by or shared with applications in other projects. **Important**: - **Replication is asynchronous**: Delays of a few milliseconds might occur between writes on the primary database and reads on the replica database. - **Replicas are read-only**: This restriction ensures data consistency and integrity. Attempts to modify a replica’s data will result in an SQL error. ## 1. Configure the primary and replica services The following code fragment defines two MariaDB services: a primary and a replica. You can use this fragment as a template by copying it into your `services.yaml` or `application.yaml` file. Be sure to: - Replace `` with the [supported MariaDB version](https://docs.upsun.com/add-services/mysql.md#supported-versions) that you need. Use the same version number for the primary and replica services. - **Important:** Use `replicator` as the endpoint name when you define the replica service. This is a special endpoint name that the replica service uses to connect to the database. ```yaml {location=".upsun/config.yaml"} services: db: type: mariadb: configuration: schemas: - main endpoints: main: default_schema: main privileges: main: admin replicator: privileges: main: replication db-replica1: type: mariadb-replica: configuration: schemas: - main endpoints: main: default_schema: main privileges: main: admin relationships: primary: db:replicator # Do not change the name `primary`. The service expects to receive this name. db-replica2: type: mariadb-replica: configuration: schemas: - main endpoints: main: default_schema: main privileges: main: admin relationships: primary: db:replicator # Do not change the name `primary`. The service expects to receive this name. ``` ### How it works Using the sample code fragment above: 1. The primary service (`db`) defines an additional `replicator` endpoint, granting the `replication` privilege. This enables a replica to connect and continuously replicate data from the primary database. ```yaml replicator: privileges: main: replication ``` 2. The replica services (`db-replica1` and `db-relica2`) use the `mariadb-replica` image type and connect back to the primary database service through the primary relationship. This establishes a replication link from `db` (the source) to `db-replica` (the target). ```yaml relationships: primary: db:replicator ``` The `db-replica1` and `db-replica2` replica services continuously stream data from the primary endpoint, maintaining a read-only copy of the primary database content. Write operations are not permitted on the replicas. ## 2. Define the relationship between the application and the replicas Even if your application won't access the replication endpoint, you must expose the endpoint to an application as a relationship so that you can connect to it over SSH. Define a new relationship in your application container, as shown below: ```yaml {location=".upsun/config.yaml"} name: myapp [...] # Relationships enable an app container's access to a service. relationships: # More information: https://fixed.docs.upsun.com/anchors/fixed/app/reference/relationships/ database: service: db endpoint: main database-readonly: service: db-replica ``` If your application's performance is still not what you expect, you can configure additional replicas as described above. --- # Source: https://docs.upsun.com/add-services/mysql/mysql-replication.md # MariaDB/MySQL external replication In rare cases, it may be useful to maintain a replica instance of your MySQL/MariaDB database outside of Upsun on a remote server. Typically, an automated backup is better for short-term usage and a `mysqldump` for longer term storage, but in some cases the data set is large enough that `mysqldump` is prohibitive. In that case, you can enable external replication using an extra permission. This guide explains replication on the Upsun side only; you must also set up and maintain your own replica instance. Consult the MySQL or MariaDB documentation for details. ## Create a replication user To set up replication you need to create a replication-enabled user. For each database that you'd like to replicate, you need to assign a `replication` permission/role, under a corresponding `endpoint`: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. mariadb: type: mariadb:11.8 configuration: schemas: - main endpoints: # Restate the default user to be used by your application. mysql: default_schema: main privileges: main: admin replicator: privileges: main: replication ``` The preceding example: - Creates a `replicator` user. - Grants read-only and table locking rights on the `main` database (namely `Select_priv`, `Show_view_priv`, `Create_tmp_table_priv`, `Lock_tables_priv` privileges). - Grants global replication rights (namely `Repl_slave_priv` and `Repl_client_priv` privileges). - Grants flushing rights (`Reload_priv` used for flushing before reading the binary log position). - If at least one `replication` permission is defined, the bin-logging is enabled on the primary server, which is essential for the replication. ## Define a relationship for the new endpoint Even if your application won’t access the replication endpoint, you still need to expose it to an application as a relationship so that you can connect to it over SSH. Add a new relationship to your application container: ```yaml {location=".upsun/config.yaml"} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" [...] # Relationships enable an app container's access to a service. relationships: database: service: mariadb endpoint: mysql replication: service: mariadb endpoint: replicator ``` ## Get the primary's binary log co-ordinates Open the MySQL CLI to the `replication` relationship, either by accessing the credentials while on the app container or using the following command. ```bash upsun sql -r replication ``` Now you need to prevent any changes to the data while you view the binary log position. You'll use this to tell the replica at exactly which point it should start replicating from. On the primary server, flush and lock all tables by running `FLUSH TABLES WITH READ LOCK`. Keep this session running - exiting it releases the lock. Get the current position in the binary log by running `SHOW MASTER STATUS`: ```sql mysql> FLUSH TABLES WITH READ LOCK; Query OK, 0 rows affected (0.016 sec) mysql> SHOW MASTER STATUS; +-----------------+----------+--------------+------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | +-----------------+----------+--------------+------------------+ | binlogs.000002 | 1036 | dflt | | +-----------------+----------+--------------+------------------+ ``` Record the `File` and `Position` details. If binary logging has just been enabled, these are blank. Now, with the lock still in place, copy the data from the primary to the replica. Login to the app container, then run: ```sh # Dump the data from primary. Note that it dumps only the databases, which "replicator" user has access to. $ mysqldump --all-databases --single-transaction -h database.internal -P 3306 -u replicator -p > /path/to/dump.sql ``` Download the dump file, then move it to the server where your replica lives so that the replica can import it. ```bash # Copy the dump to your replica $ mysql -u root < /path/to/dump.sql ``` Note for live databases: It is sufficient to make a local copy of the data; you don’t need to keep the primary locked until the replica has imported the data. Once the `mysqldump` has completed, you can release the lock on the primary by running `UNLOCK TABLES`. ```sql mysql> UNLOCK TABLES; ``` ## Set up the replica ### Configure the replica As mentioned above you have to set up a replica on your own. Assuming that you have a running MariaDB/MySQL replica instance, give the replica a unique `server_id` (distinct from primary). You can find out primary's `server_id` by running: ```sql mysql> SHOW VARIABLES LIKE 'server_id'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | server_id | 1 | +---------------+-------+ ``` Then set a distinct `server_id` number (e.g. server_id+1) in your replica config (e.g. `my.cnf`) under: ``` [mysqld] server_id=2 ``` Next, reload the replica instance for the changes to take effect. ### Set up SSH tunneling You need to set up an SSH tunnel from the replica server to the primary, tunneled through the application. **Note**: The SSH tunnel is interrupted every time the environment redeploys. For replication to continue you must set up an auto-restart for the tunnel. There are many ways to do so that are out of the scope of this documentation. You can set up an SSH tunnel using one of the following methods: - Manually using SSH. Using this method makes it easier to set up an auto-restart for the tunnel. Consult the SSH documentation for details on setting up the tunnel and the auto-restart. - Run the following Upsun CLI command (replacing `` with the name of your production branch): ```bash upsun tunnel:open --project --environment ``` This command opens local SSH tunnels to all services accessible from the application. To configure an auto-restart, you need the project's SSH address, which you can retrieve by running: ```bash upsun ssh --pipe --project ``` For details about this command, see the [Upsun CLI reference](https://docs.upsun.com/administration/cli/reference.md#usage-54). ### Binary log retention and cleanup When replication is disabled, the MariaDB service stops managing the binary logs and they remain on the file system. **You must delete these logs manually**. If the remote replica has been unreachable for some time, these logs can consume a significant amount of storage. ### Start the Replica Once the data has been imported, you are ready to start replicating. Begin by running a `CHANGE MASTER TO`, making sure that `MASTER_LOG_FILE` matches the file and `MASTER_LOG_POS` the position returned by the earlier `SHOW MASTER STATUS` on the Upsun database. For example: ```sql mysql> CHANGE MASTER TO MASTER_HOST='', MASTER_USER='replicator', MASTER_PASSWORD='', MASTER_PORT=3306, MASTER_LOG_FILE='binlogs.000002', MASTER_LOG_POS=1036, MASTER_CONNECT_RETRY=10; ``` Where `` varies depending on the SSH tunneling configuration you have, and the `` can be obtained by running `upsun ssh env`. Now start the replica with the `START SLAVE` command: ```sql mysql> START SLAVE; ``` Check that the replication is working by running the `SHOW SLAVE STATUS` command: ```sql mysql> SHOW SLAVE STATUS \G ``` If replication is working correctly, the values of both `Slave_IO_Running` and `Slave_SQL_Running` should be `Yes`: ```sql Slave_IO_Running: Yes Slave_SQL_Running: Yes ``` ### [Optional/Troubleshooting] Skipping invalid binary log queries In some cases, after applying primary's dump to the replica and starting the replica, you might experience replication errors (`Slave_SQL_Running: No` and `Error:` in the output of `SHOW SLAVE STATUS \G` above). Each of such errors needs a careful inspection, but you might be able to just skip some of them. For example: ```sql mysql> STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; START SLAVE; mysql> SHOW SLAVE STATUS \G ``` In case you have multiple errors you would need to repeat the steps above (preferred) or set `SQL_SLAVE_SKIP_COUNTER` (which corresponds to skipping the next N events from the primary) to a larger value. --- # Source: https://docs.upsun.com/add-services/mysql.md # MariaDB/MySQL (database service) Upsun supports both MariaDB and Oracle MySQL to manage your relational databases. Their infrastructure setup is nearly identical, though they differ in some features. See the [MariaDB documentation](https://mariadb.org/documentation/) or the Oracle [MySQL Server documentation](https://dev.mysql.com/doc/refman/en/) for more information. **MariaDB note**: The [example](#mariadb-example) provided later in this topic is specific to using only a **primary** MariaDB database. For details about using read-only replicas to improve performance of read-heavy applications, see the [MariaDB read-only replication](https://docs.upsun.com/add-services/mysql/mysql-readonly-replication.md) topic. ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. **Note**: - Both ``mariadb`` and ``mysql`` service types use MariaDB. They behave identically, so the information on this page applies to both of them. - The service type ``oracle-mysql`` refers to MySQL as released by Oracle, Inc. | **`mariadb` / `mysql`** | **`oracle-mysql`** | |-------------------------|--------------------| | - 11.8 - 11.4 - 10.11 - 10.6 | - 8.4 - 8.0 | ### Deprecated versions The following versions are [deprecated](https://docs.upsun.com/glossary.md#deprecated-versions). They're available, but they don't receive security updates from upstream and aren't guaranteed to work. They'll be removed in the future – consider migrating to a [supported version](#supported-versions). | **`mariadb` / `mysql`** | **`oracle-mysql`** | |-------------------------|--------------------| | - 11.2 - 11.0 - 10.5 - 10.4 - 10.3 - 10.2 - 10.1 - 10.0 - 5.5 | - 5.7 | ### Upgrade, change, or downgrade a service **Caution**: Upgrading and downgrading a service version or changing a service type are destructive processes that delete the existing service and its data. A best practice is to first back up your environment and export the data. To prevent data loss after completing either of these actions, follow these steps: 1. [Back up your environment](https://docs.upsun.com/environments/backup.md#create-a-manual-backup). If you accidentally delete the wrong service or make an error in your `config.yaml` file and need to revert your entire environment, the backup enables you to do so. 1. [Export the data](#exporting-data). Exporting the data to a portable file enables you to import it later. You cannot import data directly from a backup of your environment. 1. Change the service type in your [service configuration](https://docs.upsun.com/add-services/_index.md): - **Upgrade:** Upgrade sequentially from one supported version to another (10.6 -> 10.11 -> 11.4), and check that each upgrade commit translates into an actual deployment. - **Change or downgrade:** Specify the new service type and the desired version. 1. [Import your data](#importing-data) into the new service. ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](development/variables/use-variables.md#use-provided-variables). ### MariaDB reference For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal. ```json {} { "username": "user", "scheme": "mysql", "service": "mariadb", "fragment": null, "ip": "123.456.78.90", "hostname": "azertyuiopqsdfghjklm.mariadb.service._.eu-1.platformsh.site", "port": 3306, "cluster": "azertyuiop-main-7rqtwti", "host": "mariadb.internal", "rel": "mysql", "path": "main", "query": { "is_master": true }, "password": "", "type": "mariadb:11.8", "public": false, "host_mapped": false } ``` Example on how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_DATABASE_HOST="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode | jq -r ".mariadb[0].host")" ``` ### Oracle MySQL reference For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal. ```json {} { "username": "user", "scheme": "mysql", "service": "oracle-mysql", "fragment": null, "ip": "123.456.78.90", "hostname": "azertyuiopqsdfghjklm.oracle-mysql.service._.eu-1.platformsh.site", "port": 3306, "cluster": "azertyuiop-main-afdwftq", "host": "oracle_mysql.internal", "rel": "mysql", "path": "main", "query": { "is_master": true }, "password": "", "type": "oracle-mysql:8.4", "public": false, "host_mapped": false } ``` Example on how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_ORACLE_HOST="$(echo "$RELATIONSHIPS_JSON" | jq -r '.oraclemysql[0].host')" ``` ## Usage example Configure your service with at least 256 MB in disk space. ### 1. Configure the service To define the service, use the ``mariadb`` or ``mysql`` type for MariaDB or the ``oracle-mysql`` type for Oracle MySQL : ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: mariadb: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. ### 2. Define the relationship To define the relationship, use the following configuration: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container (````) now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: mysql ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). ### MariaDB example **Note**: Use the steps and sample code below if your application will connect to a **primary** MariaDB database. For details about using read-only replicas to improve performance of read-heavy applications, see the [MariaDB read-only replication](https://docs.upsun.com/add-services/mysql/mysql-readonly-replication.md) topic. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mariadb: services: # The name of the service container. Must be unique within a project. mariadb: type: mariadb:11.8 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mariadb: service: mariadb endpoint: mysql services: # The name of the service container. Must be unique within a project. mariadb: type: mariadb:11.8 ``` ### OracleMySQL example ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. relationships: oracle-mysql: service: # The name of the service container. Must be unique within a project. oracle-mysql: type: oracle-mysql:8.4 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: oracle-mysql: service: oracle-mysql_service endpoint: mysql service: # The name of the service container. Must be unique within a project. oracle-mysql_service: type: oracle-mysql:8.4 ``` ### Use in app To use the configured service in your app, add a configuration file similar to the following to your project. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" [...] # Relationships enable an app container's access to a service. relationships: mariadb: service: mariadb: type: mariadb:11.8 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" [...] # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: mariadb: service: mariadb endpoint: mysql service: mariadb: type: mariadb:11.8 ``` This configuration defines a single application (``myapp``), whose source code exists in the ``/myapp`` directory. ``myapp`` has access to the ``mariadb`` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship) (as per [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships). From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference). ```bash {location="myapp/.environment"} # Set environment variables for individual credentials. # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. export DB_CONNECTION="${MARIADB_SCHEME}" export DB_USERNAME="${MARIADB_USERNAME}" export DB_PASSWORD="${MARIADB_PASSWORD}" export DB_HOST="${MARIADB_HOST}" export DB_PORT="${MARIADB_PORT}" export DB_DATABASE="${MARIADB_PATH}" # Surface connection string variable for use in app. export DATABASE_URL="${DB_CONNECTION}://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE}" ``` The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``MARIADB_URL`` can be used within the application to connect to the service. Note that ``DATABASE_URL``, and all Upsun [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) like ``MARIADB_HOST``, are environment-dependent. Unlike the build produced for a given commit, they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment. A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](https://docs.upsun.com/get-started.md). ### Configure connections There may be cases where you want to configure a database connection manually. To get the URL to connect to the database, run the following command: ```bash upsun ssh env ``` The result is the complete [information for all relationships](#relationship-reference) with an additional `DATABASE_URL` property, defined on step [Use in app](#use-in-app).
Use the `DATABASE_URL` property as your connection. You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``. Service connection details can change whenever your app restarts or redeploys. **To keep your connection stable, use [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) rather than hard-coding values.** You can also see a guide on how to [convert the `PLATFORM_RELATIONSHIPS` environment variable to a different form](https://support.platform.sh/hc/en-us/community/posts/16439596373010). ## Configuration options {#configuration-options} You can configure your MySQL service in the [services configuration](https://docs.upsun.com...md) with the following options: | Name | Type | Version | Description | | ------------------ | -------------------------- | ---------------------------------- | ----------- | | `schemas` | `string` array | 10.0+ | All databases to be created. Defaults to a single `main` database. | | `endpoints` | An endpoints dictionary | 10.0+ | Endpoints with their permissions. See [multiple databases](#multiple-databases). | | `properties` | A properties dictionary | MariaDB: 10.1+; Oracle MySQL: 8.0+ | Additional properties for the database. Equivalent to using a `my.cnf` file. See [property options](#configure-the-database). | | `rotate_passwords` | A boolean | 10.3+ | Defaults to `true`. When set to `false`, [password rotation](#password-rotation) is disabled. | Example configuration: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. mariadb: type: mariadb:11.8 configuration: schemas: - main endpoints: mysql: default_schema: main privileges: main: admin properties: max_allowed_packet: 64 ``` ## Access the service directly You can access the service using the Upsun CLI by running `upsun sql`. You can also access it from you app container via [SSH](https://docs.upsun.com../../development/ssh.md). From your [relationship data](#relationship-reference), you need: `MARIADB_HOST`, `MARIADB_PORT`, `MARIADB_USERNAME`, `MARIADB_PATH` values. Then run the following command: ```bash mysql -h -P -u ``` Assuming the values from the [MariaDB reference](#mariadb-reference), that would be: ```bash mysql -h mariadb.internal -P 3306 -u user main ``` If your database relationship has a password, pass the `-p` switch and enter the password when prompted: ```bash mysql -p -h mariadb.internal -P 3306 -u user main ``` ## Define permissions With version `10.0` or later, you can define multiple users with different permissions for your database. To do so, define multiple endpoints in your [service configuration](#configuration-options). For each endpoint you add, you can define the following properties: | Name | Type | Required | Description | | ---------------- | ------------------------ | -------- | ----------- | | `default_schema` | `string` | | Which of the defined schemas to default to. If not specified, the `path` property of the relationship is `null` and so tools such as the Upsun CLI can't access the relationship. | | `privileges` | A permissions dictionary | | For each defined schema, specifies the permissions of the endpoint. | Available permissions: | Name | Type | Description | |-------------------|---------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Read-only | `ro` | Can select, create temporary tables, and see views. | | Read-write | `rw` | In addition to read-only permissions, can also insert, update, delete, manage and execute events, execute routines, create and drop indexes, manage and execute triggers, and lock tables. | | Admin | `admin` | In addition to read-write permissions, can also create, drop, and alter tables; create views; and create and alter routines. | | Replication | `replication` | For [replicating databases](https://docs.upsun.com/add-services/mysql/mysql-replication.md). In addition to read-only permissions, can also lock tables. | | Replication admin | `replication-admin` | For managing replicas across projects; can run statements such as SHOW REPLICA STATUS, CHANGE MASTER TO, START REPLICA, and so on (see this related [Dev Center article](https://devcenter.upsun.com/posts/connect-multiple-projects-applications-or-services-together/)). | ## Multiple databases With version `10.0` or later, you can define multiple databases. To do so, define multiple `schemas` in your [service configuration](#configuration-options). You can also specify multiple `endpoints` for [permissions](#define-permissions). If neither `schemas` nor `endpoints` is included, it's equivalent to the following default: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. mariadb: type: mariadb:11.8 configuration: schemas: - main endpoints: mysql: default_schema: main privileges: main: admin ``` If either `schemas` or `endpoints` are defined, no default is applied and you have to specify the full configuration. **Note**: Removing a schema from the list of ``schemas`` on further deployments results in the deletion of the schema. ### Multiple databases example The following configuration example creates a single MariaDB service named `mariadb` with two databases, `main` and `legacy`. Access to the database is defined through three endpoints: * `admin` has full access to both databases. * `reporter` has SELECT query access to `main` but no access to `legacy`. * `importer` has SELECT/INSERT/UPDATE/DELETE (but not DDL) access to `legacy` but no access to `main`. ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. mariadb: type: mariadb:11.8 configuration: schemas: - main - legacy endpoints: admin: default_schema: main privileges: main: admin legacy: admin reporter: privileges: main: ro importer: default_schema: legacy privileges: legacy: rw ``` Expose these endpoints to your app as relationships in your [app configuration](https://docs.upsun.com../../create-apps/_index.md): ```yaml {location=".upsun/config.yaml"} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" [...] # Relationships enable access from this app to a given service. # The example below shows configuration with explicitly set service names and endpoints. # See the Application reference for all options for defining relationships and endpoints. relationships: database: service: mariadb endpoint: admin reports: service: mariadb endpoint: reporter imports: service: mariadb endpoint: importer ``` These relationships are then available in the [service environment variables](#relationship-reference). Each has its own credentials, prefixed with the relationship name, you can use to connect to the given database. ## Configure the database For MariaDB 10.1 and later and Oracle MySQL 8.0 and later, you can set some configuration properties (equivalent to using a `my.cnf` file). In your settings, add the `properties` key to the `configuration` key. It offers the following properties: | Name | Type | Default | Description | |---------------------------------------|-----------|--------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `max_allowed_packet` | `integer` | `16` | The maximum size for packets in MB. Can be from `1` to `100`. | | `default_charset` | `string` | `utf8mb4` after February 2020 and `latin1` before | The default character set. Affects any tables created after it's set. | | `default_collation` | `string` | `utf8mb4_unicode_ci` after February 2020 and `latin1` before | The default collation. Affects any tables created after it's set. | | `optimizer_switch` | `string` | | A place to set various server optimization variables. See the [MariaDB documentation](https://mariadb.com/kb/en/optimizer-switch/). | | `optimizer_use_condition_selectivity` | `integer` | `4` in version 10.4.1+ and `1` before that | Which statistics are used by the optimizer. From `1` to `5`. See the [MariaDB documentation](https://mariadb.com/kb/en/server-system-variables/#optimizer_use_condition_selectivity). | | `innodb_adaptive_hash_index` | `integer` | `0` in version 10.5+ and `1` before that | Enable/Disable InnoDB Hash Index. See the [MariaDB documentation](https://mariadb.com/kb/en/innodb-system-variables/#innodb_adaptive_hash_index). | | `max_heap_table_size` | `integer` | `32` | The maximum size for user-created MEMORY tables in MB. Can be from `1` to `4096`. | | `table_definition_cache` | `integer` | `400` | The number of table definitions that can be cached. See the [MariaDB documentation](https://mariadb.com/kb/en/server-system-variables/#table_definition_cache). | | `table_open_cache` | `integer` | `400` | The maximum number of open tables cached in one table cache instance. See the [MariaDB documentation](https://mariadb.com/kb/en/server-system-variables/#table_open_cache). | | `wsrep_sync_wait` | `integer` | `0` (Disabled) | Ensure execution of statements in fully synced nodes. See the [MariaDB documentation](https://mariadb.com/kb/en/galera-cluster-system-variables/#wsrep_sync_wait). | An example of setting these properties: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. mariadb: type: mariadb:11.8 configuration: properties: max_allowed_packet: 64 default_charset: utf8mb4 default_collation: utf8mb4_unicode_ci ``` You can also change a table's character set and collation through `ALTER TABLE` commands: ```sql -- To change defaults when creating new tables: ALTER DATABASE main CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- To change defaults when creating new columns: ALTER TABLE table_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- To convert existing data: ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; ``` For further details, see the [MariaDB documentation](https://mariadb.com/kb/en/character-set-and-collation-overview/). **Note**: MariaDB configuration properties like [max_connections](https://mariadb.com/docs/server/server-management/variables-and-modes/server-system-variables#max_connections) and [innodb_buffer_pool_size](https://mariadb.com/kb/en/innodb-buffer-pool/#innodb_buffer_pool_size) are not directly configurable from ``configuration.properties`` in your services configuration. They can, however, be set indirectly, which can be useful for solving ``Too many connection`` errors. See [the troubleshooting documentation](https://docs.upsun.com/add-services/mysql/troubleshoot.md#too-many-connections) for more details. ## Password generation {#password-generation} If your YAML file does not specify a `schema` and `endpoint` for the MariaDB or MySQL service, no password is generated. Because the database container is strictly isolated, it remains invisible to any resource until you [define an explicit relationship](https://docs.upsun.com/add-services/mysql.md#2-define-the-relationship) between it and other apps or workers. The container's "walls" ensure that only authorized applications and workers can reach the data, while all other processes are blocked at the network level. If you prefer to have Upsun generate a password, you must define [`schemas` and custom `endpoints`](#1-configure-the-service) in the `services` configuration – see the example in the [multiple databases](#multiple-databases) section of this topic. For each custom endpoint that you define, Upsun generates a password. Note that you cannot customize these generated passwords. **Note**: Make sure you don’t change ``services.``. **Changing the service name creates a new service, which removes existing data from your database.** After your custom endpoints are exposed as relationships in your [app configuration](https://docs.upsun.com../../create-apps.md), you can retrieve the password for each endpoint through the `PLATFORM_RELATIONSHIPS` [environment variable](https://docs.upsun.com../../development/variables/use-variables.md#use-provided-variables) within your [application containers](https://docs.upsun.com/development/variables/use-variables.md#access-variables-in-your-app). Using this method to retrieve password credentials is considered a best practice: passwords change automatically (or [_rotate_](#password-rotation)) over time, and using incorrect passwords results in application downtime. **Avoid using hard-coded passwords in your application (and code base), which can cause security issues.** ## Password rotation {#password-rotation} **Note**: For rotation to occur, you must define a ``schema`` and ``endpoint`` in your service configuration (see [Password generation](#password-generation) above); otherwise, no password is generated to be rotated. By default, password rotation is enabled (`rotate_passwords: true`), which enables Upsun to automatically rotate MariaDB passwords during image updates or as defined by MariaDB lifetime settings. Specific scenarios might warrant disabling password rotation by [setting `rotate_passwords=false`](https://docs.upsun.com/add-services/mysql.md#configuration-options): for example, choosing to accommodate users who access a database via an SSH tunnel and provide a password in their request because they cannot retrieve the database credentials stored in the [service or `$PLATFORM_RELATIONSHIPS` MariaDB environment variables](#mariadb-reference). Passwords do **not** rotate automatically when you reset this value to `true`. **Important**: Disabling password rotation can jeopardize compliance with security certifications - make sure you weigh this risk alongside the convenience of SSH-tunneling access. ## Storage Engine It’s best to use the InnoDB storage engine wherever possible instead of MyISAM. If MyISAM tables have been inadvertently created or imported in your environments (if you see ``ENGINE=MyISAM`` in the response to ``SHOW CREATE TABLE EXISTING_TABLE``), convert them to use the InnoDB storage engine as follows: 1. Rename the existing table. ```text RENAME TABLE ; ``` 1. Create a new table from the data in the existing table. ```text CREATE TABLE SELECT * from ; ``` Now when you run `SHOW CREATE TABLE `, you see `ENGINE=InnoDB`. ## Service timezone To change the timezone for a given connection, run `SET time_zone = ;`. ## Exporting data To download all data from your SQL database, use the Upsun CLI. If you have a single SQL database, the following command exports all data to a local file: ```bash upsun db:dump ``` If you have multiple SQL databases, you are prompted for which one to export. You can also specify a database by its relationship name: ```bash upsun db:dump --relationship ``` ### Compression By default, the file is uncompressed. To compress it, use the `--gzip` (`-z`) option: ```bash upsun db:dump --gzip ``` ### Using the output in bash To pipe the result to another command, use the `--stdout` option. For example, to create a bzip2-compressed file, run: ```bash upsun db:dump --stdout | bzip2 > dump.sql.bz2 ``` ## Importing data To load data into a database, pipe an SQL dump through the `upsun sql` command, like so: ```bash upsun sql < my_database_backup.sql ``` That runs the database backup against the SQL database on Upsun. That works for any SQL file, so the usual caveats about importing an SQL dump apply (for example, it's best to run against an empty database). As with exporting, you can specify a specific environment and a specific database relationship to use: ```bash upsun sql --relationship -e < my_database_backup.sql ``` **Note**: Importing a database backup is a destructive operation. It overwrites data already in your database. It’s best to run it against an empty database. If not, make a backup or do a database export before importing. ## Sanitizing data To ensure people who review code changes can't access personally identifiable information stored in your database, [sanitize your preview environments](https://docs.upsun.com../../development/sanitize-db.md). ## Replication There is no on-site primary/replica support in your environments. In rare cases (such as for certain backup purposes), you can also enable [remote replication](https://docs.upsun.com/add-services/mysql/mysql-replication.md) to your own replica data. The replica isn't available to your application. ## Troubleshoot If you run into issues, [troubleshoot MySQL](https://docs.upsun.com/add-services/mysql/troubleshoot.md). --- # Source: https://docs.upsun.com/add-services/network-storage.md # Network Storage The Network Storage service enables a new kind of [mount](https://docs.upsun.com../create-apps/image-properties/mounts.md) that refers to a shared service rather than to a local directory. This service allows you to store data and share it between different apps. ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 1.0 This service is the Upsun network storage implementation, not the version of a third-party application. **Note**: It isn’t possible to upgrade or downgrade the network storage service version while keeping existing data in place. Changing the service version requires that the service be reinitialized. Any change to the service version results in existing data becoming inaccessible. - 2.0 ## Usage example ### 1. Configure the service To define the service, use the ``network-storage`` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: network-storage: ``` `` must be [RFC 1123](https://tools.ietf.org/html/rfc1123) compliant, and as such it must: - Contain at most 63 characters - Contain only lowercase alphanumeric characters or `-` (underscores `_` are not allowed) - Start with an alphanumeric character - End with an alphanumeric character This is due to the fact that `` is used as hostname for the network storage. Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. ### 2. Add the mount To define the mount accessible by your application, use the following configuration: ```yaml {location=".upsun/config.yaml"} applications: # The name of the app container. Must be unique within a project. : mounts: : source: service service: source_path: services: # The name of the service container. Must be unique within a project. : type: network-storage: ``` - `` is the path to your mount within the app container (relative to the app’s root). - `` is the name you [defined in step 1](#1-configure-the-service). - `` specifies where the mount points inside the service. If the `source_path` is an empty string (`""`), your mount points to the entire service. If you don’t define a `source_path`, Upsun uses the `MOUNT_PATH` as default value, without leading or trailing slashes. For example, if your mount lives in the `/my/files/` directory within your app container, it will point to a `my/files` directory within the service. ### Example configuration ```yaml {location=".upsun/config.yaml"} applications: # The name of the app container. Must be unique within a project. myapp: mounts: 'my/files': source: service service: network-storage source_path: files services: # The name of the service container. Must be unique within a project. network-storage: type: network-storage:1.0 ``` ## Multi-application usage If your project contains [multiple apps](https://docs.upsun.com../create-apps/multi-app.md), they may [share `storage` mounts](https://docs.upsun.com/create-apps/image-properties/mounts.md#share-a-mount-between-several-apps). Alternatively, they may use shared `service` mounts. If the `source_path` is the same for both apps, the files are shared between the two applications even if the mount location is different. It's also possible to have one app mount a `source_path` that's a subdirectory of another application's mount. For example: ```yaml {location=".upsun/config.yaml"} applications: # The name of the app container. Must be unique within a project. app1: # The location of the application's code. source: root: "app1" [...] mounts: # The path to your mount within the app container (relative to the app's root). 'web/uploads': # Specifies that the mount points to a network storage service that can be shared between apps. source: service # The name of the network storage service the mount points to. service: network-storage # Specifies where your mount points inside the external directory that is mounted to your app container. source_path: uploads # The name of the app container. Must be unique within a project. app2: # The location of the application's code. source: root: "app2" [...] mounts: # The path to your mount within the app container (relative to the app's root). 'process': # Specifies that the mount points to a network storage service that can be shared between apps. source: service # The name of the network storage service the mount points to. service: network-storage # Specifies where your mount points inside the external directory that is mounted to your app container. # Since the target is the uploads directory app1's mount already points to, # the network storage service is effectively shared between app1 and app2. source_path: uploads/incoming # The path to your mount within the app container (relative to the app's root). 'done': # Specifies that the mount points to a network storage service that can be shared between apps. source: service # The name of the network storage service the mount points to. service: network-storage # Specifies where your mount points inside the external directory that is mounted to your app container. # Since the target is the uploads directory app1's mount already points to, # the network storage service is effectively shared between app1 and app2. source_path: uploads/done ``` In this example, `app1` has access to the entire `uploads` directory by writing to `web/uploads`. `app2` has two mounts that it can write to: `process` and `done`. The `process` mount refers to the same directory as the `web/uploads/incoming` directory does on `app1`, and the `done` mount refers to the same directory as the `web/uploads/done` directory on `app1`. ## How do I give my workers access to my main application’s files? If you need to use a worker with access to the same file mount as your web-serving app, define all the necessary mounts as `service` mounts. The following example assumes a Network Storage service named `files` has been defined in `.upsun/config.yaml`. Drupal files directories are shared between the `web` and `worker` instances, while the Drush backup directory is unique to the `web` instance. ```yaml {location=".upsun/config.yaml"} applications: myapp: source: root: "/" type: "php:8.5" [...] mounts: # The public and private files directories are # network mounts shared by web and workers. 'web/sites/default/files': source: service service: files source_path: files 'private': source: service service: files source_path: private # The backup, temp, and cache directories for # Drupal's CLI tools don't need to be shared between web and workers. # It wouldn't hurt anything to make them network # shares, however. '/.drush': source: storage source_path: drush 'tmp': source: tmp source_path: tmp 'drush-backups': source: storage source_path: drush-backups '/.console': source: storage source_path: console # Crons run on the web container, so they have the # same mounts as the web container. crons: drupal: spec: '*/20 * * * *' commands: start: 'cd web ; drush core-cron' # The worker defined here also has the same 6 mounts; # 2 of them are shared with the web container, # the other 4 are local to the worker. workers: queue: commands: start: | cd web && drush queue-run myqueue ``` ## How can I migrate data from a `storage` mount to a `service` mount? Network Storage `service` mounts can be shared between different apps, while `storage` mounts can only be shared between different _instances_ of the same app. To move data from a `storage` mount to a `service` one, follow these instructions. Assuming you have the following `storage` mount: ```yaml {location=".upsun/config.yaml"} applications: myapp: [...] mounts: web/uploads: source: storage source_path: uploads ``` 1. Add a new `network-storage` service to your configuration: ```yaml {location=".upsun/config.yaml"} applications: myapp: [...] mounts: web/uploads: source: storage source_path: uploads services: # The name of the service container. Must be unique within a project. network-storage: type: network-storage:1.0 ``` **Note**: Make sure you [allocate enough disk space](https://docs.upsun.com/manage-resources/adjust-resources.md#vertical-scaling) to your ``network-storage`` service for your existing files with some buffer. 2. Add a new `service` mount, named `new-uploads`: ```yaml {location=".upsun/config.yaml"} applications: myapp: [...] mounts: web/uploads: source: storage source_path: uploads new-uploads: source: service service: network-storage source_path: uploads services: # The name of the service container. Must be unique within a project. network-storage: type: network-storage:1.0 ``` Note that each mount is on a different storage service, which is why they can have the same `source_path`. 3. Deploy your changes. 4. Copy all your files from the `storage` (`web/uploads`) mount to the `service` (`new-uploads`) mount using `rsync`: ```bash rsync -avz web/uploads/* new-uploads/ ``` 5. Reverse the mounts. To do so, rename the `storage` mount to `old-uploads`, and point the `web/uploads` directory to the `service` mount: ```yaml {location=".upsun/config.yaml"} applications: myapp: [...] mounts: old-uploads: source: storage source_path: uploads web/uploads: source: service service: network-storage source_path: uploads services: # The name of the service container. Must be unique within a project. network-storage: type: network-storage:1.0 ``` 6. Push your changes and check that the files are now accessible from the `service` mount (now named `web/uploads`). To check that no files were lost during the transfer, run the following command: ```bash rsync -avz old-uploads/* web/uploads/ ``` 7. Delete the contents of the `old-uploads` `storage` mount before removing it. 8. Push your changes again. --- # Source: https://docs.upsun.com/languages/nodejs/node-version.md # Manage Node.js versions p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. Each Upsun container image includes a specific language in a specific version. A set of dependencies is also provided based on that language version. This ensures that your application container is as small and efficient as possible. Therefore, by default, when you use an Upsun container image, you use the Node.js version that's included in that image, if any. If you want to use a different Node.js version, use a version manager to install it yourself. You can use one of the following version managers: - [Use `n`](#use-n) - [Use `nvm`](#use-nvm) Both of the recommendations use a `.nvmrc` file to specify the desired Node.js version. You could also specify a different file or use [environment variables](https://docs.upsun.com../../development/variables.md). ## Use `n` The [`n` package](https://github.com/tj/n) works for various Unix-like systems, including Windows Subsystem for Linux. 1. Add the desired Node.js version to your environment using `.nvmrc`, `.n-node-version`, `.node-version`, or `package.json`. ```yaml {} v16.13.2 ``` Create a ``.n-node-version`` or ``.node-version`` file in [your app root](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory): .n-node-version or .node-version ```yaml {} 16.13.2 ``` Add an ``engines.node`` property to your ``package.json``. This property accepts either an exact version or a range: package.json ```json {} { "engines": { "node": ">=0.10.3 <15" } } ``` 2. Add it as a dependency: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' dependencies: nodejs: n: "*" ``` Adding it as a dependency ensures it's cached for future builds. 3. Set the location of the `n` files using the `N_PREFIX` environment variable: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' dependencies: nodejs: n: "*" variables: env: N_PREFIX: /app/.global ``` 4. Install the specified version of Node.js in a [`build` hook](https://docs.upsun.com../../create-apps/hooks/hooks-comparison.md#build-hook): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' dependencies: nodejs: n: "*" variables: env: N_PREFIX: /app/.global hooks: build: | # Exit the hook on any failure set -e # Install the version specified in the .nvmrc file n auto # Reset the location hash to recognize the newly installed version hash -r ``` Now your hooks should be able to use the specified version of Node.js. You can verify this by running `node -v`. Your final app configuration should look something like this: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' dependencies: nodejs: n: "*" variables: env: N_PREFIX: /app/.global hooks: build: | # Exit the hook on any failure set -e # Install the version specified in the .nvmrc file n auto # Reset the location hash to recognize the newly installed version hash -r ``` ## Use `nvm` [Node Version Manager (`nvm`)](https://github.com/nvm-sh/nvm) is a bash script for managing Node.js versions. You can use it to: - Make a specific version available in the build and optionally the runtime container. - Control the specific versions to be installed with [environment variables](https://docs.upsun.com../../development/variables.md), meaning you can also have different versions in different environments. To use `nvm`, follow these steps: 1. Define which `nvm` version to use using an [environment variable](https://docs.upsun.com../../development/variables.md). Add it to your [app configuration](https://docs.upsun.com../../create-apps/_index.md): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' variables: env: # Update for your desired NVM version. NVM_VERSION: v0.39.3 ``` 2. Define your desired Node.js version using an environment variable. For your base version, set it in your app configuration: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' variables: env: # Update these for your desired NVM and Node versions. NVM_VERSION: v0.39.3 NODE_VERSION: v18.14.2 ``` To get different versions in different environments, [set environment-specific variables](https://docs.upsun.com../../development/variables/set-variables.md#create-environment-specific-variables). 3. Add a `.nvm` directory to your cache in your [build hook](https://docs.upsun.com../../create-apps/hooks/_index.md): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' variables: env: # Update these for your desired NVM and Node versions. NVM_VERSION: v0.39.3 NODE_VERSION: v18.14.2 hooks: build: | set -e unset NPM_CONFIG_PREFIX export NVM_DIR="$PLATFORM_APP_DIR/.nvm" # Link cache with app if [ ! -d "$PLATFORM_CACHE_DIR/.nvm" ]; then mkdir -p $PLATFORM_CACHE_DIR/.nvm fi ln -s $PLATFORM_CACHE_DIR/.nvm $NVM_DIR ``` **Note**: Instead of using a symlink between your cache and application directories, you might need to copy the content of ``$PLATFORM_CACHE_DIR/.nvm`` into ``$PLATFORM_APP_DIR/.nvm`` manually. To do so, run the following command: ```bash {} rsync -av $PLATFORM_CACHE_DIR/.nvm $PLATFORM_APP_DIR ``` 4. Use the cache directory and install based on the variables if not present: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' variables: env: # Update these for your desired NVM and Node versions. NVM_VERSION: v0.39.3 NODE_VERSION: v18.14.2 hooks: build: | ... # Check for Node.js version and install if not present if [ ! -d "$PLATFORM_CACHE_DIR/.nvm/versions/node/$NODE_VERSION" ]; then # Get nvm install script if correct version not present export NVM_INSTALL_FILE="${PLATFORM_CACHE_DIR}/nvm_${NVM_VERSION}_install.sh" if [ ! -f "$NVM_INSTALL_FILE" ]; then wget -nc -O "$NVM_INSTALL_FILE" "https://raw.githubusercontent.com/nvm-sh/nvm/$NVM_VERSION/install.sh" fi # Install, automatically using NODE_VERSION bash $NVM_INSTALL_FILE fi # Activate nvm [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # Use the specified version nvm use "$NODE_VERSION" ``` 5. Optional: To use the specified Node.js version in the runtime container and not just the build, activate `nvm` via [script](https://docs.upsun.com../../development/variables/set-variables.md#set-variables-via-script): ```bash {location=".environment"} unset NPM_CONFIG_PREFIX export NVM_DIR="$PLATFORM_APP_DIR/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" ``` Your final app configuration should look something like the following: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' variables: env: # Update these for your desired NVM and Node versions. NVM_VERSION: v0.39.3 NODE_VERSION: v18.14.2 hooks: build: | set -e unset NPM_CONFIG_PREFIX export NVM_DIR="$PLATFORM_APP_DIR/.nvm" # Link cache with app if [ ! -d "$PLATFORM_CACHE_DIR/.nvm" ]; then mkdir -p $PLATFORM_CACHE_DIR/.nvm fi ln -s $PLATFORM_CACHE_DIR/.nvm $NVM_DIR # Check for Node.js version and install if not present if [ ! -d "$PLATFORM_CACHE_DIR/.nvm/versions/node/$NODE_VERSION" ]; then # Get nvm install script if correct version not present export NVM_INSTALL_FILE="${PLATFORM_CACHE_DIR}/nvm_${NVM_VERSION}_install.sh" if [ ! -f "$NVM_INSTALL_FILE" ]; then wget -nc -O "$NVM_INSTALL_FILE" "https://raw.githubusercontent.com/nvm-sh/nvm/$NVM_VERSION/install.sh" fi # Install, automatically using NODE_VERSION bash $NVM_INSTALL_FILE fi # Activate nvm [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # Use the specified version nvm use "$NODE_VERSION" ``` --- # Source: https://docs.upsun.com/languages/nodejs.md # JavaScript/Node.js p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. Node.js is a popular asynchronous JavaScript runtime. Deploy scalable Node.js apps of all sizes on Upsun. You can also develop a microservice architecture mixing JavaScript and other apps with [multi-app projects](https://docs.upsun.com../../create-apps/multi-app.md). ## Supported versions You can select the major version. But the latest compatible minor version is applied automatically and can’t be overridden. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 24 - 22 - 20 ### Specify the language To use Node.js, specify ``nodejs`` as your [app’s type](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#types): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. : type: 'nodejs:' ``` For example: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'nodejs:24' ``` To use a specific version in a container with a different language, [use a version manager](node-version.md). ### Deprecated versions The following versions are [deprecated](https://docs.upsun.com/glossary.md#deprecated-versions). They're available, but they don't receive security updates from upstream and aren't guaranteed to work. They'll be removed in the future – consider migrating to a [supported version](#supported-versions). - 18 - 16 - 8.9 - 6.10 - 6.9 - 6.8 - 6.6 - 6.3 - 6.2 - 4.7 - 4.6 - 4.5 - 4.4 - 4.3 - 4.2 ## Usage example To use JavaScript with Node.js on Upsun, configure your [app configuration](https://docs.upsun.com../../create-apps.md) (a complete example is included at the end). ### 1. Specify the version Choose a version from the [list of supported versions](#supported-versions) and add it to your app configuration: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'nodejs:24' ``` ### 2. Specify any global dependencies Add the following to your app configuration: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'nodejs:24' dependencies: nodejs: sharp: "*" ``` These are now available as commands, the same as installing with `npm install -g`. ### 3. Build your app Include any commands needed to build and setup your app in the `hooks`, as in the following example: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'nodejs:24' dependencies: nodejs: sharp: "*" hooks: build: | npm run setup-assets npm run build ``` ### 4. Start your app Specify a command to start serving your app (it must be a process running in the foreground): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'nodejs:24' dependencies: nodejs: sharp: "*" hooks: build: | npm run setup-assets npm run build web: commands: start: node index.js ``` ### 5. Listen on the right port Make sure your Node.js application is configured to listen over the port given by the environment. ```js // Load the http module to create an http server. const http = require('http'); const PORT = process.env.PORT || 8888; const server = http.createServer(function (request, response) { response.writeHead(200, {"Content-Type": "application/json"}); response.end("Hello world!"); }); // Listen on the port from the Upsun configuration server.listen(PORT, () => { console.log(`Server is listening on port: ${PORT}`); }); ``` ### Complete example A complete basic app configuration looks like the following: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. 'node-app': type: 'nodejs:24' dependencies: nodejs: sharp: "*" hooks: build: | npm run setup-assets npm run build web: commands: start: "node index.js" ``` ## Dependencies By default, Upsun assumes you're using npm as a package manager. If your code has a `package.json`, the following command is run as part of the default [build flavor](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#build): ```bash npm prune --userconfig .npmrc && npm install --userconfig .npmrc ``` This means you can specify configuration in a `.npmrc` file in [your app root](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory). ### Use Yarn as a package manager To switch to Yarn to manage dependencies, follow these steps: 1. Turn off the default use of npm: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'nodejs:24' build: flavor: none ``` 2. Specify the version of Yarn you want: ```json {location="package.json"} { ... "packageManager": "yarn@3.2.1" } ``` What you do next depends on the versions of Yarn and Node.js you want. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'nodejs:24' hooks: build: | corepack yarn install ``` - Enable Corepack (which is opt-in): .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'nodejs:24' dependencies: nodejs: corepack: "*" ``` - Use Corepack to run Yarn in your build hook: .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'nodejs:24' hooks: build: | corepack yarn install ``` - Add Yarn as a global dependency: .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'nodejs:24' dependencies: nodejs: yarn: "1.22.19" ``` - Install dependencies in the ``build`` hook: .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'nodejs:24' hooks: build: | yarn --frozen-lockfile ``` ### Use Bun as a package manager **Availability** [Bun is available as a runtime and package manager](https://devcenter.upsun.com/posts/bun-support-is-here/) for Node.js **versions 20 or above**. To switch to Bun to manage dependencies, use the following configuration: ```yaml {location=".upsun/config.yaml"} applications: # The name of your app. myapp: # Choose Node.js version 20 or above. type: 'nodejs:20' # Override the default Node.js build flavor. build: flavor: none # Use Bun to install the dependencies. hooks: build: bun install ``` #### Use Bun as a runtime You can even [use Bun as a runtime](https://devcenter.upsun.com/posts/bun-support-is-here/) by adjusting the `start` command as follows: ```yaml {location=".upsun/config.yaml"} applications: # The name of your app. myapp: # Choose Node.js version 20 or above. type: 'nodejs:20' # Override the default Node.js build flavor. build: flavor: none # Use Bun to install the dependencies. hooks: build: bun install # In the start command replace node with Bun. web: commands: start: 'bun app.js' ``` ## Connecting to services You can access service credentials to connect to [managed services](https://docs.upsun.com/add-services/) from environment variables present in the application container. Consult each of the individual service documentation to see how to retrieve and surface credentials into your application. - [Chroma](https://docs.upsun.com/add-services/chroma.md#3-use-the-relationship-in-your-application) - [ClickHouse](https://docs.upsun.com/add-services/clickhouse.md#usage-example) - [Elasticsearch](https://docs.upsun.com/add-services/elasticsearch.md#use-in-app) - [Edgee (Edge Analytics)](https://docs.upsun.com/add-services/edgee.md#setup-edgee) - [Gotenberg](https://docs.upsun.com/add-services/gotenberg.md#usage-example) - [Headless Chrome](https://docs.upsun.com/add-services/headless-chrome.md#use-in-app) - [InfluxDB](https://docs.upsun.com/add-services/influxdb.md#use-in-app) - [Kafka](https://docs.upsun.com/add-services/kafka.md#use-in-app) - [MariaDB/MySQL](https://docs.upsun.com/add-services/mysql.md#use-in-app) - [Memcached](https://docs.upsun.com/add-services/memcached.md#use-in-app) - [Mercure](https://docs.upsun.com/add-services/mercure.md#use-in-app) - [MongoDB](https://docs.upsun.com/add-services/mongodb.md#use-in-app) - [Network Storage](https://docs.upsun.com/add-services/network-storage.md#usage-example) - [OpenSearch](https://docs.upsun.com/add-services/opensearch.md#use-in-app) - [PostgreSQL](https://docs.upsun.com/add-services/postgresql.md#use-in-app) - [Qdrant](https://docs.upsun.com/add-services/qdrant.md#4-use-the-relationship-in-your-application) - [RabbitMQ](https://docs.upsun.com/add-services/rabbitmq.md#use-in-app) - [Redis](https://docs.upsun.com/add-services/redis.md#use-in-app) - [Solr](https://docs.upsun.com/add-services/solr.md#use-in-app) - [Valkey](https://docs.upsun.com/add-services/valkey.md#use-in-app) - [Varnish](https://docs.upsun.com/add-services/varnish.md#usage-example) - [Vault KMS](https://docs.upsun.com/add-services/vault.md#use-vault-kms) ## Frameworks All major Javascript/Node.js web frameworks can be deployed on Upsun. See dedicated guides for deploying and working with them: - [Express](https://docs.upsun.com/get-started/stacks/express.md) - [Next.js](https://docs.upsun.com/get-started/stacks/nextjs.md) - [Strapi](https://docs.upsun.com/get-started/stacks/strapi.md) --- # Source: https://docs.upsun.com/integrations/notifications.md # Health notifications Upsun can notify you when various events happen on your project, in any environment. At this time the only notification provided is a low disk space warning, but others may be added in the future. To add or modify an integration for a project, you need to be a [project admin](https://docs.upsun.com../administration/users.md#project-roles). ## Default low-disk email notifications When you create a new project, Upsun creates a default [low-disk email notification](#low-disk-warning) for all [project admins](https://docs.upsun.com../administration/users.md#project-roles). ## Available notifications ### Low-disk warning Upsun monitors disk space usage on all applications and services in your cluster. * When available disk space drops below 20% or 4 GB, whichever is smaller, a warning notification is generated. * When available disk space drops below 10% or 2 GB, whichever is smaller, a critical notification is generated. * When available disk space returns above 20% or 4 GB, whichever is smaller, an all-clear notification is generated. Notifications are generated every 5 minutes, so there may be a brief delay between when the threshold is crossed and when the notification is triggered. ## Configuring notifications Health notifications can be set up via the [Upsun CLI](https://docs.upsun.com/administration/cli.md), through a number of different channels. ### Email notifications A notification can trigger an email to be sent, from an address of your choosing to one or more addresses of your choosing. You can view an email notification by running `upsun integration:get`. ```bash upsun integration:get +--------------+---------------+ | Property | Value | +--------------+---------------+ | id | abcdefghijklm | | type | health.email | | role | | | from_address | | | recipients | - '#admins' | +--------------+---------------+ ``` To edit the `recipients` that receive the default email notification, use the `integration:update` command. ```bash upsun integration:update abcdefghijklm --recipients you@example.com ``` The `recipients` field may be any valid email address, or one of the following special values. * `#admins` maps to all project admins and up. * `#viewers` maps to everyone with access to the project. To add a new email notification, register a `health.email` integration as follows: ```bash upsun integration:add --type health.email --recipients them@example.com --recipients others@example.com ``` You must specify one or more `recipients`, each as its own switch. The default `from-address` points to the "Upsun Bot". You can also configure a custom `--from-address`. The `--from-address` is whatever address you want the email to appear to be from. It is completely fine to use the same email address for both `from-address` and `recipients`. Note that depending on the configuration of the recipient mail server (including SPF and DKIM DNS entries) when using a custom `from-address`, the email can be marked as spam or lost. ### Slack notifications A notification can trigger a message to be posted to a Slack channel via a [Slack app](https://api.slack.com/apps). #### 1. Optional: Create a Slack app **Note**: If you are already have a Slack app, you can jump to [enabling notifications](#2-enable-notifications). 1. Open the [Slack API website](https://api.slack.com/) and go to **Your apps**. 2. Click **Create an App**. 3. Choose if you want to build your app from scratch, or via [an app manifest](https://api.slack.com/concepts/manifests). 4. Give your app a name. 5. Select a workspace to install your app in. **Note**: If you are not an admin of the selected workspace, request approval to install your app there. 6. Click **Create App**. #### 2. Enable notifications 1. Open the [Slack API website](https://api.slack.com/) and go to **Your apps**. 2. Go to **Features** > **OAuth & Permissions** in the sidebar. 3. Scroll down to the **Scopes** area and select **User Token Scopes**. 4. Click **Add an OAuth Scope** to add the `chat:write` scope. ![Slack app scopes](https://docs.upsun.com/images/slack/slack-app-scopes.png "0.30") 5. Go to **Settings** > **Install app** in the sidebar. **Note**: If you are not an admin of the workspace, you need to provide a link to install the app into the workspace and onto a channel. Once the app is approved and installed, a **User OAuth Token** is provided in your app settings. Copy the token, and use it in the next step. 6. Using the **User OAuth Token**, run the following command: ```bash upsun integration:add --type health.slack --token --channel --project ``` For example, if you want your Slack app to post messages in the `project-notifications` channel, write the channel name in the command as you would reference it within Slack: ```bash upsun integration:add --type health.slack ... --channel '#project-notifications' ... ``` 6. When the integration is successfully configured, Upsun then sends an initial message to the channel. **Bot users v. Slack apps**: Previously, Upsun allowed for the configuration of health notifications sent to Slack via bot users and their associated API tokens. As of June 2024, Slack has deprecated bot users, and integrations must be configured using Slack apps as described above. If you already have defined an integration using a bot user API token, it will continue to work properly, though you should consider upgrading your processes to the above settings to avoid any future retirement. ### PagerDuty notifications A notification can trigger a message to be sent via PagerDuty, if you are using that service. First, create a new PagerDuty "[integration](https://support.pagerduty.com/docs/services-and-integrations)" that uses the Events API v2. Copy the "Integration Key" as known as the "routing key" for the integration. Now register a `health.pagerduty` integration as follows: ```bash upsun integration:add --type health.pagerduty --routing-key YOUR_ROUTING_KEY ``` Any notification will now trigger an alert in PagerDuty. ## Validate the integration You can then verify that your integration is functioning properly [using the CLI](https://docs.upsun.com/integrations/overview.md#validate-integrations) command ```bash upsun integration:validate ``` --- # Source: https://docs.upsun.com/learn/bestpractices/oneormany.md # From monoliths through headless to microservices With Upsun, you can run multiple application containers in a single environment. This gives you access to a large variety of setups and allows you to seamlessly upgrade your app from a monolith with a single application server to a more elaborate and effective topology. You can set up multiple apps to achieve the following: - Keep your backend and frontend systems separate - Run workers alongside your main app - Or even go for a full microservices architecture Upsun makes implementing such setups and switching from one to the other pain-free. The same flexibility applies to any supported services, from relational databases to search engines and message queues. Depending on your specific use case, you can run a single database, multiple databases inside a single instance, or multiple databases in multiple versions... It's up to you! Whether you embrace a mono-repo approach with a single Git repository describing your entire setup, or divide your project into multiple repositories, Upsun allows you to build the best architecture for your needs. But while the possibilities are endless, making the right choice between creating one big project with multiple apps or keeping each app in its own project can be a tough formula to crack. So read on for guidance! ## Separate projects If you have multiple apps sharing the same code but each of them has its own data, keep your apps in separate projects. Upsun provides the automation to deploy multiple projects from the same code base, which makes their maintenance effortless. **Note**: By design, Upsun doesn’t allow your app to access services in another project through HTTP. So separate projects are appropriate in the following cases: - Your apps are for different customers/clients - Your apps don't need to directly connect to the same database - Different teams are working on different apps - You want to develop true microservices, where each microservice is a fully standalone process with its own data When in doubt over your own needs, it's better to keep separate projects than build an architecture that may prove difficult for you to maintain. ## Clustered applications A clustered application is one where your project requires multiple _app services_ that are all part of the same conceptual project. Clustered applications can range from a straightforward headless architecture, where frontend and backend systems are separated, to micro-services with dozens of apps in multiple runtimes and frameworks forming a consistent whole. Meaning, removing one of the app services would break the others. Upsun allows you to configure access from one service to another without having to worry about service discovery or complex _ingress controllers_. [Configuring incoming routes](https://docs.upsun.com/define-routes.md) is straightforward. You can have services that are only exposed to another service as well as services that are exposed to the internet. In a clustered application, you can have one of the following configurations: - Multiple [applications](https://docs.upsun.com/create-apps/multi-app.md), often in different directories or with separate code bases that deploy separately - A single app that spawns one or more [worker instances](https://docs.upsun.com/create-apps/image-properties/workers.md) that run background processes With a clustered application, you often don't need multiple service instances. The [MySQL, MariaDB](https://docs.upsun.com/add-services/mysql.md), and [Solr](https://docs.upsun.com/add-services/solr.md) services support defining multiple databases on a single service, which is significantly more efficient than defining multiple services. [Redis](https://docs.upsun.com/add-services/redis.md), [Memcached](https://docs.upsun.com/add-services/memcached.md), [Elasticsearch](https://docs.upsun.com/add-services/elasticsearch.md), and [RabbitMQ](https://docs.upsun.com/add-services/rabbitmq.md) natively support multiple bins (also called _queues_ or _indexes_) defined by the client application as part of the request. Therefore, they don't need additional configuration on Upsun. Clustered applications are appropriate in the following cases: - You want one user-facing app and an entirely separate admin-facing app that are both operating on the same data - You want to have a user-facing app and a separate worker process (either the same code or separate) that handles background tasks - You want a single conceptual app written in multiple programming languages ## A note on "multi-site" applications Some Content Management Systems or other applications support running multiple logical "sites" off of a single code base. This approach isn't recommended on Upsun. This multi-site logic is often dependent on the domain name of the incoming request, which on Upsun varies by branch. Running multiple databases, as is often recommended with this approach, is supported on Upsun but makes the setup process for each site more difficult. Leveraging the multi-site capabilities of an app are appropriate only in the following cases: - There is only a single team working on all of the "sites" involved - All "sites" should be updated simultaneously as a single unit - Each individual site is relatively low traffic. This means that the total traffic for all sites is appropriate for the resources that have been allocated. [allocated resources](https://docs.upsun.com/manage-resources.md) - All sites really do use the same codebase with no variation, just different data Otherwise, [separate projects](#separate-projects) are a better long-term plan. --- # Source: https://docs.upsun.com/add-services/opensearch.md # OpenSearch (search service) OpenSearch is a distributed RESTful search engine built for the cloud. See the [OpenSearch documentation](https://opensearch.org/docs/latest/) for more information. To switch from Elasticsearch, follow the same procedure as for [upgrading](#upgrading). ## Supported versions In the list below, notice that there you only specify the major version. Each version represents a rolling release of the latest minor version available from the upstream. The latest compatible minor version and patches are applied automatically. - 3 - 2 ## Deprecated versions The following versions are still available in your projects, but they're at their end of life and are no longer receiving security updates from upstream, or are no longer the recommended way to configure the service on Upsun. - 1.2 - 1.1 To ensure your project remains stable in the future, switch to [a supported version](#supported-versions). ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "username": null, "scheme": "http", "service": "opensearch", "fragment": null, "ip": "169.254.99.100", "hostname": "azertyuiopqsdfghjklm.opensearch.service._.eu-1.platformsh.site", "port": 9200, "cluster": "azertyuiopqsdf-main-7rqtwti", "host": "opensearch.internal", "rel": "opensearch", "path": null, "query": [], "password": "ChangeMe", "type": "opensearch:3", "public": false, "host_mapped": false } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_OPENSEARCH_HOST="$(echo "$RELATIONSHIPS_JSON" | jq -r '.opensearch[0].host')" ``` ## Usage example ### 1. Configure the service To define the service, use the ``opensearch`` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: opensearch: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. ### 2. Define the relationship To define the relationship, use the following configuration: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container (````) now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: opensearch ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). ### Example configuration ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: opensearch: services: # The name of the service container. Must be unique within a project. opensearch: type: opensearch:3 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: opensearch: service: opensearch endpoint: opensearch services: # The name of the service container. Must be unique within a project. opensearch: type: opensearch:3 ``` ### Use in app To use the configured service in your app, add a configuration file similar to the following to your project. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" [...] # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: opensearch: services: # The name of the service container. Must be unique within a project. opensearch: type: opensearch:3 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" [...] # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: opensearch: service: opensearch endpoint: opensearch services: # The name of the service container. Must be unique within a project. opensearch: type: opensearch:3 ``` This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory. `myapp` has access to the `opensearch` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship) (as per [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships). From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference). ```bash {location="myapp/.environment"} # Set environment variables for individual credentials. # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. export OS_SCHEME="${OPENSEARCH_SCHEME}" export OS_HOST="${OPENSEARCH_HOST}" export OS_PORT="${OPENSEARCH_PORT}" # Surface more common OpenSearch connection string variables for use in app. export OS_USERNAME="${OPENSEARCH_USERNAME}" export OS_PASSWORD="${OPENSEARCH_PASSWORD}" export OPENSEARCH_HOSTS=[\"$OS_SCHEME://$OS_HOST:$OS_PORT\"] ``` The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``OPENSEARCH_HOSTS`` can be used within the application to connect to the service. Note that ``OPENSEARCH_HOSTS``, and all Upsun [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) like ``OPENSEARCH_HOST``, are environment-dependent. Unlike the build produced for a given commit, they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment. A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](https://docs.upsun.com/get-started.md). **Note**: When you create an index on OpenSearch, don’t specify the ``number_of_shards`` or ``number_of_replicas`` settings in your OpenSearch API call. These values are set automatically based on available resources. ## Authentication By default, OpenSearch has no authentication. No username or password is required to connect to it. You may optionally enable HTTP Basic authentication. To do so, include the following in your `.upsun/config.yaml` configuration: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. opensearch: type: opensearch:3 configuration: authentication: enabled: true ``` That enables mandatory HTTP Basic auth on all requests. The credentials are available in any relationships that point at that service, in the `OPENSEARCH_USERNAME` and `OPENSEARCH_PASSWORD` [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``. Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) directly rather than hard coding any values. This functionality is generally not required if OpenSearch isn't exposed on its own public HTTP route. However, certain applications may require it, or it allows you to safely expose OpenSearch directly to the web. To do so, add a route to `.upsun/config.yaml` that has `opensearch:opensearch` as its upstream (where `opensearch` is whatever you named the service). For example: ```yaml {location=".upsun/config.yaml"} routes: "https://www.os.{default}/": type: redirect to: "https://os.{default}/" "https://os.{default}/": type: upstream upstream: "opensearch:opensearch" services: # The name of the service container. Must be unique within a project. opensearch: configuration: authentication: enabled: true ``` ## Plugins OpenSearch offers a number of plugins. To enable them, list them under the `configuration.plugins` key in your `.upsun/config.yaml` file, like so: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. opensearch: configuration: plugins: - analysis-icu ``` In this example you'd have the ICU analysis plugin and the size mapper plugin. If there is a publicly available plugin you need that isn't listed here, [contact support](https://docs.upsun.com/learn/overview/get-support.md). ### Available plugins This is the complete list of plugins that can be enabled: | Plugin | Description | 1 | 2 | 3 | |-------------------------|-------------------------------------------------------------------------------------------|-----|----|-----| | `analysis-icu` | Support ICU Unicode text analysis | * | * | * | | `analysis-kuromoji` | Japanese language support | * | * | * | | `analysis-nori` | Integrates Lucene Nori analysis module into OpenSearch | * | * | * | | `analysis-phonetic` | Phonetic analysis | * | * | * | | `analysis-smartcn` | Smart Chinese Analysis Plugins | * | * | * | | `analysis-stempel` | Stempel Polish Analysis Plugin | * | * | * | | `analysis-ukrainian` | Ukrainian language support | * | * | * | | `ingest-attachment` | Extract file attachments in common formats (such as PPT, XLS, and PDF) | * | * | * | | `mapper-annotated-text` | Adds support for text fields with markup used to inject annotation tokens into the index | * | * | * | | `mapper-murmur3` | Murmur3 mapper plugin for computing hashes at index-time | * | * | * | | `mapper-size` | Size mapper plugin, enables the `_size` meta field | * | * | * | | `repository-s3` | Support for using S3 as a repository for Snapshot/Restore | * | * | * | ### Alternative plugins These plugins are currently available for OpenSearch `2.0` and `3.0`. The names below show exactly how they should be added to your configuration. For example, to use the `alerting` plugin, specify it in your `services.yaml` as so: ```yaml {location=".upsun/config.yaml"} # The name of the service container. Must be unique within a project. opensearch: type: "opensearch:3" disk: 1024 configuration: plugins: - alerting ``` **Different names used**: It should be noted that **these names may differ to what they are commonly known as in the [OpenSearch docs](https://opensearch.org/docs/latest/).** To help your understanding of what each plugin does, please click each plugin for a link to the corresponding GitHub repositories. | Plugin | Description | 1 | 2 | 3 | |-----------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------|-------|-----|-----| | [`alerting`](https://github.com/opensearch-project) | Monitor data and send alert notifications automatically | N/A | * | * | | [`opensearch-anomaly-detection`](https://github.com/opensearch-project/anomaly-detection) | Detect anomalies as your log data and monitor data in near real time | N/A | * | * | | [`asynchronous-search`](https://github.com/opensearch-project/asynchronous-search) | Run search queries in the background and retrieve results as they become available | N/A | * | * | | [`opensearch-cross-cluster-replication`](https://github.com/opensearch-project/cross-cluster-replication) | Replicate data across two OpenSearch clusters | N/A | * | * | | [`opensearch-custom-codecs`](https://github.com/opensearch-project/custom-codecs) | Provide custom Lucene codecs for loading through Apache Lucene's `NamedSPILoader` | N/A | * | * | | [`opensearch-flow-framework`](https://github.com/opensearch-project/flow-framework) | Innovate AI applications on OpenSearch | N/A | * | * | | [`notifications`](https://github.com/opensearch-project/notifications) | A central location for all of your notifications from OpenSearch plugins | N/A | * | * | | [`opensearch-reports-scheduler`](https://github.com/opensearch-project/reporting) | Export and share reports from OpenSearch Dashboards dashboards, saved search, alerts and visualizations | N/A | * | * | | [`geospatial`](https://github.com/opensearch-project/geospatial) | An OpenSearch plugin that contains geospatial specific features | N/A | * | * | | [`opensearch-index-management`](https://github.com/opensearch-project/index-management) | A suite of features to monitor and manage indexes | N/A | * | * | | [`opensearch-job-scheduler`](https://github.com/opensearch-project/job-scheduler) | Schedule periodical jobs running within OpenSearch nodes | N/A | * | * | | [`opensearch-knn`](https://github.com/opensearch-project/k-NN) | Easily run the nearest neighbor search on billions of documents | N/A | * | * | | [`opensearch-ml-plugin`](https://github.com/opensearch-project/ml-commons/) | Leverage existing open source machine learning algorithms | N/A | * | * | | [`opensearch-skills`](https://github.com/opensearch-project/skills) | Provides tools for ml-common's agent framework OpenSearch ml-commons | N/A | * | * | | [`neural-search`](https://github.com/opensearch-project/neural-search) | Index documents and conduct a neural search on indexed documents | N/A | * | * | | [`opensearch-observability`](https://github.com/opensearch-project/observability) | Collection of plugins and applications that let you visualize data-driven events | N/A | * | * | | [`performance-analyzer`](https://github.com/opensearch-project/performance-analyzer) | A REST API that allows you to query numerous performance metrics | N/A | * | * | | [`opensearch-sql-plugin`](https://github.com/opensearch-project/sql) | Extract insights out of OpenSearch using the familiar SQL or Piped Processing Language (PPL) query syntax | N/A | * | * | ### Plugin removal Removing plugins previously added in your `.upsun/config.yaml` file doesn't automatically uninstall them from your OpenSearch instances. This is deliberate, as removing a plugin may result in data loss or corruption of existing data that relied on that plugin. Removing a plugin usually requires reindexing. To permanently remove a previously enabled plugin, [upgrade the service](#upgrading) to create a new instance of OpenSearch and migrate to it. In most cases it isn't necessary as an unused plugin has no appreciable impact on the server. ## Upgrading The OpenSearch data format sometimes changes between versions in incompatible ways. OpenSearch doesn't include a data upgrade mechanism as it's expected that all indexes can be regenerated from stable data if needed. To upgrade (or downgrade) OpenSearch, use a new service from scratch. There are two ways to do so. ### Destructive In your `.upsun/config.yaml` file, change the version *and* name of your OpenSearch service. Be sure to also update the reference to the now changed service name in it's corresponding application's `relationship` block. When you push that to Upsun, the old service is deleted and a new one with the new name is created with no data. You can then have your application reindex data as appropriate. This approach has the downsides of temporarily having an empty OpenSearch instance, which your application may or may not handle gracefully, and needing to rebuild your index afterward. Depending on the size of your data that could take a while. ### Transitional With a transitional approach, you temporarily have two OpenSearch services. Add a second OpenSearch service with the new version a new name and give it a new relationship in `.upsun/config.yaml`. You can optionally run in that configuration for a while to allow your application to populate indexes in the new service as well. Once you're ready to switch over, remove the old OpenSearch service and relationship. You may optionally have the new OpenSearch service use the old relationship name if that's easier for your app to handle. Your application is now using the new OpenSearch service. This approach has the benefit of never being without a working OpenSearch instance. On the downside, it requires two running OpenSearch servers temporarily, each of which consumes resources and needs adequate disk space. Depending on the size of your data, that may be a lot of disk space. --- # Source: https://docs.upsun.com/administration/organizations.md # Organizations Organizations allow you to manage your Upsun projects, users, and billing. You can group multiple projects in one organization and manage them together. To manage users within your organization, see how to [manage organization users](https://docs.upsun.com/administration/users.md#manage-organization-users). ## Manage your organization settings As an organization owner, you can manage the basic settings for your organization such as its name and URL. To change the name (URL) and label of the ``acme`` organization, run: ```bash {} upsun organization:info --org acme label "Acme Corp" name acme-corp ``` To verify the changes, run: ```bash {} upsun organization:info --org acme-corp ``` ## Manage your organization billing As an organization owner or an organization user with the **Manage billing** permission, you can access and download invoices and edit billing information such as the stored credit card and billing address. ## Create a new organization You can create new organizations with different payment methods and billing addresses and organize your projects as you want. To create an organization with the label ``Acme`` and the name (URL) ``acme``, run: ```bash {} upsun organization:create --label "Acme" --name acme --country "United States" ``` To verify the changes, run: ```bash {} upsun organization:info --org acme ``` **Note**: To monitor your spend, you can [set billing alerts](https://docs.upsun.com/administration/billing/monitor-billing.md#manage-billing-alerts) on your new organization. Billing alerts are based on a [current month estimate](https://docs.upsun.com/administration/billing/monitor-billing.md#current-month-estimate). Once that estimate reaches a defined threshold, you receive an email notification. ## Delete an existing organization As an organization owner, you can delete your own organization. Note that if your organization owns projects or owes remaining invoices, you can not delete it yourself. To have it deleted, [contact support](https://docs.upsun.com/learn/overview/get-support.md). To delete the organization ``acme``, run: ```bash {} upsun organization:delete --org acme ``` ## Transfer project ownership You can transfer your project ownership to a different organization at anytime. To do this, you must be an organization owner or have the [manage billing permission](https://docs.upsun.com/administration/users.md#organization-permissions). 1. Make the new organization owner a [project admin](https://docs.upsun.com/administration/users.md#) for the project you want to transfer. 2. To ask for the transfer, from your organization account open a [support ticket](https://docs.upsun.com/learn/overview/get-support.md). Once the transfer is completed, the new organization can administer all project settings and billing and receives future invoices. Ownership transfer automatically transfers subscription charges to the new organization. ## Transfer organization ownership To transfer an organization to a different owner, first make sure that user is part of the organization. If they aren't yet, [add them](https://docs.upsun.com/administration/users.md#add-a-user-to-an-organization). Then open a [support ticket](https://docs.upsun.com/learn/overview/get-support.md) from the current organization to ask for the transfer. ## Fixed and Flex organizations ### What is an Upsun Fixed organization? Ideal for workloads that have consistent resource requirements with stable and predictable usage. Users can select a plan with predefined CPU and Memory resources. You can not adjust these resources, nor scale them automatically. To increase capacity, you’ll need to upgrade to a higher plan. **Fixed resources**: **Fixed:** Resource from the plan is applied to the production environment. For preview, the user has the default small size for all containers. ### What is an Upsun Flex organization? Ideal for workloads that evolve over time or have dynamic resource requirements. Flex will suit most use cases. Users will be able to allocate the exact CPU and Memory resources that your applications and services need. You can adjust these resources at any time, or configure them to adapt automatically. You are charged based on the resources you allocate. **Flex resources**: **Flex:** Users can customize resources per container (per app or service) for **all** environments. ### What can you do? When creating a new organization, users will be able to select the organization type from a drop-down option based on their preference. Once the organization is created, users can manage their organizations like they do today. ### Feature differences #### Developer experience | **Feature** | **Upsun Fixed** | **Upsun Flex** | |-------------|-----------------|----------------| | Manual backups | Yes | Yes | | Health notifications | Yes | Yes | | Preview environments | Yes | Yes | | Free SSL certificates | Yes | Yes | | Source integrations (GitHub, GitLab, Bitbucket) | Yes | Yes | | Runtime operations | Yes | Yes | | Custom # of preview environments | No (3 small included, purchase by bulk of 3) | Yes | | Custom size of preview environments | No | Yes | | Resource allocation | Project Level Plans | Container Level | | Custom build resources | No | Yes | | Autoscaling | No | Yes | | Horizontal scaling of apps | No | Yes | | Guaranteed CPU | No | Yes | | Dedicated architecture | Yes | No | | Custom domains on preview environments | Enterprise and Elite only | Yes | | Automated code updates | Enterprise and Elite only | Yes | | Manual deployment | Enterprise and Elite only | Yes | | Zero downtime deployment | Enterprise and Elite only | Yes | | Custom backup retention policies | Different packages | Unlimited (pay for storage) | | Email SMTP server | Yes | Yes | | Email validation (DKIM) | Enterprise and Elite only | Yes | | ElasticSearch (Premium containers) | Enterprise and Elite only | No | | MongoDB (Premium containers) | Enterprise and Elite only | No | #### Observability tools | **Feature** | **Upsun Fixed** | **Upsun Flex** | |-------------|-----------------|----------------| | Logs forwarding | Enterprise and Elite only | Yes | | Blackfire | Enterprise and Elite only (or self-service add-on) | Yes | | HTTP Traffic | Yes (but longer timeframe with Enterprise) | Yes | | Continuous profiling | Enterprise and Elite only | Yes | | Resources | Yes (but longer timeframe with Enterprise) | Yes | #### User management | **Feature** | **Upsun Fixed** | **Upsun Flex** | |----------------|----------------------------------------|------------------| | Google SSO | Enterprise and Elite only | Yes, with add-on | | OpenID Connect | Elite only | Yes, with add-on | | Multifactor Authentication | Enterprise and Elite only | Yes, with add-on | | Teams | Enterprise and Elite only | Yes, with add-on | #### Support & SLAs | **Feature** | **Upsun Fixed** | **Upsun Flex** | |-------------|-----------------|----------------| | Support SLA | Enterprise and Elite only | Yes, with add-on | | Uptime SLA | Enterprise and Elite only (Architecture based) | Yes, with add-on | | CDN | Enterprise and Elite only | Yes | | Fastly WAF | Enterprise & Elite only as add-on | Yes, with add-on | | Upsun WAF | Enterprise and Elite only | Yes | #### Billing | **Feature** | **Upsun Fixed** | **Upsun Flex** | |-------------|-----------------|----------------| | Pay as you go (Monthly) | Yes | Yes | | Pay with credit card | Yes | Yes | | Pay with SEPA | Enterprise and Elite only | Yes | | Volume discounts | No | Yes | #### Security & Compliance | **Feature** | **Upsun Fixed** | **Upsun Flex** | |-------------|-----------------|----------------| | Privacy regulations | Yes | Yes | | SOC 2 | Yes | Yes | | PCI DSS Level 1-compatible | Yes | Yes | | HIPAA | Enterprise and Elite only in specific regions | Coming soon | ### Fixed and Flex FAQs #### What happens to my URL? - `https://auth.api.platform.sh/` will become `https://auth.upsun.com/`. #### If I had a Fixed organization (previously Platform.sh), will I be redirected to my organizations? - Yes. You will be automatically redirected to the new console and can log in using the same credentials. #### Will I be able to switch if I have both Fixed and Flex organizations? - Yes. You can navigate between organizations (Fixed or Flex) from a drop-down list. #### How will Fixed vs Flex be identifiable in the console? - Organizations will have tags next to their names in the console. - Organizations will also be categorized by organization type in the console. #### Will I be able to access Fixed projects via the Upsun CLI? - Correct. #### Will I still use the same configuration files for Fixed projects? - Correct. The same configuration file structures remain (`.platform.app.yaml`, `.platform/services.yaml`, `.platform/routes.yaml`, etc). #### Besides the name "Platform.sh" going away, will there be visual changes in the console? Yes. - There will be a new way to create organizations (you can now choose Fixed or Flex). - Ability to navigate between organization types. - **[15-day free trial](https://auth.upsun.com/register/)** for users creating Flex organizations. #### With a unified CLI, will there be a way to identify Fixed vs Flex in the project list? - You will see a list of all organizations. - There is no field in the CLI that explicitly identifies Fixed vs Flex. #### Do Upsun projects run in the same regions as Platform.sh projects? Correct. #### How can I anticipate my monthly invoice with usage-based pricing? Upsun gives a monthly price estimation for the current and next full month based on current usage pattern. #### Can I use the same credentials / SSO / 2FA on Platform and Upsun? Yes. #### Can I use Blackfire for my Upsun applications? Upsun includes Blackfire by default. #### Will Upsun be delivered entirely on a “self service” model? Yes. Additionally, Upsun offers discounts based on volume commitment that is contracted for 1+ Year. #### Can I try Upsun before buying? Yes, you can [sign-up for the 15-day trial](https://auth.upsun.com/register/). --- # Source: https://docs.upsun.com/dedicated-environments/dedicated-gen-2/overview.md # Source: https://docs.upsun.com/dedicated-environments/overview.md # Source: https://docs.upsun.com/integrations/overview.md # Source: https://docs.upsun.com/learn/overview.md # What is Upsun Fixed? Upsun is a Cloud Application Platform built especially for continuous deployment. It allows you to host web applications on the cloud while making your development and testing workflows more productive. If you're new to Upsun, the [Philosophy](https://docs.upsun.com/learn/overview/philosophy.md), [Structure](https://docs.upsun.com/learn/overview/structure.md), and [Build and Deploy](https://docs.upsun.com/learn/overview/build-deploy.md) pages cover all the basics to start on the right track. The main requirement of Upsun is that you use Git to manage your application code. If you have a single-app project, you can configure it from a single `.upsun/config.yaml` file, usually located at the root of your app folder in your Git repository. [Multi-app projects](https://docs.upsun.com/create-apps/multi-app.md) can be set up in various ways. Upsun is built on Debian, supports many different programming [languages](https://docs.upsun.com/languages.md) and environments, and features recommended optimizations for several [featured frameworks](https://docs.upsun.com/get-started.md). Finally, you can also get tips for setting up your own [development workflow](https://docs.upsun.com/development.md) and [administrating](https://docs.upsun.com/administration.md) your Upsun account. ## Git Driven Infrastructure As a Cloud Application Platform, Upsun automatically manages everything your application needs to run. That means you can, and should, view your infrastructure needs as part of your application and address them under version control. ### Infrastructure as code Upsun covers not only all of your hosting needs but also most of your DevOps needs. It is a single tool that covers the application life-cycle from development to production and scaling. You only need to write your code, including a single or a few YAML files that specify your desired infrastructure, commit it to Git, and push. You don't need to set up anything manually. The web server is already set up and configured, as is any database, search engine, or cache that you specify. Every branch you push can be made a fully independent environment—complete with your application code, a copy of your database, a copy of your search index, a copy of your user files, everything. Its automatically generated URL can be sent to stakeholders or automated CI systems. It really is "what would my site look like if I merged this to production?" every time. You can use these concepts to replicate a traditional development/staging/production workflow, or even to give every feature its own effective staging environment before merging to production (empowering you to use git-flow like methodologies even better). You could also have an intermediary integration branch for several other branches. Upsun respects the structure of branches. It's entirely up to you. ### Full stack management Managing your full stack on Upsun gives you the following unique features: 1. **Unified Environment:** All of your [services](https://docs.upsun.com/add-services.md) (MySQL, Elasticsearch, MongoDB, etc.) are managed inside the cluster and included in the price, with no external single-points-of-failure. When you [back up an environment](https://docs.upsun.com/environments/backup.md), you get a fully consistent snapshot of your whole application. 2. **Multi-Services & Multi-App:** You can deploy [multiple applications](https://docs.upsun.com/create-apps/multi-app.md) (for example, in a microservice-based architecture), using multiple data backends (MySQL, PostgreSQL, Redis, etc.) written in multiple frameworks (Drupal + NodeJS + Flask, for example) in multiple languages, all in the same cluster. 3. **Full Cluster Cloning Technology:** The full production cluster can be cloned in under a minute—including all of its data—to create on-the-fly, ephemeral [preview environments](https://docs.upsun.com/glossary.md#preview-environment) that are a byte-level copy of production. 4. **Fail-Proof Deployments:** Every time you test a new feature, you also test the deployment process. 5. **Continuous Deployment from the Start:** Everything is build-oriented, with a consistent, repeatable build process, simplifying the process of keeping your application up-to-date and secure. --- # Source: https://docs.upsun.com/learn/overview/philosophy.md # Philosophy Upsun aims at reducing configuration and making developers more productive. It abstracts your project infrastructure and manages it for you, so you never have to configure services like a web server, a MySQL database, or a Redis cache from scratch again. Upsun is built on one main idea — your server infrastructure is part of your app, so it should be version controlled along with your app. Every branch you push to your Git repository can come with bug fixes, new features, **and** infrastructure changes. You can then test everything as an independent deployment, including your application code and all of your services with a copy of their data (database entries, search index, user files, etc.). This allows you to preview exactly what your site would look like if you merged your changes to production. ## The basics On Upsun, a **project** is linked to a Git repository and is composed of one or more **apps**. An app is a directory in your Git repository with a specific Upsun configuration and dedicated HTTP endpoints (via the `.upsun/config.yaml` file). Projects are deployed in **environments**. An environment is a standalone copy of your live app which can be used for testing, Q&A, implementing new features, fixing bugs, and so on. Every project you deploy on Upsun is built as a *virtual cluster* containing a series of containers. The main branch of your Git repository is always deployed as a production cluster. Any other branch can be deployed as a staging or development cluster. There are three types of containers within your cluster, all usually configured from a single `.upsun/config.yaml` file stored alongside your code: - The [*router*](https://docs.upsun.com/define-routes.md) is a single Nginx process responsible for mapping incoming requests to an app container, and for optionally providing HTTP caching. - One or more [*apps*](https://docs.upsun.com/create-apps.md) holding the code of your project. - Some optional [*services*](https://docs.upsun.com/add-services.md) like MySQL/MariaDB, Elasticsearch, Redis, or RabbitMQ. They come as optimized pre-built images. ## The workflow Every time you deploy a branch to Upsun, the code is *built* and then *deployed* on a new cluster. The [**build** process](https://docs.upsun.com/learn/overview/build-deploy.md#build-steps) looks through the configuration files in your repository and assembles the necessary containers. The [**deploy** process](https://docs.upsun.com/learn/overview/build-deploy.md#deploy-steps) makes those containers live, replacing the previous versions, with no service downtime. Depending on your needs, you can also [set up a **post-deploy** hook](#add-a-post-deploy-hook) to run after your app is deployed and your application container starts accepting traffic. Adding a [`post-deploy` hook](https://docs.upsun.com/create-apps/hooks/hooks-comparison.md#post-deploy-hook) can be useful to run updates that don't require exclusive database access. Note that if you're using Gatsby to pull from a backend container on the same environment, you need a `post-deploy` hook to successfully build and deploy your app. ### How your app is built During the [build step](https://docs.upsun.com/learn/overview/build-deploy.md#build-steps), dependencies specified in `.upsun/config.yaml` are installed on application containers. You can also customize the build step by providing a [`build` hook](https://docs.upsun.com/create-apps/hooks/hooks-comparison.md#build-hook) composed of one or more shell commands that help create your production codebase. That could be compiling TypeScript files, running some scripts, rearranging files on disk, or whatever else you want. Note that at this point all you have access to is the filesystem; there are **no services or other databases available**. Your live website is unaffected. Once the build step is completed, the filesystem is frozen and a read-only container image is created. That filesystem is the final build artifact. ### How your app is deployed Before starting the [deployment](https://docs.upsun.com/learn/overview/build-deploy.md#deploy-steps) of your app, Upsun pauses all incoming requests and holds them to avoid downtime. Then, the current containers are stopped and the new ones are started. Upsun then opens networking connections between the various containers, as specified in `.upsun/config.yaml`. The connection information for each service is available from the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables), or the [`PLATFORM_RELATIONSHIPS` environment variable](https://docs.upsun.com/development/variables/use-variables.md). Similar to the build step, you can define a [deploy hook](https://docs.upsun.com/create-apps/hooks/hooks-comparison.md#deploy-hook) to prepare your app. Your app has complete access to all services, but the filesystem where your code lives is now read-only. Finally, Upsun opens the floodgates and lets incoming requests through your newly deployed app. ### Add a post-deploy hook You can add a [`post-deploy` hook](https://docs.upsun.com/create-apps/hooks/hooks-comparison.md#post-deploy-hook) to be run after the build and deploy steps. Similar to the [`deploy` hook](https://docs.upsun.com/create-apps/hooks/hooks-comparison.md#deploy-hook), the `post-deploy` hook only runs once your application container accepts requests. So you can use it to run updates such as content imports or cache warmups that can be executed simultaneously with normal traffic. During a redeploy, the `post-deploy` hook is the only hook that is run. ## Get support If you're facing an issue with Upsun, open a [support ticket](https://docs.upsun.com/learn/overview/get-support.md). ## What's next? To get a feeling of what working with Upsun entails, see the [Get Started](https://docs.upsun.com/get-started.md) framework guides. --- # Source: https://docs.upsun.com/create-apps/web/php-basic.md # Create a basic PHP app with a front controller To handle dynamic requests to your PHP app, you might want to use a [front controller](https://en.wikipedia.org/wiki/Front_controller). The following example shows how for such an app you might start defining [your web server](https://docs.upsun.com/create-apps/image-properties/web.md). ## Define a document root Start by defining your document root (where all your publicly visible pages are). ```yaml {location=".upsun/config.yaml"} applications: myapp: source: root: "/" web: locations: '/': root: 'public' ``` ## Define a front controller Define where all requests that don't match a file in the document root are sent. ```yaml {location=".upsun/config.yaml"} applications: myapp: source: root: "/" web: locations: '/': root: 'public' passthru: '/index.php' index: - index.php ``` In this case, `/index.php` acts as a front controller and handles dynamic requests. Because it handles dynamic requests, you want to ensure that scripts are enabled and responses aren't cached. ```yaml {location=".upsun/config.yaml"} applications: myapp: source: root: "/" web: locations: '/': ... scripts: true # No caching for static files. # (Dynamic pages use whatever cache headers are generated by the program.) expires: -1 ``` ## Define rules You might want to define specific rules for the location. For example, you might want to allow all kinds of files except mp4 files. ```yaml {location=".upsun/config.yaml"} applications: myapp: source: root: "/" web: locations: '/': ... # Allow all file types generally allow: true rules: # Disallow .mp4 files specifically. \.mp4$: allow: false ``` ## Set different rules for specific locations You might want to set specific rules for specific locations. For example, you might have files in your `/public/images` directory that are served at `/images`. You could define a specific cache time for them and limit them to only static image files. ```yaml {location=".upsun/config.yaml"} applications: myapp: source: root: "/" web: locations: '/': ... # Set a 5 min expiration time for static files in this location. # Missing files are sent to front controller # through the '/' location above. '/images': expires: 300 passthru: true # Do not execute PHP scripts from this location and do not # deliver their source code (for enhanced security). scripts: false allow: false rules: # Only allow static image files in this location '\.(jpe?g|png|gif|svgz?|ico|bmp)$': allow: true ``` ## Complete example ```yaml {location=".upsun/config.yaml"} applications: myapp: source: root: "/" web: locations: '/': root: 'public' passthru: '/index.php' index: - index.php scripts: true # No caching for static files. # (Dynamic pages use whatever cache headers are generated by the program.) expires: -1 # Allow all file types generally allow: true rules: # Disallow .mp4 files specifically. \.mp4$: allow: false # Set a 5 min expiration time for static files in this location. # Missing files are sent to front controller # through the '/' location above. '/images': expires: 300 passthru: true # Do not execute PHP scripts from this location and do not # deliver their source code (for enhanced security). scripts: false allow: false rules: # Only allow static image files in this location '\.(jpe?g|png|gif|svgz?|ico|bmp)$': allow: true ``` --- # Source: https://docs.upsun.com/languages/php.md # PHP **Note**: You can now use the Upsun [composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) to install runtimes and tools in your application container. To find out more about this feature, see the [dedicated documentation page](https://docs.upsun.com/create-apps/app-reference/composable-image.md). Also, see how you can [modify your PHP runtime when using the composable image](#modify-your-php-runtime-when-using-the-composable-image). ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 8.5 - 8.4 - 8.3 - 8.2 Note that from PHP versions 7.1 to 8.1, the images support the Zend Thread Safe (ZTS) version of PHP. ### Specify the language To use PHP, specify `php` as your [app's `type`](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#types): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. : type: 'php:' ``` For example: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' ``` ### Deprecated versions The following versions are [deprecated](https://docs.upsun.com/glossary.md#deprecated-versions). They're available, but they don't receive security updates from upstream and aren't guaranteed to work. They'll be removed in the future – consider migrating to a [supported version](#supported-versions). - 8.1 - 8.0 - 7.4 - 7.3 - 7.2 - 7.1 - 7.0 - 5.6 - 5.5 - 5.4 ## Usage example Configure your app to use PHP on Upsun. ### 1. Specify the version Choose a [supported version](#supported-versions) and add it to your [app configuration](https://docs.upsun.com../../create-apps/_index.md): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' ``` ### 2. Serve your app To serve your app, define what (and how) content should be served by setting the [`locations` parameter](https://docs.upsun.com/create-apps/image-properties/web.md#locations). Usually, it contains the two following (optional) keys: - `root` for the document root, the directory to which all requests for existing `.php` and static files (such as `.css`, `.jpg`) are sent. - `passthru` to [define a front controller](https://docs.upsun.com../../create-apps/web/php-basic.md#set-different-rules-for-specific-locations) to handle nonexistent files. The value is a file path relative to the [app root](https://docs.upsun.com/create-apps/image-properties/source.md). **Note**: For enhanced security, when setting ``passthru`` to ``true``, you might also want to add the following configuration: - Set ``scripts`` to ``false``. This prevents PHP scripts from being executed from the specified location. - Set ``allow`` to ``false``. By default, when PHP scripts aren’t executed, their source code is delivered. Setting ``allow`` to ``false`` allows you to keep the source code of your PHP scripts confidential. Adjust the `locations` block to fit your needs. In the following example, all requests made to your site's root (`/`) are sent to the `public` directory and nonexistent files are handled by `app.php`: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' web: locations: '/': root: 'public' passthru: '/app.php' ``` See how to [create a basic PHP app with a front controller](https://docs.upsun.com../../create-apps/web/php-basic.md). To have more control, you can define rules to specify which files you want to allow [from which location](https://docs.upsun.com../../create-apps/web/php-basic.md#set-different-rules-for-specific-locations). ### Complete example A complete basic app configuration looks like the following: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' web: locations: '/': root: 'public' passthru: '/app.php' ``` ## Dependencies Up to PHP version 8.1, it's assumed that you're using [Composer](https://getcomposer.org/) 1.x to manage dependencies. If you have a `composer.json` file in your code, the default [build flavor is run](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#build): ```bash composer --no-ansi --no-interaction install --no-progress --prefer-dist --optimize-autoloader ``` To use Composer 2.x on your project, either use PHP 8.2+ or, in your app configuration, add the following [dependency](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#dependencies): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' dependencies: php: composer/composer: '^2' ``` Adding a dependency to the [dependencies block](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#dependencies) makes it available globally. So you can then use included dependencies as commands within your app container. You can add multiple global dependencies to the dependencies block, such as [Node.js](https://docs.upsun.com../nodejs.md#2-specify-any-global-dependencies). If you want to have more control over Composer or if you don't want to use Composer at all, adapt the [build flavor](#change-the-build-flavor). You can also use a [private, authenticated third-party Composer repository](https://docs.upsun.com/languages/php/composer-auth.md). ### Change the build flavor If you need more control over the dependency management, you can either use your custom build flavor or interact with Composer itself through [its environment variables](https://getcomposer.org/doc/03-cli.md#environment-variables). You can remove the default build flavor and run your own commands for complete control over your build. Set the build flavor to `none` and add the commands you need to your `build` hook, as in the following example: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' build: flavor: none hooks: build: | set -e composer install --no-interaction --no-dev ``` That installs production dependencies with Composer but not development dependencies. The same can be achieved by using the default build flavor and [adding the `COMPOSER_NO_DEV` variable](https://docs.upsun.com../../development/variables/set-variables.md). See more on [build flavors](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#build). ### Alternative repositories In addition to the standard `dependencies` format, you can specify alternative repositories for Composer to use as global dependencies. So you can install a forked version of a global dependency from a custom repository. To install from an alternative repository: 1. Set an explicit `require` block: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' dependencies: php: require: "platformsh/client": "2.x-dev" ``` This is equivalent to `composer require platform/client 2.x-dev`. 2. Add the repository to use: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' dependencies: php: require: "platformsh/client": "2.x-dev" repositories: - type: vcs url: "git@github.com:platformsh/platformsh-client-php.git" ``` That installs `platformsh/client` from the specified repository URL as a global dependency. For example, to install Composer 2 and the `platform/client 2.x-dev` library from a custom repository, use the following: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' [...] dependencies: php: require: composer/composer: '^2' "platformsh/client": "2.x-dev" repositories: - type: vcs url: "git@github.com:platformsh/platformsh-client-php.git" ``` ### Configure security blocking {#configure-security-blocking} When building a PHP app, Upsun runs `composer install`, which runs the latest available Composer version. By default, PHP builds fail if a dependency in a project has a known vulnerability. A PHP build might also fail if a dependency is abandoned. **The best practice is to upgrade the dependencies** to reduce security risks and to catch issues sooner. However, you can configure the level of security blocking by defining the following keys in the `.dependencies.php.config` section of your `.upsun/config.yaml` file. | Key | Description | | ------------------------| ---------------------------------------------------------------- | | `audit.block-insecure` | Default is `true`. **Important: Upsun recommends keeping this default setting and upgrading affected dependencies to reduce security risks.** | | `audit.block-abandoned` | Default is `false`; set to `true` for even stricter security. Ignored if `audit.block-insecure` is `false`. | | `audit.ignore` | Array of specific advisories to ignore; see example below. | | `audit.ignore-severity` | Ignore vulnerabilities based on their severity rating (`low`/`medium`/`high`). See the example below.
For each rating, include an `apply` key with one of these values: - `all` to ignore everything for this rating - `block` to ignore this severity level for blocking builds (but still flag findings in audit reports) - `audit` to ignore this severity level in audit reports (but still block builds) | Examples: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' dependencies: php: config: audit: ignore: # ignore these security advisories - "PKSA-yhcn-xrg3-68b1" - "PKSA-2wrf-1mxk-1pky" ``` ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' dependencies: php: config: audit: ignore-severity: low: apply: all # ignore all low severity findings ``` Related information: - [Troubleshooting PHP builds that now fail](https://docs.upsun.com/languages/php/troubleshoot.md#build-failure-security-blocking) ### Additional Composer schema properties In addition to [alternate repositories](#alternative-repositories), other [Composer schema properties](https://getcomposer.org/doc/04-schema.md) can be added to the global dependencies. For example, one of your dependencies may be a plugin where you need to explicitly whitelist it as an [allowed-plugin](https://getcomposer.org/doc/06-config.md#allow-plugins). To add additional composer schema properties: 1. Set an explicit `require` block: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' dependencies: php: require: "third-party/required-plugin"": "^3.0" ``` 2. Add each additional property as a block at the same indentation as the `require` block: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' dependencies: php: require: symfony/runtime: '*' config: "allow-plugins": symfony/runtime: true ``` ## Connect to services You can access service credentials to connect to [managed services](https://docs.upsun.com/add-services/) from environment variables present in the application container. Consult each of the individual service documentation to see how to retrieve and surface credentials into your application. - [Chroma](https://docs.upsun.com/add-services/chroma.md#3-use-the-relationship-in-your-application) - [ClickHouse](https://docs.upsun.com/add-services/clickhouse.md#usage-example) - [Elasticsearch](https://docs.upsun.com/add-services/elasticsearch.md#use-in-app) - [Edgee (Edge Analytics)](https://docs.upsun.com/add-services/edgee.md#setup-edgee) - [Gotenberg](https://docs.upsun.com/add-services/gotenberg.md#usage-example) - [Headless Chrome](https://docs.upsun.com/add-services/headless-chrome.md#use-in-app) - [InfluxDB](https://docs.upsun.com/add-services/influxdb.md#use-in-app) - [Kafka](https://docs.upsun.com/add-services/kafka.md#use-in-app) - [MariaDB/MySQL](https://docs.upsun.com/add-services/mysql.md#use-in-app) - [Memcached](https://docs.upsun.com/add-services/memcached.md#use-in-app) - [Mercure](https://docs.upsun.com/add-services/mercure.md#use-in-app) - [MongoDB](https://docs.upsun.com/add-services/mongodb.md#use-in-app) - [Network Storage](https://docs.upsun.com/add-services/network-storage.md#usage-example) - [OpenSearch](https://docs.upsun.com/add-services/opensearch.md#use-in-app) - [PostgreSQL](https://docs.upsun.com/add-services/postgresql.md#use-in-app) - [Qdrant](https://docs.upsun.com/add-services/qdrant.md#4-use-the-relationship-in-your-application) - [RabbitMQ](https://docs.upsun.com/add-services/rabbitmq.md#use-in-app) - [Redis](https://docs.upsun.com/add-services/redis.md#use-in-app) - [Solr](https://docs.upsun.com/add-services/solr.md#use-in-app) - [Valkey](https://docs.upsun.com/add-services/valkey.md#use-in-app) - [Varnish](https://docs.upsun.com/add-services/varnish.md#usage-example) - [Vault KMS](https://docs.upsun.com/add-services/vault.md#use-vault-kms) ## PHP settings You can configure your PHP-FPM runtime configuration by specifying the [runtime in your app configuration](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#runtime). In addition to changes in runtime, you can also change the PHP settings. Some commonly used settings are: | Name | Default | Description | |------|---------|-------------| | `max_execution_time` | `300` | The maximum execution time, in seconds, for your PHP scripts and apps. A value of `0` means there are no time limits. | | `max_file_uploads` | `20` | The maximum number of files that can be uploaded in each request. | | `max_input_time` | `60` | The maximum time in seconds that your script is allowed to receive input (such as for file uploads). A value of `-1` means there are no time limits. | | `max_input_vars` | `1000` | The maximum number of input variables that are accepted in each request. | | `memory_limit` | `128M` | The memory limit, in megabytes, for PHP. Ensure that the PHP memory limit is set to a lower value than your environment's memory. | | `post_max_size` | `64M` | The maximum size, in megabytes, per uploaded file. To upload larger files, increase the value. | | `zend.assertions` | `-1` | Assertions are optimized and have no impact at runtime. Set assertions to `1` for your local development system. [See more on assertions](https://www.php.net/manual/en/regexp.reference.assertions). | | `opcache.memory_consumption` | `64` | The number of megabytes available for [the OPcache](https://docs.upsun.com/languages/php/tuning.md#opcache-preloading). For large apps with many files, increase this value. | | `opcache.validate_timestamps` | `On` | If your app doesn't generate compiled PHP, you can [disable this setting](https://docs.upsun.com/languages/php/tuning.md#disable-opcache-timestamp-validation). | ### Retrieve the default values To retrieve the default PHP values, run the following [CLI command](https://docs.upsun.com../../administration/cli/_index.md): ```bash upsun ssh "php --info" ``` To get specific default values, use grep. For example, to get the value for `opcache.memory_consumption`, run the following command: ```bash upsun ssh "php --info" | grep opcache.memory_consumption ``` ### Retrieve the settings To see the settings used on your environment: 1. Find the PHP configuration files with the following [CLI command](https://docs.upsun.com../../administration/cli/_index.md): ```bash upsun ssh "php --ini" ``` The output is something like the following: ```bash Configuration File (php.ini) Path: /etc/php/8.0-zts/cli Loaded Configuration File: /etc/php/8.0-zts/cli/php.ini Scan for additional .ini files in: /etc/php/8.0-zts/cli/conf.d Additional .ini files parsed: (none) ``` 2. Display the configuration file by adapting the following command with the output from step 1: ```bash upsun ssh "cat " ``` ### Customize PHP settings You can customize PHP values for your app in two ways. The recommended method is to use variables. For more information, see how to use [PHP-specific variables](https://docs.upsun.com/development/variables.md#php-specific-variables). You can provide a custom ``php.ini`` file at the [app root](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory). Using this method isn’t recommended since it offers less flexibility and is more error-prone. Consider using variables instead. For example, to change the PHP memory limit, use the following configuration: php.ini ```ini {} memory_limit = 256M ``` If you're using [PHP-CLI](#execution-mode), you need to take into account the default settings of PHP-CLI when you customize your PHP settings. The default settings of PHP-CLI can't be overwritten and are the following: ```text max_execution_time=0 max_input_time=-1 memory_limit=-1 ``` ### Disable functions for security A common recommendation for securing PHP installations is disabling built-in functions frequently used in remote attacks. By default, Upsun doesn't disable any functions. If you're sure a function isn't needed in your app, you can disable it. For example, to disable `pcntl_exec` and `pcntl_fork`, add the following to your [app configuration](https://docs.upsun.com../../create-apps/_index.md): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' variables: php: disable_functions: "pcntl_exec,pcntl_fork" ``` Common functions to disable include: | Name | Description | |------|-------------| | `create_function` | This function has been replaced by anonymous functions and shouldn't be used anymore. | | `exec`, `passthru`, `shell_exec`, `system`, `proc_open`, `popen` | These functions allow a PHP script to run a bash shell command. Rarely used by web apps except for build scripts that might need them. | | `pcntl_*` | The `pcntl_*` functions are responsible for process management. Most of them cause a fatal error if used within a web request. Cron tasks or workers may need them. Most are usually safe to disable. | | `curl_exec`, `curl_multi_exec` | These functions allow a PHP script to make arbitrary HTTP requests. If you're using HTTP libraries such as Guzzle, don't disable them. | | `show_source` | This function shows a syntax highlighted version of a named PHP source file. Rarely useful outside of development. | ## Execution mode 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](https://docs.upsun.com/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](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory). - The Common Gateway Interface mode (PHP-CGI) is the mode used for web apps and web requests. This is the default mode when the `start` command isn't explicitly set. To use PHP-CGI, run your script with a symlink: `/usr/bin/start-php-app `, where is a file path relative to the [app root](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory). With PHP-CGI, PHP is run using the FastCGI Process Manager (PHP-FPM). ## Alternate start commands To specify an alternative process to run your code, set a `start` command. For more information about the start command, see the [web commands reference](create-apps/image-properties/web.md#web-commands). By default, start commands use PHP-CLI. Find out how and when to use each [execution mode](#execution-mode). Note that the `start` command must run in the foreground and is executed before the [deploy hook](https://docs.upsun.com../../create-apps/hooks/hooks-comparison.md). That means that PHP-FPM can't run simultaneously with another persistent process such as [ReactPHP](https://github.com/platformsh-examples/platformsh-example-reactphp) or [Amp](https://github.com/platformsh-examples/platformsh-example-amphp). If you need multiple processes, they have to run in separate containers. See some generic examples on how to use alternate start commands: ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" web: commands: start: /usr/bin/start-php-app ``` - Add your web server’s code in a PHP file. - Specify an alternative ``start`` command by adapting the following: .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" web: commands: start: /usr/bin/start-php-app ``` - Configure the container to listen on a TCP socket: .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" web: upstream: socket_family: tcp protocol: http ``` When you listen on a TCP socket, the ``$PORT`` environment variable is automatically set. See more options on how to [configure where requests are sent](https://docs.upsun.com/create-apps/image-properties/web.md#upstream). You might have to configure your app to connect via the ``$PORT`` TCP socket, especially when using web servers such as [Swoole](https://docs.upsun.com/languages/php/swoole.md) or [Roadrunner](https://github.com/roadrunner-server/roadrunner). - Optional: Override redirects to let the custom web server handle them: .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" locations: "/": passthru: true scripts: false allow: false ``` To execute runtime-specific tasks (such as clearing cache) before your app starts, follow these steps: - Create a separate shell script that includes all the commands to be run. - Specify an alternative ``start`` command by adapting the following: .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" web: commands: start: bash && /usr/bin/start-php-app ``` is the bash script created in step 1. is a file path relative to the [app root](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory). ## Foreign function interfaces PHP 7.4 introduced support for [foreign function interfaces (FFIs)](https://en.wikipedia.org/wiki/Foreign_function_interface). FFIs allow your PHP program to call routines or use services written in C or Rust. Note: FFIs are only intended for advanced use cases. Use with caution. If you are using C code, you need `.so` library files. Either place these files directly in your repository or compile them in a makefile using `gcc` in your [build hook](https://docs.upsun.com../../create-apps/hooks/hooks-comparison.md#build-hook). Note: The `.so` library files shouldn't be located in a publicly accessible directory. If you are compiling Rust code, use the build hook to [install Rust](https://doc.rust-lang.org/stable/book/ch01-01-installation.md). To leverage FFIs, follow these steps: 1. [Enable and configure OPcache preloading](https://docs.upsun.com/languages/php/tuning.md#enable-opcache-preloading). 2. Enable the FFI extension: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'php:8.5' runtime: extensions: - ffi ``` 3. Make sure that your [preload script](https://docs.upsun.com/languages/php/tuning.md#opcache-preloading) calls the `FFI::load()` function. Using this function in preload is considerably faster than loading the linked library on each request or script run. 4. If you are running FFIs from the command line, enable the preloader by adding the following configuration: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'php:8.5' variables: php: opcache.enable_cli: true ``` 5. Run your script with the following command: ```bash php ``` ## Frameworks All major PHP web frameworks can be deployed on Upsun. See dedicated guides for deploying and working with them: - [Laravel](https://docs.upsun.com/get-started/stacks/laravel.md) - [Symfony](https://docs.upsun.com/get-started/stacks/symfony.md) ## Modify your PHP runtime when using the composable image **Note**: This section is only relevant when using the Upsun [composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md). The following table presents the possible modifications you can make to your PHP primary runtime using the `stack.runtimes` key in a composable image. For example, `extensions` are enabled under `.applications.frontend.stack.runtimes[0]["php@8.5"].extensions` for PHP 8.5). See the [example](#example-php-configuration) below for more details. **Note**: The PHP-FPM service starts automatically only when PHP is the primary runtime. | Name | Type | Description | |-----------------------------|-------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------| | `extensions` | List of `string`s OR [extensions definitions](https://docs.upsun.com/create-apps/app-reference/composable-image#php-extensions-and-python-packages) | [PHP extensions](https://docs.upsun.com/languages/php/extensions.md) to enable. | | `disabled_extensions` | List of `string`s | [PHP extensions](https://docs.upsun.com/languages/php/extensions.md) to disable. | | `request_terminate_timeout` | `integer` | The timeout (in seconds) for serving a single request after which the PHP-FPM worker process is killed. | | `sizing_hints` | A [sizing hints definition](#sizing-hints) | The assumptions for setting the number of workers in your PHP-FPM runtime. | | `xdebug` | An Xdebug definition | The setting to turn on [Xdebug](https://docs.upsun.com/languages/php/xdebug.md). | ### PHP-FPM service sizing hints {#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](https://docs.upsun.com/languages/php/fpm.md). ### Example PHP configuration {#example-php-configuration} Here is an example configuration: ```yaml {location=".upsun/config.yaml"} applications: frontend: type: "composable:25.11" stack: runtimes: - "php@8.4": extensions: - apcu # A PHP extension made available to the PHP runtime - sodium - xsl - pdo_sqlite xdebug: idekey: YOUR_KEY disabled_extensions: - gd request_terminate_timeout: 200 sizing_hints: request_memory: 45 reserved_memory: 70 - "python@3.13" packages: - "php84Extensions.apcu" # A PHP extension made available to all runtimes. - "python313Packages.yq" ``` **Note**: You can also set your [app’s runtime timezone](https://docs.upsun.com/create-apps/timezone.md). --- # Source: https://docs.upsun.com/learn/overview/yaml/platform-yaml-tags.md # Upsun Fixed YAML tags In addition to the [basic functions you should be familiar with](https://docs.upsun.com/learn/overview/yaml/what-is-yaml.md), YAML allows for special tags. Upsun accepts certain custom tags to facilitate working with configuration files. These tags work with Upsun configuration files, but may not elsewhere. ## Include Use the `!include` tag to embed external files within a given YAML file. The tag requires two properties: | Property | Type | Possible values | Description | | -------- | -------- | ----------------------------- | ----------- | | `type` | `string` | `string`, `binary`, or `yaml` | See the descriptions of [strings](#string), [binaries](#binary), and [YAML](#yaml). Defaults to `yaml`. | | `path` | `string` | | The path to the file to include, relative to the application directory or `source.root`. | **Note**: By default, ``path`` is relative to the current application’s directory (what you would define with ``source.root``). It is possible to include files from a directory parent to the folder however. For example, for the following project structure: ```bash {} . ├── .upsun |   └── .upsun/config.yaml ├── backend │   ├── main.py │   ├── requirements.txt │   └── scripts │   ├── ... │   └── common_build.sh └── frontend    ├── README.md    ├── package-lock.json    ├── package.json    ├── public    ├── scripts    │   └── clean.sh    └── src ``` This configuration is valid: .upsun/config.yaml ```yaml {} applications: frontend: source: root: frontend # ... hooks: build: !include type: string path: ../backend/scripts/common_build.sh ``` ### `string` Use `string` to include an external file inline in the YAML file as if entered as a multi-line string. For example, if you have a build hook like the following: ```yaml {location=".upsun/config.yaml"} applications: myapp: hooks: build: | set -e cp a.txt b.txt ``` You could create a file for the script: ```text {location="build.sh"} set -e cp a.txt b.txt ``` And replace the hook with an include tag for an identical result: ```yaml {location=".upsun/config.yaml"} applications: myapp: hooks: build: !include type: string path: build.sh ``` This helps you break longer configuration like build scripts out into a separate file for easier maintenance. Even if ``path`` is relative to the current application's directory, it is also possible to include a shell script from a directory parent to the folder however. For example, for the following project structure: ```bash . ├── .upsun |   └── config.yaml ├── backend │   ├── main.py │   ├── requirements.txt │   └── scripts │   ├── ... │   └── common_build.sh └── frontend    ├── README.md    ├── package-lock.json    ├── package.json    ├── public    ├── scripts    │   └── clean.sh    └── src ``` This configuration is valid: ```yaml {location=".upsun/config.yaml"} applications: frontend: source: root: frontend # ... hooks: build: !include type: string path: ../backend/scripts/common_build.sh ``` **Note**: Please note that Upsun will execute this ``../backend/scripts/common_build.sh`` script using [Dash](https://wiki.archlinux.org/title/Dash). ### `binary` Use `binary` to include an external binary file inline in the YAML file. The file is base64 encoded. For example, you could include a `favicon.ico` file in the same folder as your app configuration. Then you can include it as follows: ```yaml {location=".upsun/config.yaml"} some-property: favicon: !include type: binary path: favicon.ico ``` ### `yaml` Use `yaml` to include an external YAML file inline as if entered directly. Because `yaml` is the default, you can use it without specifying the type. For example, you could have your configuration for works defined in a `worker.yaml` file: ```yaml {location="worker.yaml"} commands: start: python queue-worker.py variables: env: type: worker ``` Then the following three configurations are exactly equivalent: ```yaml {location=".upsun/config.yaml"} workers: queue1: !include "worker.yaml" ``` ```yaml {location=".upsun/config.yaml"} workers: queue1: !include type: yaml path: 'worker.yaml' ``` ```yaml {location=".upsun/config.yaml"} workers: queue1: commands: start: python queue-worker.py variables: env: type: worker ``` This can help simplify more complex files. For [multiple application](https://docs.upsun.com/create-apps/multi-app.md) project, you can also include another ``.upsun/apps/my-app.yaml`` file in the main `.upsun/config.yaml`. ```yaml {location=".upsun/apps/my-app.yaml"} source: root: "/" type: "nodejs:18" web: commands: start: "node index.js" upstream: socket_family: tcp locations: "/": passthru: true ``` and including it: ```yaml {location=".upsun/config.yaml"} applications: myapp: !include ./apps/my-app.yaml ``` ## Archive Use the `!archive` tag for a reference to an entire directory specified relative to where the YAML file is. For example, you might want to define a configuration directory for your [Solr service](https://docs.upsun.com/add-services/solr.md). You might do so as follows: ```yaml {location=".upsun/config.yaml"} mysearch: type: solr:8.0 configuration: conf_dir: !archive "solr/conf" ``` The `!archive` tag means that the value for `conf_dir` isn't the string `solr/conf` but the entire `solr/conf` directory. This directory is in the `.upsun` directory, since that's where the `.upsun/config.yaml` file is. The `solr/conf` directory is then copied into the Upsun management system to use with the service. --- # Source: https://docs.upsun.com/add-services/postgresql/postgresql-readonly-replication.md # PostgreSQL read-only replication You can improve the performance of read-heavy applications by defining read-only replicas of your PostgreSQL database and then connecting your applications to those replicas. Examples of read-heavy applications include: - Listing pages or dashboards - Reporting or analytics jobs - Background jobs that frequently query data **Note**: - **Replication is asynchronous**: Delays of a few milliseconds might occur between writes on the primary database and reads on the replica database. - **Replicas are read-only**: This restriction ensures data consistency and integrity. Attempts to modify data will result in an SQL error. ### Replica scope and sharing services {#replica-scope-sharing-services} PostgreSQL services (which provide access to databases and replicas) defined in a project cannot be accessed by or shared with applications in other projects. ## 1. Configure the primary and replica services The following code fragment defines two MariaDB services: a primary and a replica. You can use this fragment as a template by copying it into your `services.yaml` or `application.yaml` file. Be sure to: - Replace `` with the [supported PostgreSQL version](https://docs.upsun.com/add-services/postgresql.md#supported-versions) that you need. Use the same version number for the primary and replica services. - **Important:** Use `replicator` as the endpoint name when you define the replica service. This is a special endpoint name that the replica service uses to connect to the database. ```yaml {location=".upsun/config.yaml"} services: db: type: postgresql: configuration: extensions: - postgis endpoints: replicator: replication: true db-replica1: type: postgres-replica: configuration: endpoints: postgresql: default_database: main extensions: - postgis relationships: primary: db:replicator # Do not change the name `primary`. The service expects to receive this name. db-replica2: type: postgres-replica: configuration: endpoints: postgresql: default_database: main extensions: - postgis relationships: primary: db:replicator # Do not change the name `primary`. The service expects to receive this name. ``` ### How it works Using the sample code fragment above: 1. After you define the replicator endpoints, the primary service creates a `replicator` user that has permission to replicate the database. You must specify `replicator` as the endpoint name, as described at the start of this topic. ```yaml endpoints: replicator: replication: true ``` 2. In the replica services (in this example, db-replica1 and db-replica2), defining the relationship `primary: db:replicator` ensures that the service can connect to the primary database as the `replicator` user. ```yaml relationships: primary: db:replicator ``` The `db-replica1` and `db-replica2` replica services continuously stream data from the primary endpoint, maintaining a read-only copy of the primary database content. Write operations are not permitted on the replicas. ## 2. Define the relationship between the application and the replicas Even if your application won't access the replication endpoint, you must expose the endpoint to an application as a relationship so that you can connect to it over SSH. Add a new relationship to your application container, as shown below: ```yaml {location=".upsun/config.yaml"} name: myapp [...] # Relationships enable an app container's access to a service. relationships: # More information: https://fixed.docs.upsun.com/anchors/fixed/app/reference/relationships/ database: service: db endpoint: main database-readonly: service: db-replica ``` If your application's performance is still not what you expect, you can configure additional replicas as described above. --- # Source: https://docs.upsun.com/development/sanitize-db/postgresql-symfony.md # Sanitizing databases: PostgreSQL and Symfony Databases of live websites often contain personally identifiable information (PII) such as full names, mailing addresses, and phone numbers. To ensure people reviewing code changes can't access information they shouldn't, sanitize your databases of any PII that they may contain. This example goes through the process for a PostgreSQL database using Symfony. ## Before you begin You need: - A project with a [PostgreSQL database](https://docs.upsun.com../../add-services/postgresql.md). - A command interface installed: - If doing it manually, the [Symfony CLI](https://symfony.com/download). - Otherwise, make sure ``pqsl`` is installed in your environment. This guide is about sanitizing PostgreSQL databases. This guide doesn't address: - Sanitizing NoSQL Databases (such as [MongoDB](https://docs.upsun.com../../add-services/mongodb.md)) - Input validation and input sanitization, which both help prevent security vulnerabilities ## Sanitize the database Make sure that you only sanitize preview environments and **never** the production environment. Otherwise you may lose most or even all of the relevant data stored in your database. First, take a [database dump](https://docs.upsun.com../../add-services/postgresql.md#exporting-data) of your preview environment. This is just a safety precaution. Production data isn't altered. To get a database dump, run the following command: ``symfony db:dump -e ``. You see output like the following: ```sql {} id | user_email | display_name -----+-----------------------------------------+----------------------- 3501 | daniel02@yourcompany.com | Jason Brown 3502 | ismith@kim.com | Sandra Griffin 3503 | olee@coleman-rodriguez.com | Miss Christine Morgan ``` - Change the fields where PII is contained with the [UPDATE](https://mariadb.com/kb/en/update/). For example, to change the display name of users with an email address not in your company’s domain to a random value, run the following query: ```sql {} UPDATE users SET display_name==substring(md5(display_name||'$PLATFORM_PROJECT_ENTROPY') for 8); WHERE email NOT LIKE '%@yourcompany%' ``` Adapt and run that query for all fields that you need to sanitize. If you modify fields that you shouldn’t alter, [you can restore them](https://docs.upsun.com/environments/restore.md) from the dump you took in step 1. You can create a script to automate the sanitization process to be run automatically on each new deployment. Once you have a working script, add your script to sanitize the database to [a ](https://docs.upsun.com/create-apps/hooks/hooks-comparison.md#deploy-hook): .upsun/config.yaml ```yaml {} applications: myapp: # ... hooks: deploy: | # ... cd /app/public if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then # Do whatever you want on the production site. else # The sanitization of the database should happen here (since it's non-production) sanitize_the_database.sh fi ``` Assumptions: - An Entity User exist and contains all of your PII (Personally Identifiable Information) - [fakerphp/faker](https://fakerphp.github.io/) has been installed as a dependency on your Symfony application Set up a script by following these steps: - Create a Symfony command to sanitize data src/Command/SanitizeDataCommand.php ```php {} setDescription('This command allows you to sanitize user data (username and email).'); } protected function execute(InputInterface $input, OutputInterface $output) { $io = new SymfonyStyle($input, $output); $users = $this->userRepository->findAll(); $io->progressStart(count($users)); /** @var User $user */ foreach ($users as $user) { $io->progressAdvance(); // initialize faker $faker = Faker\Factory::create(); // sanitize user info $user->setUsername(uniqid($faker->userName())); $user->setEmail($faker->email()); // adapt to your needs $this->entityManager->flush(); } $io->progressFinish(); return static::SUCCESS; } } ``` - Update the deploy hook to run your Symfony Command on each deploy. .upsun/config.yaml ```yaml {} applications: myapp: hooks: build: ... deploy: | if [ "$PLATFORM_ENVIRONMENT_TYPE" != production ]; then # The sanitization of the database should happen here (since it's non-production) php bin/console app:sanitize-data fi ``` To sanitize only on the initial deploy and not all future deploys, on sanitization create a file on a mount. Then add a check for the file as in the following example: .upsun/config.yaml ```yaml {} applications: myapp: hooks: build: ... deploy: | if [ "$PLATFORM_ENVIRONMENT_TYPE" != production ] && [ ! -f MOUNT_PATH/is_sanitized ]; then # The sanitization of the database should happen here (since it's non-production) php bin/console app:sanitize-data touch MOUNT_PATH/is_sanitized fi ``` - Commit your changes by running the following command: ```bash {} git add src/Command/SanitizeDataCommand.php .upsun/config.yaml && git commit -m "Add sanitization." ``` Push the changes to ``staging`` and verify that environment’s database was sanitized. Once merged to production, all data from future preview environments are sanitized on environment creation. This example show you how to sanitize data on multiple projects inside an organization, except for production environments. Assumptions: - Symfony Command from previous tab ``Using a Symfony Command`` has already been pushed to all of your environments. Set up a script by following these steps: - Create an executable sanitizing script by running the following command: ```bash {} touch sanitize_fleet.sh && chmod +x sanitize_fleet.sh ``` - Make the script sanitize environments with an [environment type](https://docs.upsun.com/administration/users.md#environment-type-roles) other than ``production``. The following example runs only in preview environments and sanitizes data using the Symfony Command from previous tab, already pushed to all of your environments. sanitize_fleet.sh ```bash {} if [ -n "$ZSH_VERSION" ]; then emulate -L ksh; fi ###################################################### # fleet sanitization demo script, using the Symfony CLI. # # Enables the following workflow on a project: # . # └── main # ├── staging # | └── new-feature # └── auto-updates # # Usage # 1. source this script: `. sanitize_fleet.sh` or `source sanitize_fleet.sh` depending of your local machine # 2. define ORGANIZATION var: ORGANIZATION= # 3. run `sanitize_organization_data $ORGANIZATION` ###################################################### # Utility functions. # list_org_projects: Print list of projects operation will be applied to before starting. # $1: Organization, as it appears in console.upsun.com. list_org_projects () { symfony project:list -o $1 --columns="ID, Title" } # get_org_projects: Retrieve an array of project IDs for a given organization. # Note: Makes array variable PROJECTS available to subsequent scripts. # $1: Organization, as it appears in console.upsun.com. get_org_projects () { PROJECTS_LIST=$(symfony project:list -o $1 --pipe) PROJECTS=($PROJECTS_LIST) } # get_project_envs: Retrieve an array of envs IDs for a project. # Note: Makes array variable ENVS available to subsequent scripts. # $1: ProjectId, as it appears in console.upsun.com. get_project_envs () { ENV_LIST=$(symfony environment:list -p $1 --pipe) ENVS=($ENV_LIST) } # list_project_envs: Print list of envs operation will be applied to before starting. # $1: ProjectId, as it appears in console.upsun.com. list_project_envs () { symfony environment:list -p $1 } # add_env_var: Add environment level environment variable. # $1: Variable name. # $2: Variable value. # $3: Target project ID. # $4: Target environment ID. add_env_var () { VAR_STATUS=$(symfony project:curl -p $3 /environments/$4/variables/env:$1 | jq '.status') if [ "$VAR_STATUS" != "null" ]; then symfony variable:create \ --name $1 \ --value "$2" \ --prefix env: \ --project $3 \ --environment $4 \ --level environment \ --json false \ --sensitive false \ --visible-build true \ --visible-runtime true \ --enabled true \ --inheritable true \ -q else printf "\nVariable $1 already exists. Skipping." fi } # Main functions. sanitize_organization_data () { list_org_projects $1 get_org_projects $1 for PROJECT in "${PROJECTS[@]}" do printf "\n### Project $PROJECT." # get environments list list_project_envs $PROJECT get_project_envs $PROJECT for ENVIRONMENT in "${ENVS[@]}" do unset -f ENV_CHECK ENV_CHECK=$(symfony project:curl -p $PROJECT /environments/$ENVIRONMENT | jq -r '.status') unset -f ENV_TYPE ENV_TYPE=$(symfony project:curl -p $PROJECT /environments/$ENVIRONMENT | jq -r '.type') if [ "$ENV_CHECK" = active -a "$ENV_TYPE" != production ]; then unset -f DATA_SANITIZED DATA_SANITIZED=$(symfony variable:get -p $PROJECT -e $ENVIRONMENT env:DATA_SANITIZED --property=value) if [ "$DATA_SANITIZED" != true ]; then printf "\nEnvironment $ENVIRONMENT exists and isn't sanitized yet. Sanitizing data." printf "\n" # do sanitization here symfony ssh -p $PROJECT -e $ENVIRONMENT -- php bin/console app:sanitize-data printf "\nSanitizing data is finished, redeploying" add_env_var DATA_SANITIZED true $PROJECT $ENVIRONMENT else printf "\nEnvironment $ENVIRONMENT exists and doesn't need to be sanitized. skipping." fi elif [ "$ENV_TYPE" == production ]; then printf "\nEnvironment $ENVIRONMENT is production one, skipping." else printf "\nEnvironment $ENVIRONMENT isn't active $ENV_CHECK, skipping." fi done done } ``` - use this shell script Depending on the machine you want to run this script on, adapt this to your needs. ```bash {} . sanitize_fleet.sh # or source sanitize_fleet.sh ORGANIZATION= sanitize_organization_data $ORGANIZATION ``` **Note**: You can find the organization identifier for a specific project, within the Upsun console, by clicking on your name, and then on “Settings”, in the top right corner. - [Option] Commit your changes by running the following command: ```bash {} git add sanitize_fleet.sh && git commit -m "Add sanitization." ``` Push the changes to ``staging`` and verify that environment’s database was sanitized. Once merged to production, all data from future preview environments are sanitized on environment creation. ## What's next You learned how to remove sensitive data from a database. To replace sensitive data that with other meaningful data, you can add a `faker` to the process. A `faker` is a program that generates fake data that looks real. Having meaningful PII-free data allows you to keep your current Q&A, external reviews, and other processes. To add a faker, adapt your sanitizing queries to replace each value that contains PII with a new value generated by the faker. You might also want to make sure that you [implement input validation](https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.md#goals-of-input-validation). If your database contains a lot of data, consider using the [`REINDEX` statement](https://www.postgresql.org/docs/current/sql-reindex.md) to help improve performance. --- # Source: https://docs.upsun.com/development/sanitize-db/postgresql.md # Source: https://docs.upsun.com/add-services/postgresql.md # PostgreSQL (Database service) PostgreSQL is a high-performance, standards-compliant relational SQL database. See the [PostgreSQL documentation](https://www.postgresql.org/docs/9.6/index.md) for more information. **Note**: The [example](#usage-example) provided later in this topic is specific to using only a **primary** database. For details about using read-only replicas to improve performance of read-heavy applications, see the [PostgreSQL read-only replication](https://docs.upsun.com/add-services/postgresql/postgresql-readonly-replication.md) topic. ## Supported versions You can select the major version. But the latest compatible minor version is applied automatically and can’t be overridden. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 18 - 17 - 16 - 15 - 14 **Note**: You can’t upgrade to PostgreSQL 12 with the ``postgis`` extension enabled. For more details, see how to [upgrade to PostgreSQL 12 with ](#upgrade-to-postgresql-12-with-the-postgis-extension). ### Deprecated versions The following versions are [deprecated](https://docs.upsun.com/glossary.md#deprecated-versions). They're available, but they don't receive security updates from upstream and aren't guaranteed to work. They'll be removed in the future – consider migrating to a [supported version](#supported-versions). - 13 - 12 - 11 - 10 - 9.6 - 9.5 - 9.3 ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "username": "main", "scheme": "pgsql", "service": "postgresql", "fragment": null, "ip": "123.456.78.90", "hostname": "azertyuiopqsdfghjklm.postgresql.service._.eu-1.platformsh.site", "port": 5432, "cluster": "azertyuiopqsdf-main-afdwftq", "host": "postgresql.internal", "rel": "postgresql", "path": "main", "query": { "is_master": true }, "password": "ChangeMe", "type": "postgresql:18", "public": false, "host_mapped": false } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_POSTGRESQL_HOST="$(echo "$RELATIONSHIPS_JSON" | jq -r '.postgresql[0].host')" ``` ## Usage example **Note**: Use the steps and sample code below if your application will connect to a **primary** PostgreSQL database. For details about using read-only replicas to improve performance of read-heavy applications, see the [PostgreSQL read-only replication](https://docs.upsun.com/add-services/postgresql/postgresql-readonly-replication.md) topic. ### 1. Configure the service To define the service, use the ``postgresql`` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: postgresql: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. ### 2. Define the relationship To define the relationship, use the following configuration: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container (````) now has access to the service via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: postgresql ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). For PHP, enable the [extension](https://docs.upsun.com/languages/php/extensions.md) for the service: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # PHP extensions. runtime: extensions: - pdo_pgsql # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # PHP extensions. runtime: extensions: - pdo_pgsql # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: postgresql ``` ### Example configuration ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # PHP extensions. runtime: extensions: - pdo_pgsql # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: postgresql: services: # The name of the service container. Must be unique within a project. postgresql: type: postgresql:18 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # PHP extensions. runtime: extensions: - pdo_pgsql # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: postgresql: service: postgresql endpoint: postgresql services: # The name of the service container. Must be unique within a project. postgresql: type: postgresql:18 ``` ### Use in app To use the configured service in your app, add a configuration file similar to the following to your project. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" # PHP extensions. runtime: extensions: - pdo_pgsql [...] # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: postgresql: services: # The name of the service container. Must be unique within a project. postgresql: type: postgresql:18 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" # PHP extensions. runtime: extensions: - pdo_pgsql [...] # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: postgresql: service: postgresql endpoint: postgresql services: # The name of the service container. Must be unique within a project. postgresql: type: postgresql:18 ``` This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory. `myapp` has access to the `postgresql` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship) (as per [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships). From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference). ```bash {location="myapp/.environment"} # Set environment variables for individual credentials. # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. export DB_CONNECTION="${POSTGRESQL_SCHEME}" export DB_USERNAME="${POSTGRESQL_USERNAME}" export DB_PASSWORD="${POSTGRESQL_PASSWORD}" export DB_HOST="${POSTGRESQL_HOST}" export DB_PORT="${POSTGRESQL_PORT}" export DB_DATABASE="${POSTGRESQL_PATH}" # Surface connection string variable for use in app. export DATABASE_URL="${DB_CONNECTION}://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE}" ``` The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``DATABASE_URL`` can be used within the application to connect to the service. Note that ``DATABASE_URL``, and all Upsun [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) like ``POSTGRESQL_HOST``, are environment-dependent. Unlike the build produced for a given commit, they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment. A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](https://docs.upsun.com/get-started.md). ## Access the service directly Access the service using the Upsun CLI by running `upsun sql`. You can also access it from your app container via [SSH](https://docs.upsun.com/development/ssh.md). From your [relationship data](#relationship-reference), you need: `POSTGRESQL_USERNAME`, `POSTGRESQL_HOST`, and `POSTGRESQL_PORT`. Then run the following command: ```bash psql -U -h -p ``` Using the values from the [example](#relationship-reference), that would be: ```bash psql -U main -h postgresql.internal -p 5432 ``` You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``. Service connection details can change whenever your app restarts or redeploys. **To keep your connection stable, use [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) rather than hard-coding values.** ## Exporting data The easiest way to download all data in a PostgreSQL instance is with the Upsun CLI. If you have a single SQL database, the following command exports all data using the `pg_dump` command to a local file: ```bash upsun db:dump ``` If you have multiple SQL databases it prompts you which one to export. You can also specify one by relationship name explicitly: ```bash upsun db:dump --relationship postgresql ``` By default the file is uncompressed. If you want to compress it, use the `--gzip` (`-z`) option: ```bash upsun db:dump --gzip ``` You can use the `--stdout` option to pipe the result to another command. For example, if you want to create a bzip2-compressed file, you can run: ```bash upsun db:dump --stdout | bzip2 > dump.sql.bz2 ``` It is also possible to generate the dump locally if you have the `pg_dump` command installed with `upsun tunnel:single`. The command will first ask for the service and then will provide a prompt for the URI string that you can use. For example: ```bash pg_dump -d postgresql://REPLACE_URI_FROM_OUTPUT -f dump.sql ``` ## Importing data Make sure that the imported file contains objects with cleared ownership and `IF EXISTS` clauses. For example, you can create a DB dump with following parameters: ```bash pg_dump --no-owner --clean --if-exists ``` The easiest way to load data into a database is to pipe an SQL dump through the `upsun sql` command, like so: ```bash upsun sql < my_database_backup.sql ``` That runs the database backup against the SQL database on Upsun. That works for any SQL file, so the usual caveats about importing an SQL dump apply (for example, it's best to run against an empty database). As with exporting, you can also specify a specific environment to use and a specific database relationship to use, if there are multiple. ```bash upsun sql --relationship postgresql -e < my_database_backup.sql ``` **Note**: Importing a database backup is a destructive operation. It overwrites data already in your database. Taking a backup or a database export before doing so is strongly recommended. ## Sanitizing data To ensure people who review code changes can't access personally identifiable information stored in your database, [sanitize your preview environments](https://docs.upsun.com/development/sanitize-db/postgresql.md). ## Set locale for database You can choose your locale when a database is created by setting locale-related variables. There are three ways to set a locale option, as detailed in the table below: | Name | Type | Default | Description | |--------|-----------|----------|--------------| | `default_ctype` | `string` | `C.UTF-8` | The default character classification. Affects any tables created after it's set.| | `default_collation` | `string`|`C.UTF-8`| The default collation rules. Affects any tables created after it's set.| | `default_charset` | `string` | `UTF8` | The default encoding character set. Affects any tables created after it's set.| ## Multiple databases Support for defining multiple databases and multiple users with different permissions is available in versions `10` and later of this service. To do so requires defining multiple endpoints. Under the `configuration` key of your service there are two additional keys: * `databases`: This is a YAML array listing the databases that should be created. If not specified, a single database named `main` is created. Note that removing a schema from the list of `schemas` on further deployments results in **the deletion of the schema.** * `endpoints`: This is a nested YAML object defining different credentials. Each endpoint may have access to one or more schemas (databases), and may have different levels of permission for each. The valid permission levels are: * `ro`: Using this endpoint only `SELECT` queries are allowed. * `rw`: Using this endpoint `SELECT` queries as well as `INSERT`/`UPDATE`/`DELETE` queries are allowed. * `admin`: Using this endpoint all queries are allowed, including DDL queries (`CREATE TABLE`, `DROP TABLE`, etc.). Consider the following illustrative example: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. postgresql: type: "postgresql:18" configuration: databases: - main - legacy endpoints: admin: privileges: main: admin legacy: admin reporter: default_database: main privileges: main: ro importer: default_database: legacy privileges: legacy: rw ``` This example creates a single PostgreSQL service named `postgresql`. The server has two databases, `main` and `legacy` with three endpoints created. * `admin`: has full access to both databases. * `reporter`: has `SELECT` query access to the `main` database, but no access to `legacy`. * `importer`: has `SELECT`/`INSERT`/`UPDATE`/`DELETE` access (but not DDL access) to the `legacy` database. It doesn't have access to `main`. If a given endpoint has access to multiple databases you should also specify which is listed by default in the relationships array. If one isn't specified, the `path` property of the relationship is `null`. While that may be acceptable for an application that knows the name of the database it's connecting to, automated tools like the Upsun CLI can't access the database on that relationship. For that reason, defining the `default_database` property is always recommended. Once these endpoints are defined, you need to expose them to your application as a relationship. Continuing with the above example, your `relationships` in `.upsun/config.yaml` might look like: ```yaml {location=".upsun/config.yaml"} applications: # The name of the app container. Must be unique within a project. myapp: source: root: "/" [...] # Relationships enable access from this app to a given service. # The example below shows configuration with explicitly set service names and endpoints. # See the Application reference for all options for defining relationships and endpoints. relationships: database: service: postgresql endpoint: admin reports: service: postgresql endpoint: reporter imports: service: postgresql endpoint: importer services: # The name of the service container. Must be unique within a project. postgresql: type: "postgresql:18" configuration: databases: - main - legacy endpoints: admin: privileges: main: admin legacy: admin reporter: default_database: main privileges: main: ro importer: default_database: legacy privileges: legacy: rw ``` Each database is accessible to your application through the `database`, `reports`, and `imports` relationships. They'll be available in the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) and all have the same structure documented [above](#relationship-reference), but with different credentials. You can use those to connect to the appropriate database with the specified restrictions using whatever the SQL access tools are for your language and application. A service configuration without the `configuration` block defined is equivalent to the following default values: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. postgresql: type: "postgresql:18" configuration: databases: - main endpoints: postgresql: default_database: main privileges: main: admin ``` If you do not define `database` but `endpoints` are defined, then the single database `main` is created with the following assumed configuration: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. postgresql: type: "postgresql:18" configuration: databases: - main endpoints: ``` Alternatively, if you define multiple databases but no endpoints, a single user `main` is created with `admin` access to each of your databases, equivalent to the configuration below: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. postgresql: type: "postgresql:18" configuration: databases: - firstdb - seconddb - thirddb endpoints: main: firstdb: admin seconddb: admin thirddb: admin ``` ## Password generation {#password-generation} If your YAML file does not specify a `schema` and `endpoint` for a database service, no password is generated. Because your database is isolated on a private network and cannot be seen from the internet, you can omit a password without compromising security. This simplifies your workflow by removing the need to manage credentials, while container isolation ensures that only your application can access the data. If you prefer to have Upsun generate a password, you must define [`schemas` and custom `endpoints`](#1-configure-the-service) in the `services` configuration – see the example in the [multiple databases](#multiple-databases) section of this topic. For each custom endpoint that you define, Upsun generates a password. Note that you cannot customize these generated passwords. **Note**: Make sure you don’t change ``services.``. **Changing the service name creates a new service, which removes existing data from your database.** After your custom endpoints are exposed as relationships in your [app configuration](https://docs.upsun.com../../create-apps.md), you can retrieve the password for each endpoint through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) within your [application containers](https://docs.upsun.com/development/variables/use-variables.md#access-variables-in-your-app). Using this method to retrieve password credentials is considered a best practice: passwords might change over time, and using incorrect passwords results in application downtime. **Avoid using hard-coded passwords in your application (and code base), which can cause security issues.** ## Service timezone To change the timezone for the current session, run `SET TIME ZONE ;`. ## Extensions Upsun supports a number of PostgreSQL extensions. To enable them, list them under the `configuration.extensions` key in your `.upsun/config.yaml` file, like so: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. postgresql: type: "postgresql:18" configuration: extensions: - pg_trgm - hstore ``` In this case, you have `pg_trgm` installed, providing functions to determine the similarity of text based on trigram matching, and `hstore` providing a key-value store. ### Available extensions The following is the extensive list of supported extensions. Note that you can't currently add custom extensions not listed here. * `address_standardizer` - Used to parse an address into constituent elements. Generally used to support geocoding address normalization step. * `address_standardizer_data_us` - For standardizing addresses based on US dataset example * `adminpack` - administrative functions for PostgreSQL (only available in versions less than 17) * `autoinc` - functions for auto-incrementing fields * `bloom` - bloom access method - signature file based index (requires 9.6 or higher) * `btree_gin` - support for indexing common data types in GIN * `btree_gist` - support for indexing common data types in GiST * `chkpass` - data type for auto-encrypted passwords * `citext` - data type for case-insensitive character strings * `cube` - data type for multidimensional cubes * `dblink` - connect to other PostgreSQL databases from within a database * `dict_int` - text search dictionary template for integers * `dict_xsyn` - text search dictionary template for extended synonym processing * `earthdistance` - calculate great-circle distances on the surface of the Earth * `file_fdw` - foreign-data wrapper for flat file access * `fuzzystrmatch` - determine similarities and distance between strings * `hstore` - data type for storing sets of (key, value) pairs * `insert_username` - functions for tracking who changed a table * `intagg` - integer aggregator and enumerator (obsolete) * `intarray` - functions, operators, and index support for 1-D arrays of integers * `isn` - data types for international product numbering standards * `lo` - Large Object maintenance * `ltree` - data type for hierarchical tree-like structures * `moddatetime` - functions for tracking last modification time * `pageinspect` - inspect the contents of database pages at a low level * `pg_buffercache` - examine the shared buffer cache * `pg_freespacemap` - examine the free space map (FSM) * `pg_prewarm` - prewarm relation data (requires 9.6 or higher) * `pg_stat_statements` - track execution statistics of all SQL statements executed * `pg_trgm` - text similarity measurement and index searching based on trigrams * `pg_visibility` - examine the visibility map (VM) and page-level visibility info (requires 9.6 or higher) * `pgcrypto` - cryptographic functions * `pgrouting` - pgRouting Extension (requires 9.6 or higher) * `pgrowlocks` - show row-level locking information * `pgstattuple` - show tuple-level statistics * `plpgsql` - PL/pgSQL procedural language * `postgis` - PostGIS geometry, geography, and raster spatial types and functions * `postgis_sfcgal` - PostGIS SFCGAL functions * `postgis_tiger_geocoder` - PostGIS tiger geocoder and reverse geocoder * `postgis_topology` - PostGIS topology spatial types and functions * `postgres_fdw` - foreign-data wrapper for remote PostgreSQL servers * `refint` - functions for implementing referential integrity (obsolete) * `seg` - data type for representing line segments or floating-point intervals * `sslinfo` - information about SSL certificates * `tablefunc` - functions that manipulate whole tables, including `crosstab` * `tcn` - Triggered change notifications * `timetravel` - functions for implementing time travel * `tsearch2` - compatibility package for pre-8.3 text search functions (obsolete, only available for 9.6 and 9.3) * `tsm_system_rows` - TABLESAMPLE method which accepts number of rows as a limit (requires 9.6 or higher) * `tsm_system_time` - TABLESAMPLE method which accepts time in milliseconds as a limit (requires 9.6 or higher) * `unaccent` - text search dictionary that removes accents * `uuid-ossp` - generate universally unique identifiers (UUIDs) * `vector` - Open-source [vector](https://github.com/pgvector/pgvector) similarity search for PostgreSQL 11+ * `xml2` - XPath querying and XSLT **Note**: You can’t upgrade to PostgreSQL 12 with the ``postgis`` extension enabled. For more details, see how to [upgrade to PostgreSQL 12 with ](#upgrade-to-postgresql-12-with-the-postgis-extension). ## Notes ### Could not find driver If you see this error: `Fatal error: Uncaught exception 'PDOException' with message 'could not find driver'`, this means you are missing the `pdo_pgsql` PHP extension. You need to enable it in your `.upsun/config.yaml` ([see above](#1-configure-the-service)). ## Upgrading PostgreSQL 10 and later include an upgrade utility that can convert databases from previous versions to version 10 or later. If you upgrade your service from a previous version of PostgreSQL to version 10 or above, it upgrades automatically. The utility can't upgrade PostgreSQL 9 versions, so upgrades from PostgreSQL 9.3 to 9.6 aren't supported. Upgrade straight to version 11 instead. **Note**: Make sure you first test your migration on a separate branch. Also, be sure to take a backup of your production environment **before** you merge this change. **Warning**: Downgrading isn’t supported. If you need to downgrade, dump to SQL, remove the service, recreate the service, and import your dump. ### Upgrade to PostgreSQL 12 with the `postgis` extension You can't upgrade to PostgreSQL 12 with the `postgis` extension enabled. It involves a change to a major version that results in a failed deployment that requires support intervention to fix. Upgrading from 12 to a higher version is possible. If you need to upgrade to version 12, follow the same steps recommended for downgrading: 1. Dump the database. 2. Remove the service. 3. Create a new service with PostgreSQL 12. 4. Import the dump to that service. --- # Source: https://docs.upsun.com/administration/pricing.md # Pricing Upsun offers flexible, predictable [pricing](https://upsun.com/pricing/) for organizations and projects. **Note**: This page is meant to provide some context for how the pricing model relates to technical work on Upsun. It is not meant to be your primary resource for the exact costs of certain features. The official Upsun [Pricing page](https://upsun.com/pricing/) should always be considered the primary source of pricing details. In general, there are four main dimensions that determine the cost of work on Upsun. | Pricing dimension | Details | |---|---| | Project fees | An individual project on Upsun comes with a consistent monthly cost. The cost includes all of the orchestration and provisioning characteristics that define the Upsun platform.It comes with some baseline features and feature limits, such as infrastructure metrics and a certain number of build minutes. Individual preview environments do not come with their own associated creation cost - you are charged only for the resources those preview environments use during their lifespan (see next row). | | [Project resources](https://docs.upsun.com/manage-resources.md) | Deploying on Upsun allows you fine-grained control over the amount of resources allocated for your application and service containers. CPU, memory, and disk (including backup disk) are calculated across each organization, project, and environment to determine your overall usage for a billing period. | | [User licenses](https://docs.upsun.com/administration/users.md) | Each organization user comes with a license fee. Users can be given different levels of access to singular projects within an organization, or to multiple projects, without changing that license fee. There are two exceptions which are not charged the license fee: Viewers and Viewers who Manage Billing. There are no limits to the number of users you can have in an organization.| | Feature add-ons | There are additional features that can be added to the organization that come with their own cost. Few of these are available immediately during the Beta phase, but more will be added. | A given organization's monthly billing is then made up of the sum of each of these dimensions. You can monitor your spend from the Console via a [current month estimate](https://docs.upsun.com/administration/billing/monitor-billing.md#current-month-estimate) and a [next month estimate](https://docs.upsun.com/administration/billing/monitor-billing.md#next-month-estimate). You can also [set billing alerts](https://docs.upsun.com/administration/billing/monitor-billing.md#manage-billing-alerts) to receive an email when your current month estimate reaches a defined threshold. ## Dunning process If a payment fails, your organization will be immediately restricted. Upsun will proceed to make three separate attempts to take the outstanding balance from your account. These attempts will be made on the 4th, 6th and 11th of the month. If your payment fails after the third attempt on the 11th, your organization will be suspended the following day. When an organization is restricted or suspended, the following applies: - Access to `/projects/{project_id}/user-access` and `/users/{user_id}/project-access` will be denied. - Access to `/projects/{project_id}/team-access` and `/teams/{user_id}/project-access` will be denied. - Access to `/projects/{project_id}/access` and its subresources will be denied. - Projects cannot be transferred to a restricted organization. - Editing or deleting the organization is not allowed. - Creating or deleting members is forbidden. - Editing member permissions is allowed only to add the billing permission - no permissions can be removed. - Access to all account proxy endpoints requiring `plans` or `project:create` permissions is denied, so creating or editing subscriptions at the organization level is forbidden. If you are a new Upsun customer and your first payment has failed, your projects will be deleted on the 13th - two days after the final payment attempt. For all other customers, projects will be deleted 30 days after your organization is suspended on the 11th. You will be notified 10 days before this deletion occurs and a payment will be attempted for the last time. If unsuccessful, all projects on the billing subscription will be deleted. Be sure to visit the [Pricing page](https://upsun.com/pricing/) for exact details related to Upsun pricing. --- # Source: https://docs.upsun.com/development/private-repository.md # Pull code from a private Git repository To complete its build, your Upsun project may need to access pieces of code stored in private Git repositories. Examples include themes, libraries, and modules. Configure these repositories to grant access to your project. To grant access to a private Git repository, add the project's public SSH key to your Git repository's deploy keys. ## 1. Get your project's public key 1. In the Console, open the project you want. 2. Click **Settings Settings**. 3. Under **Project settings**, click **Deploy key**. 4. Click ** Copy**. ![Deploy Key](https://docs.upsun.com/images/management-console/settings-deploy-key.png "0.5") ## 2. Add the key to your repository in your Git provider * [GitHub deploy key](https://docs.github.com/en/developers/overview/managing-deploy-keys#deploy-keys) * [GitLab deploy key](https://docs.gitlab.com/ee/user/project/deploy_keys/#grant-project-access-to-a-public-deploy-key) * [Bitbucket access key](https://support.atlassian.com/bitbucket-cloud/docs/configure-repository-settings/) If you're only pulling code, the key doesn't need write permissions. Now your Upsun project can access your private repository via SSH, including to add dependencies. This means you can access the private repository through links like: ``git@:/.git``. For example, you can clone a repository in your [`build` hook](https://docs.upsun.com../create-apps/hooks/_index.md): ```yaml {location=".upsun/config.yaml"} applications: : hooks: build: | set -e git clone git@bitbucket.org:username/module.git ``` You can also use [private repositories as submodules](https://docs.upsun.com/development/submodules.md#use-private-git-repositories). ## Using multiple private GitHub repositories GitHub requires a separate deploy key for each repository. To grant your project access to multiple repositories, create an automated user account, known as a machine user, with its own SSH key. You can then add the machine account as collaborator to specific repositories or to a team with access to the repositories. See more information about [machine users on GitHub](https://docs.github.com/en/developers/overview/managing-deploy-keys#machine-users). --- # Source: https://docs.upsun.com/security/project-isolation.md # Project isolation At Upsun, customer environments are strictly isolated from each other using [namespaces](https://man7.org/linux/man-pages/man7/namespaces.7.md), [seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.md), and [cgroups](https://man7.org/linux/man-pages/man7/cgroups.7.md). Persistent data (uploaded files into mounts, database data, etc.) is stored on a region-wide storage layer. Data is stored redundantly and mounted into the environments on deployment. Network is behind a firewall for incoming connections. Only a few ports are opened to incoming traffic: ports 22, 80, and 443. There are no exceptions, so any incoming web service requests, [ETL](https://aws.amazon.com/what-is/etl/#:~:text=Extract%2C%20transform%2C%20and%20load%20%28,and%20machine%20learning%20%28ML%29%29.) jobs, or otherwise need to transact over one of these protocols. Outgoing TCP traffic isn’t behind a firewall, **with the exception of port 25 which is blocked**. For containers to be allowed to connect to each other, the following requirements must be met: - The containers must live in the same environment. - You need to define an explicit relationship between the containers in your app configuration. --- # Source: https://docs.upsun.com/create-apps/multi-app/project-structure.md # Choose a project structure How you structure a project with multiple apps depends on how your code is organized and what you want to accomplish. For example, there are various ways you could set up the following multiple apps: Here are some example use cases and potential ways to organize the project: | Use case | Structure | |-----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------| | Separate basic apps that are worked on together. | [Unified app configuration](#unified-app-configuration) | | One app depends on code from another app. | [Nested directories](#nested-directories) | | You want to keep configuration separate from code, such as through Git submodules. | [Configuration separate from code](#split-your-code-source-into-multiple-git-submodule-repositories) | | You want multiple apps from the same source code. | [Unified app configuration](#unified-app-configuration) | | You want to control all apps in a single location. | [Unified app configuration](#unified-app-configuration) | ## Unified app configuration You can configure all your apps from a single file. To do so, create a `.upsun/config.yaml` and define each app as a key. For example, if you have an API Platform backend with a Symfony API, a Mercure Rocks server, and a Gatsby frontend, you can organize your repository like this: ```txt {no-copy="true"} ├── .upsun │ ├── config.yaml <- Unified configuration ├── admin │ └── ... <- API Platform Admin app code ├── api-app │ └── ... <- Bigfoot app code ├── gatsby │ └── ... <- Gatsby app code └── mercure └── ... <- Mercure Rocks app code ``` The `api` app is built from the `api-app` directory. The `admin` app is built from the `admin` directory. The `gatsby` app is built from the `gatsby` directory. The `mercure` app is built from the `mercure` directory. They all have different configurations for how they serve the files. For more details, see the [complete example file](https://github.com/platformsh-templates/bigfoot-multiapp/blob/multiapp-monolith/.platform/applications.yaml). **Note**: The ``.upsun`` directory is located at the root, separate from your apps. It contains all the needed configuration files to set up the routing, services and behavior of each app. Since the code bases of your apps live in a different directory, you need to [change the source root of each app](#change-the-source-root-of-your-app). To build multiple apps from the repository root, set ``source.root`` to ``/``. This allows you to control all your apps in one place and even build multiple apps from the same source code. To allow your apps to communicate with each other, define [relationships](https://docs.upsun.com/create-apps/multi-app/relationships.md). Note that with this setup, when you amend the code of one of your apps, the build image for your other apps can still be reused. Once your repository is organized, you can use a configuration similar to the following: ```yaml {location=".upsun/config.yaml"} applications: api: type: 'php:8.5' relationships: database: service: "database" endpoint: "postgresql" mounts: "/var/cache": "shared:files/cache" "/var/log": "shared:files/log" "/var/sessions": "shared:files/sessions" web: locations: "/": root: "public" passthru: '/index.php' index: - index.php headers: Access-Control-Allow-Origin: "*" hooks: build: | set -x -e curl -s https://get.symfony.com/cloud/configurator | bash symfony-build deploy: | set -x -e symfony-deploy source: root: api-app admin: type: nodejs:16 mounts: '/.tmp_platformsh': 'shared:files/tmp_platformsh' '/build': 'shared:files/build' '/.cache': 'shared:files/.cache' '/node_modules/.cache': 'shared:files/node_modules/.cache' web: locations: "/admin": root: "build" passthru: "/admin/index.html" index: - "index.html" headers: Access-Control-Allow-Origin: "*" hooks: build: | set -eu corepack yarn install --immutable --force post_deploy: | corepack yarn run build source: root: admin gatsby: type: 'nodejs:18' mounts: '/.cache': { source: tmp, source_path: cache } '/.config': { source: storage, source_path: config } '/public': { source: storage, source_path: public } web: locations: '/site': root: 'public' index: [ 'index.html' ] scripts: false allow: true hooks: build: | set -e yarn --frozen-lockfile post_deploy: | yarn build --prefix-paths source: root: gatsby mercure: type: golang:1.18 mounts: 'database': { source: storage, source_path: 'database' } '/.local': { source: storage, source_path: '.local' } '/.config': { source: storage, source_path: '.config' } web: commands: start: ./mercure run --config Caddyfile.platform_sh locations: /: passthru: true scripts: false request_buffering: enabled: false headers: Access-Control-Allow-Origin: "*" hooks: build: | # Install Mercure using cache FILE="mercure_${MERCUREVERSION}_Linux_x86_64.tar.gz" if [ ! -f "$PLATFORM_CACHE_DIR/$FILE" ]; then URL="https://github.com/dunglas/mercure/releases/download/v${MERCUREVERSION}/$FILE" wget -O "$PLATFORM_CACHE_DIR/$FILE" $URL else echo "Found $FILE in cache, using cache" fi file $PLATFORM_CACHE_DIR/$FILE tar xvzf $PLATFORM_CACHE_DIR/$FILE source: root: mercure/.config ``` ## Nested directories When code bases are separate, changes to one app don't necessarily mean that the other apps in the project get rebuilt. You might have a situation where app `main` depends on app `languagetool`, but `languagetool` doesn't depend on `main`. In such cases, you can nest the dependency so the parent (`main`) gets rebuilt on changes to it or its children, but the child (`languagetool`) is only rebuilt on changes to itself. For example, you might have a Python app (`main`) that runs a script that requires Java code to be up to date. But the Java app (`languagetool`) doesn't require updating when the Python app (`main`) is updated. In that case, you can nest the Java app within the Python app: ```txt {no-copy="true"} ├── .upsun │ ├── .upsun/config.yaml ├── languagetool │ └── main.java <- Java app code └── main.py <- Python app code ``` The Python app's code base includes all of the files at the top level (excluding the `.upsun` directory) *and* all of the files within the `languagetool` directory. The Java app's code base includes only the files within the `languagetool` directory. In this case, your `.upsun/config.yaml` file must contain 2 entries, one for the `main` app and second one for the `languagetool` app. **Note**: The ``.upsun`` directory is located at the root, separate from your apps. It contains all the needed configuration files to set up the routing, services and behavior of each app. Since the code base of the ``languagetool`` app lives in a different directory (``languagetool/``), you need to [change the source root](#change-the-source-root-of-your-app) of the ``languagetool`` app. Once your repository is organized, you can use a configuration similar to the following: ```yaml {location=".upsun/config.yaml"} applications: main: type: 'python:3.11' source: root: '/' ... languagetool: type: 'java:17' source: root: 'languagetool' ... ``` ## Split your code source into multiple Git submodule repositories If you have different teams working on different code with different processes, you might want each app to have its own repository. Then you can build them together in another repository using [Git submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules). With this setup, your apps are kept separate from the top application. Each app has its own [Git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules) containing its code base. All your apps are configured in a single `.upsun/config.yaml` file. So you could organize your [project repository](https://github.com/platformsh-templates/bigfoot-multiapp/tree/submodules-root-app-yaml) like this: ```text {no-copy="true"} ├── .upsun │ ├── config.yaml ├── @admin <-- API Platform Admin submodule ├── @api <-- Bigfoot submodule ├── @gatsby <-- Gatsby submodule ├── @mercure <-- Mercure rocks submodule └── .gitmodules ``` [Add the submodules using the Git CLI](https://docs.upsun.com/development/submodules.md#clone-submodules-during-deployment). Your `.gitmodules` file would define all the submodules like this: ```txt {location=".gitmodules"} [submodule "admin"] path = admin url = https://github.com/platformsh-templates/bigfoot-multiapp-admin.git [submodule "api"] path = api url = https://github.com/platformsh-templates/bigfoot-multiapp-api.git [submodule "gatsby"] path = gatsby url = https://github.com/platformsh-templates/bigfoot-multiapp-gatsby.git [submodule "mercure"] path = mercure url = https://github.com/platformsh-templates/bigfoot-multiapp-mercure.git ``` **Note**: In this case, and any other case where your app configuration files are kept outside of the app directory, make sure you [change the source root](#change-the-source-root-of-your-app) for each of your apps. ## Change the source root of your app When your app's code base and configuration file aren't located at the same directory level in your project repository, you need to [define a root directory](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory) for your app. To do so, add a new `source.root` property in your app configuration. For example, to change the source root of the `admin` app from the [unified app configuration](#unified-app-configuration) example project, you could add the following configuration: ```yaml {location=".upsun/config.yaml"} applications: admin: source: root: admin ``` The `source.root` path is relative to the repository root. In this example, the `admin` app now treats the `admin` directory as its root when building. If `source.root` isn't specified, it defaults to the project root directory, that is `"/"`. --- # Source: https://docs.upsun.com/projects.md # Manage projects See how to manage projects within Upsun. To create a project, see how to [get started](https://docs.upsun.com../get-started.md). --- # Source: https://docs.upsun.com/define-routes/proxy.md # Proxy routes **Warning**: Only use this feature to address edge cases where you need to proxy to another, outside project. **Do not use this for internal routing.** To expose your app to the outside world, see [how to define routes](https://docs.upsun.com/define-routes.md). Sometimes you want your app to pass requests on to a different Upsun project. Basic redirects only work within the same project, so use proxy routes for routes elsewhere. You can define an external proxy on your Upsun project by defining a route like the following: ```yaml {location=".upsun/config.yaml"} routes: https://{default}/foo: type: proxy to: https://www.example.com ``` This route passes requests for `https://{default}/foo/index.html` to `https://www.example.com/foo/index.html`. You can also define a proxy route to an URL composed of an IP address and a port: ```yaml {location=".upsun/config.yaml"} routes: https://{default}/foo: type: proxy to: https://192.0.2.0:8000 ``` ## URL paths In the basic example above, the route preserves the URL path, `/foo`, in the request. If you want to proxy a route to `https://www.example.com` without the URL path `/foo`, add a trailing slash `/` to the `to` definition. ```yaml {location=".upsun/config.yaml"} routes: https://{default}/foo: type: proxy to: https://www.example.com/ ``` The trailing slash makes the proxy route interpret the location as having a different path. So requests for `https://{default}/foo/index.html` are forwarded to `https://www.example.com/index.html`. To override the URL path entirely, define a route that contains its own path. For example: ```yaml {location=".upsun/config.yaml"} routes: https://{default}/foo: type: proxy to: https://www.example.com/bar ``` This route passes requests for `https://{default}/foo/index.html` to `https://www.example.com/bar/index.html`. ## Multiple apps with the same base URL You can use proxy routes to map a single domain to multiple Upsun projects with their own subdomain/domain names. You might have a need to access multiple projects, each hosting specific applications for different languages. You want to serve them all at the same base URL with different paths (`https://example.com/en`, `https://example.com/fr`, and so on). Because domains can't be reused at Upsun, you can't just set the same domain for all projects. Use proxy routes so a single project can access different projects using the same base URL. In the following example, a single project specifies proxy routes to three apps with the same `default` base URL. Each app handles a different language. ```yaml {location=".upsun/config.yaml"} routes: https://{default}/en: type: proxy to: https://en.example.com/ https://{default}/jp: type: proxy to: https://jp.example.com/ https://{default}/pt: type: proxy to: https://pt.example.com/ ``` The apps behind the proxy need to ensure links to assets are shown to the target domain. For example, by changing `https://en.example.com/style.css` to `https://example.com/en/style.css`. The following diagram shows the example project forwarding specific requests to the correct app. ```mermaid {no-copy="true"} sequenceDiagram participant User participant Project as Proxy project participant En as En project participant Jp as Jp project participant Pt as Pt project User->>+Project: example.com/en/index.html Project->>+En: en.example.com/index.html Note over En: Changes asset links En-->>-Project: index.html Project-->>-User: index.html User->>+Project: example.com/jp/index.html Project->>+Jp: jp.example.com/index.html Note over Jp: Changes asset links Jp-->>-Project: index.html Project-->>-User: index.html User->>+Project: example.com/pt/index.html Project->>+Pt: pt.example.com/index.html Note over Pt: Changes asset links Pt-->>-Project: index.html Project-->>-User: index.html ``` ### Large projects This architecture makes the router of a single project into the central element of your app. This setup may make scaling more difficult as the router scales with the size of that project. The router can become a bottleneck for all external sites and acts as a single point of failure. For larger projects, you should handle multiple websites with the same base URL via a [CDN](https://docs.upsun.com../domains/cdn.md). --- # Source: https://docs.upsun.com/languages/python/python-version.md # Manage Python versions in non-Python containers p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. You may need to use a specific version of Python that isn't available in an app container for a different language. For example, a container might have a long-term support version, while you want the latest version. In such cases, use the [Pyenv version manager](https://github.com/pyenv/pyenv) to install the specific version you want to use. 1. Add your target Python version as a [variable](https://docs.upsun.com../../development/variables/_index.md): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' variables: env: # Update for your desired Python version. PYTHON_VERSION: "3.11.0" ``` 2. Add Pyenv in a [`build` hook](https://docs.upsun.com../../create-apps/hooks/hooks-comparison.md#build-hook): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' variables: env: # Update for your desired Python version. PYTHON_VERSION: "3.11.0" hooks: build: | # Exit the hook on any failure set -e # Clone Pyenv to the build cache if not present if [ ! -d "$PLATFORM_CACHE_DIR/.pyenv" ]; then mkdir -p $PLATFORM_CACHE_DIR/.pyenv git clone https://github.com/pyenv/pyenv.git $PLATFORM_CACHE_DIR/.pyenv fi # Pyenv environment variables export PYENV_ROOT="$PLATFORM_CACHE_DIR/.pyenv" export PATH="$PYENV_ROOT/bin:$PATH" # Initialize Pyenv if command -v pyenv 1>/dev/null 2>&1; then eval "$(pyenv init --path)" fi # Install desired Python version mkdir -p $PLATFORM_CACHE_DIR/.pyenv/versions if [ ! -d "$PLATFORM_CACHE_DIR/.pyenv/versions/$PYTHON_VERSION" ]; then pyenv install $PYTHON_VERSION fi # Set global Python version pyenv global $PYTHON_VERSION ``` Now your build hook can use the specified version of Python. You can verify this by running `python --version`. If you want this Python version to be available in the runtime environment, follow these steps: 1. Copy Pyenv to your runtime environment at the end of your build hook: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'php:8.5' hooks: build: | ... # Copy Pyenv directory to runtime directory cp -R $PLATFORM_CACHE_DIR/.pyenv $PLATFORM_APP_DIR # Rehash Pyenv for new (runtime) location PYENV_ROOT="$PLATFORM_APP_DIR/.pyenv" $PLATFORM_APP_DIR/.pyenv/bin/pyenv rehash ``` 2. Create an [`.environment` file](https://docs.upsun.com../../development/variables/set-variables.md#set-variables-via-script): ```bash touch .environment ``` 3. Update the PATH for the runtime environment: ```yaml {location=".environment"} export PATH=/app/.pyenv/bin:/app/.pyenv/shims:$PATH ``` Now the specified Python version is used in the runtime environment. --- # Source: https://docs.upsun.com/languages/python.md # Python p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. Python is a general purpose scripting language often used in web development. You can deploy Python apps on Upsun using a server or a project such as [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/). ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 3.14 - 3.13 - 3.12 - 3.11 - 3.10 ### Specify the language To use Python, specify ``python`` as your [app’s type](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#types): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. : type: 'python:' ``` For example: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' ``` ### Deprecated versions The following versions are [deprecated](https://docs.upsun.com/glossary.md#deprecated-versions). They're available, but they don't receive security updates from upstream and aren't guaranteed to work. They'll be removed in the future – consider migrating to a [supported version](#supported-versions). - 3.9 - 3.8 - 3.7 - 3.6 - 3.5 - 2.7 \* This version doesn't receive any updates at all. You are strongly recommended to upgrade to a supported version. ## Usage example ### Run your own server You can define any server to handle requests. Once you have it configured, add the following configuration to get it running on Upsun: 1. Specify one of the [supported versions](#supported-versions): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' ``` 2. Install the requirements for your app. ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' dependencies: python3: pipenv: "2024.4.1" hooks: build: | set -eu pipenv install --system --deploy ``` 3. Define the command to start your web server: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' web: # Start your app with the configuration you define # You can replace the file location with your location commands: start: python server.py ``` You can choose from many web servers such as Daphne, Gunicorn, Hypercorn, and Uvicorn. See more about [running Python web servers](https://docs.upsun.com/languages/python/server.md). ### Use uWSGI You can also use [uWSGI](https://uwsgi-docs.readthedocs.io/en/latest/) to manage your server. Follow these steps to get your server started. 1. Specify one of the [supported versions](#supported-versions): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' ``` 2. Define the conditions for your web server: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' web: upstream: # Send requests to the app server through a unix socket # Its location is defined in the SOCKET environment variable socket_family: "unix" # Start your app with the configuration you define # You can replace the file location with your location commands: start: "uwsgi --ini conf/uwsgi.ini" locations: # The folder from which to serve static assets "/": root: "public" passthru: true expires: 1h ``` 3. Create configuration for uWSGI such as the following: ```ini {location="config/uwsgi.ini"} [uwsgi] # Unix socket to use to talk with the web server # Uses the variable defined in the configuration in step 2 socket = $(SOCKET) protocol = http # the entry point to your app wsgi-file = app.py ``` Replace `app.py` with whatever your file is. 4. Install the requirements for your app. ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' dependencies: python3: pipenv: "2024.4.1" hooks: build: | set -eu pipenv install --system --deploy ``` 5. Define the entry point in your app: ```python # You can name the function differently and pass the new name as a flag # start: "uwsgi --ini conf/uwsgi.ini --callable " def application(env, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [b"Hello world from Upsun"] ``` ## Package management Your app container comes with pip pre-installed. For more about managing packages with pip, Pipenv, and Poetry, see how to [manage dependencies](https://docs.upsun.com/languages/python/dependencies.md). To add global dependencies (packages available as commands), add them to the `dependencies` in your [app configuration](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#dependencies): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' dependencies: python3: : ``` For example, to use `pipenv` to manage requirements and a virtual environment, add the following: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' dependencies: python3: pipenv: "2024.4.1" hooks: build: | set -eu pipenv install --system --deploy ``` ## Connect to services The following examples show how to access various [services](https://docs.upsun.com../../add-services.md) with Python. For more information on configuring a given service, see the page for that service. You can access service credentials to connect to [managed services](https://docs.upsun.com/add-services/) from environment variables present in the application container. Consult each of the individual service documentation to see how to retrieve and surface credentials into your application. - [Chroma](https://docs.upsun.com/add-services/chroma.md#3-use-the-relationship-in-your-application) - [ClickHouse](https://docs.upsun.com/add-services/clickhouse.md#usage-example) - [Elasticsearch](https://docs.upsun.com/add-services/elasticsearch.md#use-in-app) - [Edgee (Edge Analytics)](https://docs.upsun.com/add-services/edgee.md#setup-edgee) - [Gotenberg](https://docs.upsun.com/add-services/gotenberg.md#usage-example) - [Headless Chrome](https://docs.upsun.com/add-services/headless-chrome.md#use-in-app) - [InfluxDB](https://docs.upsun.com/add-services/influxdb.md#use-in-app) - [Kafka](https://docs.upsun.com/add-services/kafka.md#use-in-app) - [MariaDB/MySQL](https://docs.upsun.com/add-services/mysql.md#use-in-app) - [Memcached](https://docs.upsun.com/add-services/memcached.md#use-in-app) - [Mercure](https://docs.upsun.com/add-services/mercure.md#use-in-app) - [MongoDB](https://docs.upsun.com/add-services/mongodb.md#use-in-app) - [Network Storage](https://docs.upsun.com/add-services/network-storage.md#usage-example) - [OpenSearch](https://docs.upsun.com/add-services/opensearch.md#use-in-app) - [PostgreSQL](https://docs.upsun.com/add-services/postgresql.md#use-in-app) - [Qdrant](https://docs.upsun.com/add-services/qdrant.md#4-use-the-relationship-in-your-application) - [RabbitMQ](https://docs.upsun.com/add-services/rabbitmq.md#use-in-app) - [Redis](https://docs.upsun.com/add-services/redis.md#use-in-app) - [Solr](https://docs.upsun.com/add-services/solr.md#use-in-app) - [Valkey](https://docs.upsun.com/add-services/valkey.md#use-in-app) - [Varnish](https://docs.upsun.com/add-services/varnish.md#usage-example) - [Vault KMS](https://docs.upsun.com/add-services/vault.md#use-vault-kms) ## Sanitizing data By default, data is inherited automatically by each child environment from its parent. If you need to sanitize data in preview environments for compliance, see how to [sanitize databases](https://docs.upsun.com../../development/sanitize-db.md). ## Frameworks All major Python web frameworks can be deployed on Upsun. See dedicated guides for deploying and working with them: - [Django](https://docs.upsun.com/get-started/stacks/django.md) - [Flask](https://docs.upsun.com/get-started/stacks/flask.md) --- # Source: https://docs.upsun.com/add-services/rabbitmq.md # RabbitMQ (message queue service) [RabbitMQ](https://www.rabbitmq.com/documentation.md) is a message broker that supports multiple messaging protocols, such as the Advanced Message Queuing Protocol (AMQP). It gives your apps a common platform to send and receive messages and your messages a safe place to live until they're received. ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 4.1 ### Deprecated versions The following versions are [deprecated](https://docs.upsun.com/glossary.md#deprecated-versions). They're available, but they don't receive security updates from upstream and aren't guaranteed to work. They'll be removed in the future – consider migrating to a [supported version](#supported-versions). - 4.0 - 3.13 - 3.12 - 3.11 - 3.10 - 3.9 - 3.8 - 3.7 - 3.6 - 3.5 ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "username": "guest", "scheme": "amqp", "service": "rabbitmq", "fragment": null, "ip": "123.456.78.90", "hostname": "azertyuiopqsdfghjklm.rabbitmq.service._.eu-1.platformsh.site", "port": 5672, "cluster": "azertyuiopqsdf-main-afdwftq", "host": "rabbitmq.internal", "rel": "rabbitmq", "path": null, "query": [], "password": "ChangeMe", "type": "rabbitmq:4.1", "public": false, "host_mapped": false } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_RABBITMQ_HOST="$(echo "$RELATIONSHIPS_JSON" | jq -r '.rabbitmq[0].host')" ``` ## Usage example ### 1. Configure the service To define the service, use the ``rabbitmq`` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: rabbitmq: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. ### 2. Define the relationship To define the relationship, use the following configuration: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container (````) now has access to the service via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: rabbitmq ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). ### Example configuration ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: rabbitmq: services: # The name of the service container. Must be unique within a project. rabbitmq: type: rabbitmq:4.1 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: rabbitmq: service: rabbitmq endpoint: rabbitmq services: # The name of the service container. Must be unique within a project. rabbitmq: type: rabbitmq:4.1 ``` ### Use in app To use the configured service in your app, add a configuration file similar to the following to your project. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" [...] # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: rabbitmq: services: # The name of the service container. Must be unique within a project. rabbitmq: type: rabbitmq:4.1 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" [...] # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: rabbitmq: service: rabbitmq endpoint: rabbitmq services: # The name of the service container. Must be unique within a project. rabbitmq: type: rabbitmq:4.1 ``` This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory. `myapp` has access to the `rabbitmq` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship) (as per [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships). From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference). ```bash {location="myapp/.environment"} # Set environment variables for individual credentials. # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. export QUEUE_SCHEME="${RABBITMQ_SCHEME}" export QUEUE_USERNAME="${RABBITMQ_USERNAME}" export QUEUE_PASSWORD="${RABBITMQ_PASSWORD}" export QUEUE_HOST="${RABBITMQ_HOST}" export QUEUE_PORT="${RABBITMQ_PORT}" # Set a single RabbitMQ connection string variable for AMQP. export AMQP_URL="${QUEUE_SCHEME}://${QUEUE_USERNAME}:${QUEUE_PASSWORD}@${QUEUE_HOST}:${QUEUE_PORT}/" ``` The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``AMQP_URL`` can be used within the application to connect to the service. Note that ``AMQP_URL``, and all Upsun [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) like ``RABBITMQ_HOST``, are environment-dependent. Unlike the build produced for a given commit, they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment. A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](https://docs.upsun.com/get-started.md). ## Connect to RabbitMQ When debugging, you may want to connect directly to your RabbitMQ service. You can connect in multiple ways: - An [SSH tunnel](#via-ssh) - A [web interface](#access-the-management-ui) In each case, you need the login credentials that you can obtain from the [relationship](#relationship-reference). ### Via SSH To connect directly to your RabbitMQ service in an environment, open an SSH tunnel with the [Upsun CLI](https://docs.upsun.com../administration/cli.md). To open an SSH tunnel to your service with port forwarding, run the following command: ```bash upsun tunnel:single --gateway-ports ``` Then configure a RabbitMQ client to connect to this tunnel using the credentials from the [relationship](#relationship-reference). See a [list of RabbitMQ client libraries](https://www.rabbitmq.com/devtools.md). ### Access the management UI RabbitMQ offers a [management plugin with a browser-based UI](https://www.rabbitmq.com/management.md). You can access this UI with an SSH tunnel. To open a tunnel, follow these steps. 1. SSH into your app container with a flag for local port forwarding: 2. ```bash ssh $(upsun ssh --pipe) -L 15672:.internal:15672 ``` is the [name you defined](#2-define-the-relationship). 2. Open `http://localhost:15672` in your browser. Log in using the username and password from the [relationship](#relationship-reference). ## Configuration options You can configure your RabbitMQ service in the [services configuration](#1-configure-the-service) with the following options: | Name | Type | Required | Description | |----------|-------------------|----------|------------------------------------------------------| | `vhosts` | List of `string`s | No | Virtual hosts used for logically grouping resources. | You can configure additional [virtual hosts](https://www.rabbitmq.com/vhosts.md), which can be useful for separating resources, such as exchanges, queues, and bindings, into their own namespaces. To create virtual hosts, add them to your configuration as in the following example: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. rabbitmq: type: "rabbitmq:4.1" configuration: vhosts: - host1 - host2 ``` ## Upgrading When upgrading RabbitMQ, skipping major versions (e.g. 3.7 -> 3.11) [is not supported](https://www.rabbitmq.com/upgrade.md#rabbitmq-version-upgradability). Make sure you upgrade sequentially (3.7 -> 3.8 -> 3.9 -> 3.10 -> 3.11) and that each upgrade commit translates into an actual deployment. --- # Source: https://docs.upsun.com/define-routes/redirects.md # Redirects Managing redirection rules is a common requirement for web applications, especially in cases where you do not want to lose incoming links that have changed or been removed over time. You can manage redirection rules on your Upsun projects in two different ways, which we describe here. If neither of these options satisfy your redirection needs, you can still implement redirects directly from within your application, which if implemented with the appropriate caching headers would be almost as efficient as using the configuration options provided by Upsun. **Route limits**: Please note that the maximum size of the routes document is 128 KB, which should fit around 300 different routes. [Read more about route limits here.](https://docs.upsun.com/define-routes.md#route-limits) ## Whole-route redirects Using whole-route redirects, you can define very basic routes in your [`.upsun/config.yaml`](https://docs.upsun.com/define-routes.md) file whose sole purpose is to redirect. A typical use case for this type of route is adding or removing a `www.` prefix to your domain, as the following example shows: ```yaml {location=".upsun/config.yaml"} routes: https://{default}/: type: redirect to: https://www.{default}/ ``` The default HTTP status code for Whole-route redirects is `301`. See [Specify a HTTP status code](#specify-a-http-status-code) to change the status code that is used. ## Partial redirects In the [`.upsun/config.yaml`](https://docs.upsun.com/define-routes.md) file you can also add partial redirect rules to existing routes: ```yaml {location=".upsun/config.yaml"} routes: https://{default}/: # ... redirects: expires: 1d paths: '/from': to: 'https://example.com/' '^/foo/(.*)/bar': to: 'https://example.com/$1' regexp: true ``` This format is richer and works with any type of route, including routes served directly by the application. The default HTTP status code for partial redirects is `302`. See [Specify a HTTP status code](#specify-a-http-status-code) to change the status code that is used. Two keys are available under `redirects`: | Key | Required | Description | | ------------------ | -------- | ----------- | | `expires` | No | The duration the redirect is cached. Examples of valid values include `3600s`, `1d`, `2w`, `3m`. To disable caching for all your redirects, set `expires` to `0`. You can also [disable caching on a specific redirect](#disable-caching-on-your-redirects). | | `paths` | Yes | The paths to be redirected | Each rule under `paths` is defined by a key describing: - The expression to match against the request path - A value object describing both the destination to redirect to, with detail on how to handle the redirection The value object is defined with the following keys: | Key | Required | Default | Description | | ------------------ | -------- | ----------- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `to` | Yes | n/a | A relative URL - `'/destination'`, or absolute URL - `'https://example.com/'`. | | `regexp` | No | `false` | Specifies whether the path key should be interpreted as a PCRE regular expression. If you use a capturing group, the replace field (`$1`) has to come after a slash (`/`). [More information](#redirects-using-regular-expressions). | | `prefix` | No | `true`, but not supported if `regexp` is `true` | Specifies whether both the path and all its children or just the path itself should be redirected. [More information](#redirects-using-prefix-and-append_suffix). | | `append_suffix` | No | `true`, but not supported if `regexp` is `true` or if `prefix` is `false` | Determines if the suffix is carried over with the redirect. [More information](#redirects-using-prefix-and-append_suffix). | | `code` | No | n/a | HTTP status code. Valid status codes are `301`, `302`, `307`, and `308`. Defaults to `302` for [Partial redirects](#partial-redirects), and `301` for [Whole-route redirects](#whole-route-redirects). [More information](#specify-a-http-status-code). | | `expires` | No | Defaults to the `expires` value defined directly under the `redirects` key, but can be fine-tuned. To [disable caching on a specific redirect](#disable-caching-on-your-redirects), set `expires` to `0`. | The duration the redirect is cached for. [More information](#manage-caching). To set up partial redirects, you can use regular expressions (`regexp`). Alternatively, and in many cases, you can use the `prefix` and/or `append_suffix` keys to achieve the same results. Here are some examples to illustrate this and help you choose a method for your partial redirects: It achieves the same result as this basic redirect: ```yaml {} '/from': to: https://example.com/to ``` Consider this redirect using ``prefix``: ```yaml {} '/from': to: https//example.com/to prefix: false ``` It achieves the same result as this ``regexp`` redirect: ```yaml {} '^/from$': regexp: true to: https://example.com/to ``` Consider this redirect using ``append_suffix``: ```yaml {} '/from': to: https//example.com/to append_suffix: false ``` It achieves the same result as this ``regexp`` redirect: ```yaml {} '^/from(/.*|)$': regexp: true to: https://example.com/to ``` **Warning**: If you’re using ``regexp`` in a redirect, you can’t also use ``prefix`` and ``append_suffix``. Likewise, if you’re using ``prefix`` and ``append_suffix``, you can’t also use ``regexp``. ### Redirects using regular expressions You can use regular expressions to configure your redirects. In the following example, a request to `https://example.com/foo/a/b/c/bar` redirects to `https://example.com/a/b/c`: ```yaml {location=".upsun/config.yaml"} routes: https://{default}/: type: upstream # ... redirects: paths: '^/foo/(.*)/bar': to: 'https://example.com/$1' regexp: true ``` The following special arguments in the `to` statement are available when `regexp` is set to `true`: - `$is_args` evaluates to `?` or empty string - `$args` evaluates to the full query string if any - `$arg_foo` evaluates to the value of the query parameter `foo` - `$uri` evaluates to the full URI of the request. ### Redirects using `prefix` and `append_suffix` Instead of using regular expressions to configure your redirects, you might want to use the `prefix` and `append_suffix` keys. **Warning**: If you’re using ``regexp`` in a redirect, you can’t also use ``prefix`` and ``append_suffix``. Likewise, if you’re using ``prefix`` and ``append_suffix``, you can’t also use ``regexp``. When set to `true`, which is their default value, `prefix` and `append_suffix` are equivalent. For example: ```yaml {} routes: https://{default}/: type: upstream # ... redirects: paths: '/from': to: 'https://{default}/to' prefix: true ``` ```yaml {} routes: https://{default}/: type: upstream # ... redirects: paths: '/from': to: 'https://{default}/to' append_suffix: true ``` With both configurations: - `/from` redirects to `/to` - `/from/some/path` redirects to `/to/some/path` However, when set to `false`, `prefix` and `append_suffix` behave differently. For example, with the following configuration: ```yaml routes: https://{default}/: type: upstream # ... redirects: paths: '/from': to: 'https://{default}/to' prefix: true ``` A request to `/from/` redirects to `/to/some/path`, but a request to `/from/some/path` does not. And with the following configuration: ```yaml routes: https://{default}/: type: upstream # ... redirects: paths: '/from': to: 'https://{default}/to' append_suffix: false ``` A request to `/from/some/path` (and any path after `/from`) redirects to just `/to`. ### Specify a HTTP status code To set a specific HTTP status code for your redirect, use the `code` key: ```yaml routes: https://{default}/: type: upstream # ... redirects: paths: '/from': to: 'https://example.com/' code: 308 '/here': to: 'https://example.com/there' ``` In this example, redirects from `/from` use a `308` HTTP status code, while redirects from `/here` default to `302` ("found", as long as the resource is indeed found as a result from the redirect). ### Manage caching You can [set an expiration time on your redirects](#set-an-expiration-time-on-your-redirects) or even [disable caching](#disable-caching-on-your-redirects) on them. #### Set an expiration time on your redirects You can specify how long you want your redirects to be cached for. To do so, use the `expires` key under the `redirects` key. In the following example, all redirects are cached for two weeks: ```yaml routes: https://{default}/: type: upstream # ... redirects: expires: 2w paths: '/from': to: 'https://example.com/' '/here': to: 'https://example.com/there' ``` If you want to set a different expiration time for a specific redirect, use the same `expires` key, but under the `paths` key. In the following example: - The first redirect uses the default expiration time set on all redirects and is cached for two weeks - The second redirect ignores the default expiration time set on all redirects, and is cached for three days instead ```yaml routes: https://{default}/: type: upstream # ... redirects: expires: 2w paths: '/from': to: 'https://example.com/' '/here': to: 'https://example.com/there' expires: 3d ``` **Note**: You can set an expiration time on a specific redirect (under the ``paths`` key) even if you haven’t defined a default expiration time on all your redirects (under the ``redirects`` key). The expiration time you set on a specific redirect (under the ``paths`` key) overwrites any default expiration time you may have set on all your redirects (under the ``redirects`` key). #### Disable caching on your redirects To disable caching on all your redirects, set the `expires` key to `0` under the `redirects` key: ```yaml routes: https://{default}/: type: upstream # ... redirects: expires: 0 paths: '/from': to: 'https://example.com/' '/here': to: 'https://example.com/there' ``` To disable caching on a specific redirect only, set the `expires` key to `0` under the relevant path in the `paths` section. In the following example, caching is disabled on the second redirect only: ```yaml routes: https://{default}/: type: upstream # ... redirects: paths: '/from': to: 'https://example.com/' '/here': to: 'https://example.com/there' expires: 0 ``` ## Other redirects ### Application-driven redirects If neither whole-route or partial redirects satisfy your redirection needs, you can still implement redirects directly in your application. If sent with the appropriate caching headers, this is nearly as efficient as implementing the redirect through one of the two configurations described above. Implementing application-driven redirects depends on your own code or framework and is beyond the scope of this documentation. ### Query-strings based redirects Upsun **does not** support redirects based on query strings. If you want to redirect based on query strings, this logic has to be implemented by your application. --- # Source: https://docs.upsun.com/languages/php/redis.md # Source: https://docs.upsun.com/add-services/redis.md # Redis (Object cache) [Redis](https://redis.io/documentation) is a multi-model database that allows you to store data in memory for high-performance data retrieval and key-value storage. Upsun supports two different Redis configurations: - [Persistent](#persistent-redis): to set up fast persistent storage for your application - [Ephemeral](#ephemeral-redis): to set up a non-persistent cache for your application ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 8.0 - 7.2 ### Deprecated versions The following versions are [deprecated](https://docs.upsun.com/glossary.md#deprecated-versions). They're available, but they don't receive security updates from upstream and aren't guaranteed to work. They'll be removed in the future – consider migrating to a [supported version](#supported-versions). - 7.0 - 6.2 - 6.0 - 5.0 Note that versions 3.0 and higher support up to 64 different databases per instance of the service, while Redis 2.8 only supports a single database. ## Service types Depending on your needs, you can set up Redis as [persistent](#persistent-redis) or [ephemeral](#ephemeral-redis). ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "username": null, "scheme": "redis", "service": "redis", "fragment": null, "ip": "123.456.78.90", "hostname": "azertyuiopqsdfghjklm.redis.service._.eu-1.platformsh.site", "port": 6379, "cluster": "azertyuiopqsdf-main-7rqtwti", "host": "redis.internal", "rel": "redis", "path": null, "query": [], "password": null, "type": "redis:8.0", "public": false, "host_mapped": false } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_REDIS_HOST="$(echo "$RELATIONSHIPS_JSON" | jq -r '.redis[0].host')" ``` The format of the relationship is identical whether your Redis service is [ephemeral](#ephemeral-redis) or [persistent](#persistent-redis). ## Persistent Redis By default, Redis is an ephemeral service that stores data in memory. This allows for fast data retrieval, but also means data can be lost when a container is moved or shut down. To solve this issue, configure your Redis service as persistent. Persistent Redis stores data on a disk, restoring it if the container restarts. To switch from persistent to ephemeral Redis, set up a new service with a different name. **Warning**: Upsun sets the maximum amount of memory (``maxmemory``) Redis can use for the data set, and it cannot be amended. It is defined by comparing the following values and keeping the lower of the two: - Disk size/6 (based on a [recommendation from Redis](https://docs.redis.com/latest/rs/installing-upgrading/install/plan-deployment/hardware-requirements/#productionenvironment)) - The amount of memory allocated to the service container For instance, if your Redis container has 3072 MB of disk space and 1024 MB of memory, only 512 MB of RAM are actually available to the service (3072/6 = 512). But if your Redis container has 3072 MB of disk space and 256 MB of memory, only 256 MB of RAM are actually available to the service (as per the container limit). ### Usage example #### 1. Configure the service To define the service, use the `redis-persistent` endpoint: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: redis-persistent: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. #### 2. Define the relationship To define the relationship, use the `redis` endpoint : ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: redis ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). For PHP, enable the [extension](https://docs.upsun.com/languages/php/extensions.md) for the service: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: redis ``` ### Configuration example ```yaml {} applications: # The name of the app container. Must be unique within a project. : source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: redis: services: # The name of the service container. Must be unique within a project. redis: type: redis-persistent:8.0 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: redis: service: redis endpoint: redis services: # The name of the service container. Must be unique within a project. redis: type: redis-persistent:8.0 ``` ### Use in app To use the configured service in your app, add a configuration file similar to the following to your project. ```yaml {} applications: # The name of the app container. Must be unique within a project. : source: root: "myapp" # PHP extensions. runtime: extensions: - redis [...] # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: redis: services: # The name of the service container. Must be unique within a project. redis: type: redis-persistent:8.0 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : source: root: "myapp" # PHP extensions. runtime: extensions: - redis [...] # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: redis: service: redis endpoint: redis services: # The name of the service container. Must be unique within a project. redis: type: redis-persistent:8.0 ``` This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory. `myapp` has access to the `redis` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship) (as per [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships). From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference). ```bash {location="myapp/.environment"} # Set environment variables for individual credentials. # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. export CACHE_HOST="${REDIS_HOST}" export CACHE_PORT="${REDIS_PORT}" export CACHE_PASSWORD="${REDIS_PASSWORD}" export CACHE_SCHEME="${REDIS_SCHEME}" # Surface a Redis connection string for use in app. export CACHE_URL="${CACHE_SCHEME}://${CACHE_PASSWORD}@${CACHE_HOST}:${CACHE_PORT}" ``` The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``CACHE_URL`` can be used within the application to connect to the service. Note that ``CACHE_URL``, and all Upsun [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) like ``REDIS_HOST``, are environment-dependent. Unlike the build produced for a given commit, they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment. A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](https://docs.upsun.com/get-started.md). ## Ephemeral Redis By default, Redis is an ephemeral service that serves as a non-persistent cache. Ephemeral Redis stores data only in memory and requires no disk space. When the service reaches its memory limit, it triggers a cache cleanup. To customize those cache cleanups, set up an [eviction policy](#eviction-policy). Make sure your app doesn't rely on ephemeral Redis for persistent storage as it can cause issues. For example, if a container is moved during region maintenance, the `deploy` and `post_deploy` hooks don't run and an app that treats the cache as permanent shows errors. To prevent data from getting lost when a container is moved or shut down, you can use the [persistent Redis](#persistent-redis) configuration. Persistent Redis provides a cache with persistent storage. ### Usage example #### 1. Configure the service To define the service, use the `redis` endpoint: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: redis: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. #### 2. Define the relationship To define the relationship, use the `redis` endpoint : ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: redis ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). For PHP, enable the [extension](https://docs.upsun.com/languages/php/extensions.md) for the service: ```yaml {} applications: # The name of the app container. Must be unique within a project. : source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : services: # The name of the service container. Must be unique within a project. : type: redis: ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: redis services: # The name of the service container. Must be unique within a project. : type: redis: ``` ### Configuration example ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: redis: services: # The name of the service container. Must be unique within a project. redis: type: redis:8.0 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: redis: service: redis endpoint: redis services: # The name of the service container. Must be unique within a project. redis: type: redis:8.0 ``` ### Use in app To use the configured service in your app, add a configuration file similar to the following to your project. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: redis: services: # The name of the service container. Must be unique within a project. redis: type: redis:8.0 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: redis: service: redis endpoint: redis services: # The name of the service container. Must be unique within a project. redis: type: redis:8.0 ``` This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory. `myapp` has access to the `redis` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship) (as per [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships). From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference). ```bash {location="myapp/.environment"} # Set environment variables for individual credentials. # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. export CACHE_HOST="${REDIS_HOST}" export CACHE_PORT="${REDIS_PORT}" export CACHE_PASSWORD="${REDIS_PASSWORD}" export CACHE_SCHEME="${REDIS_SCHEME}" # Surface a Redis connection string for use in app. export CACHE_URL="${CACHE_SCHEME}://${CACHE_PASSWORD}@${CACHE_HOST}:${CACHE_PORT}" ``` The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``CACHE_URL`` can be used within the application to connect to the service. Note that ``CACHE_URL``, and all Upsun [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) like ``REDIS_HOST``, are environment-dependent. Unlike the build produced for a given commit, they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment. A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](https://docs.upsun.com/get-started.md). ## Multiple databases Redis 3.0 and above support up to 64 databases. But you can't set up different access rights to each database. When you set up a relationship connection, access to all of the databases is automatically granted. The way to access a particular database depends on the [client library](https://redis.io/clients) you're using: To manage [thread safety](https://github.com/redis/redis-py/blob/master/docs/advanced_features.rst#user-content-a-note-about-threading), the Python library suggests using separate client instances for each database: ```python {} import os from redis import Redis database0 = Redis(host=os.getenv('REDIS_HOST'), port=os.getenv('REDIS_PORT'), db=0) database1 = Redis(host=os.getenv('REDIS_HOST'), port=os.getenv('REDIS_PORT'), db=1) ``` Use the Redis [select](https://redis.io/commands/select): ```javascript {} const redis = require('redis'); const client = redis.createClient(process.env.REDIS_PORT, process.env.REDIS_HOST); await client.SELECT(0); // switch to DB 0 await client.set('x', '42'); // write 42 to x await client.MOVE('x', 1); // move to DB 1 await client.SELECT(1); // switch to DB 1 const value = await client.get('x'); // returns 42 ``` ## Eviction policy When Redis reaches its memory limit, it triggers a cache cleanup. To customize those cache cleanups, set up an eviction policy such as the following: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. redis: type: "redis:8.0" configuration: maxmemory_policy: allkeys-lfu ``` The following table presents the possible values: | Value | Policy description | |-------------------|-------------------------------------------------------------------------------------------------------------| | `allkeys-lru` | Removes the oldest cache items first. This is the default policy when `maxmemory_policy` isn't set. | | `noeviction` | New items aren’t saved when the memory limit is reached. | | `allkeys-lfu` | Removes least frequently used cache items first. | | `volatile-lru` | Removes least recently used cache items with the `expire` field set to `true`. | | `volatile-lfu` | Removes least frequently used cache items with the `expire` field set to `true`. | | `allkeys-random` | Randomly removes cache items to make room for new data. | | `volatile-random` | Randomly removes cache items with the `expire` field set to `true`. | | `volatile-ttl` | Removes cache items with the `expire` field set to `true` and the shortest remaining `time-to -live` value. | For more information on the different policies, see the official [Redis documentation](https://redis.io/docs/latest/operate/rs/databases/memory-performance/eviction-policy/). ## Access your Redis service After you've [configured your Redis service](#usage-example), you can access it using either the Upsun CLI or through the [Redis CLI](https://redis.io/docs/latest/operate/rs/references/cli-utilities/). ### Upsun CLI Unlike the Redis CLI, connecting via the Upsun CLI does not require additional authentication steps if you are already authenticated in your terminal. Access your Redis service by running the command: ```bash upsun redis ``` ### Redis CLI Retrieve the hostname and port you can connect to through the `PLATFORM_RELATIONSHIPS` [environment variable](https://docs.upsun.com../../development/variables/use-variables.md#use-provided-variables). To do so, run the `upsun relationships` command. After you've retrieved the hostname and port, [open an SSH session](https://docs.upsun.com../development/ssh.md). To access your Redis service, run the following command: ```bash redis-cli -h -p ``` If you have a Grid project, note that the `CONFIG GET` and `CONFIG SET` admin commands are restricted. To get the current configuration, run the following command: ```bash redis-cli -h -p info ``` ## Use Redis as a handler for PHP sessions A PHP session allows you to store different data for each user through a unique session ID. By default, PHP handles sessions using files. But you can use Redis as a session handler, which means Redis stores and retrieves the data saved into sessions. To set up Redis as your session handler, add a configuration similar to the following: ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: source: root: "myapp" type: "php:8.5" # PHP extensions. runtime: extensions: - redis relationships: redissession: variables: php: session.save_handler: redis session.save_path: "tcp://:" web: locations: '/': root: 'web' passthru: '/index.php' services: # The name of the service container. Must be unique within a project. redissession: type: "redis-persistent:8.0" ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: source: root: "myapp" type: "php:8.5" # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: redissession: service: redissession endpoint: redis variables: php: session.save_handler: redis session.save_path: "tcp://:" web: locations: '/': root: 'web' passthru: '/index.php' services: # The name of the service container. Must be unique within a project. redissession: type: "redis-persistent:8.0" ``` --- # Source: https://docs.upsun.com/administration/cli/reference.md # Source: https://docs.upsun.com/integrations/activity/reference.md # Activity reference Activities log changes to your project, including when you deploy your app, when you [push code](#push), and when a [cron job is run](#cron). To automate your workflows, you can parse and react to the activity's JSON object through [activity scripts](https://docs.upsun.com../activity.md). ## Activity schema Every activity has a corresponding JSON object containing all information for that activity, including timestamps, configuration, and sometimes logs. In practice, you can ignore much of the JSON object's content. The most commonly used values are documented in this reference. The response differs depending on the activity and doesn't always include all fields. ### Example response The following is a shortened example of a response for an [environment sync activity](https://docs.upsun.com/glossary.md#sync). You can also see [complete examples of responses](#examples). ```json {no-copy="true"} { "id": "abcdefg123456", ... "created_at": "2026-12-16T14:28:17.890467+00:00", "updated_at": null, "type": "environment.synchronize", "parameters": { ... }, "project": "abcdefgh1234567", "environments": [ "feature" ], "state": "complete", "result": "success", "started_at": "2026-12-16T14:28:18.188888+00:00", "completed_at": "2026-12-16T14:31:48.809068+00:00", "completion_percent": 100, "cancelled_at": null, "timings": { "wait": 0, "build": 0.349, "deploy": 209.986, "execute": 210.508 }, "log": "Building application 'app' (runtime type: php:8.5, tree: 9851a01)\n Reusing existing build for this tree ID\n\n...\nRedeploying environment test, as a clone of main\n ...\n Closing all services\n Opening application app and its relationships\n Executing deploy hook for application app\n ... Environment configuration\n app (type: php:8.5, size: S, disk: 2048)\n\n ...", "payload": { ... }, "description": "Cloé Weber synchronized test's **data** from Main", "text": "Cloé Weber synchronized test's **data** from Main", "expires_at": "2026-12-16T14:28:17.890467+00:00" } ``` ### `id` A unique `id` value to identify the activity itself. ### `*_at` `created_at`, `started_at`, `updated_at`, `cancelled_at`, `completed_at`, and `expires_at` are all timestamps in UTC. For when a given activity occurred, use `completed_at`. You can use these properties to calculate the duration of the activity. To calculate the timing for steps in the activity, see the [`timings` property](#timings). ### `parameters` The `parameters` property includes detailed information about what triggered the activity, such as the user, the impacted environment, the git commits, or the cron commands. The response changes based on the activity. ### `project` The ID of the project in which the activity took place. Use this value to distinguish multiple projects sent the same URL. Different from [`project` activities](#type). ### `type` The type of the activity in one of the following categories: - [Project](#project-activity-types) - [Environment](#environment-activity-types) - [Integration](#integration-activity-types) - [Maintenance](#maintenance-activity-types) #### `project` activity types Activities that happened on a given project. The following table presents the possible activity types: | Name | Description | |-----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `project.clear_build_cache` | The build cache is cleared. | | `project.create` | A new project is created. | | `project.metrics.enable` | A metric from the [continuous profiling](https://docs.upsun.com/increase-observability.md) has been enabled. | | `project.metrics.update` | A metric from the [continuous profiling](https://docs.upsun.com/increase-observability.md) has been updated. | | `project.metrics.disable` | A metric from the [continuous profiling](https://docs.upsun.com/increase-observability.md) has been disabled. | | `project.modify.title` | The project title has changed. | | `project.variable.create` | A new [project variable](https://docs.upsun.com/administration/web/configure-project.md#variables) has been created. The value is visible only if the variable is not [set as sensitive](https://docs.upsun.com../../development/variables/set-variables.md#variable-options). | | `project.variable.delete` | A [project variable](https://docs.upsun.com/administration/web/configure-project.md#variables) has been deleted. | | `project.variable.update` | A [project variable](https://docs.upsun.com/administration/web/configure-project.md#variables) has been modified. | #### `environment` activity types Activities that happened on an environment. The following table presents the possible activity types: | Name | Description | |--------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `environment.activate` | The environment has been made [active](https://docs.upsun.com/glossary.md#active-environment). | | `environment.backup` | A user triggered a [backup](https://docs.upsun.com/environments/backup.md). | | `environment.backup.delete` | A user deleted a [backup](https://docs.upsun.com/environments/backup.md). | | `environment.branch` | A [new branch](https://docs.upsun.com/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](https://docs.upsun.com/define-routes/https.md#certificate-renewals). | | `environment.cron` | A [cron job](https://docs.upsun.com/create-apps/image-properties/crons.md) has completed. | | `environment.deactivate` | An environment has been made [inactive](https://docs.upsun.com/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. | | `environment.domain.delete` | A [domain](administration/web/configure-project.md#domains) associated with the environment has been removed. | | `environment.domain.update` | A [domain](administration/web/configure-project.md#domains) associated with the environment has been updated, such as having its SSL certificate modified. | | `environment.initialize` | The [default branch](https://docs.upsun.com/environments.md#default-environment) of the project has just been initialized with its first commit. | | `environment.merge` | An environment was [merged](https://docs.upsun.com/glossary.md#merge) through the CLI, Console, or API. A basic Git merge doesn't trigger this activity. | | `environment.merge-pr` | A Pull Request/Merge Request was merged through the CLI, Console, or API. A basic Git merge doesn't trigger this activity. | | `environment.operation` | A [source operation](https://docs.upsun.com/create-apps/runtime-operations.md) has been triggered | | `environment.pause` | An environment has been [paused](https://docs.upsun.com/environments.md#pause-an-environment). | | `environment.push` | A user [pushed](https://docs.upsun.com/administration/cli/reference.md#environmentpush) code to a branch, either existing or new. | | `environment.redeploy` | An environment was [redeployed](https://docs.upsun.com/administration/cli/reference.md#environmentredeploy). | | `environment.restore` | A user restored a [backup](https://docs.upsun.com/environments/backup.md). | | `environment.resume` | An inactive environment was [resumed](https://docs.upsun.com/environments.md#resume-a-paused-environment) | | `environment.resources.update` | The resources allocated to the environment [have been updated](https://docs.upsun.com/manage-resources/adjust-resources.md). | | `environment.route.create` | A new [route](https://docs.upsun.com/administration/web/configure-environment.md#routes) has been created through the API. Edits made using Git to the `.upsun/config.yaml` file don't trigger this activity. | | `environment.route.delete` | A [route](https://docs.upsun.com/administration/web/configure-environment.md#routes) has been deleted through the API. Edits made using Git to the `.upsun/config.yaml` file don't trigger this activity. | | `environment.route.update` | A [route](https://docs.upsun.com/administration/web/configure-environment.md#routes) has been modified through the API. Edits made using Git to the `.upsun/config.yaml` file don't trigger this activity. | | `environment.source-operation` | A [source operation](https://docs.upsun.com/create-apps/source-operations.md) has been triggered. | | `environment.synchronize` | An environment has had its data and/or code replaced with the data and/or code from its parent environment. | | `environment.update.http_access` | [HTTP access rules](https://docs.upsun.com/administration/web/configure-environment.md#http-access-control) for an environment have been modified. | | `environment.update.restrict_robots` | The option to [hide from search engines](https://docs.upsun.com../../environments/search-engine-visibility.md) has been enabled or disabled for an environment. | | `environment.update.smtp` | Email sending has been enabled or disabled for an environment. | | `environment.variable.create` | A [new variable](https://docs.upsun.com/development/variables/set-variables.md#variable-options) has been created. The value is visible only if the variable is not [set as sensitive](https://docs.upsun.com../../development/variables/set-variables.md#variable-options). | | `environment.variable.delete` | A [variable](https://docs.upsun.com/development/variables/set-variables.md#variable-options) has been deleted. | | `environment.variable.update` | A [variable](https://docs.upsun.com/development/variables/set-variables.md#variable-options) has been modified. | | `environment_type.access.create` | A [new access](https://docs.upsun.com/administration/users.md#manage-project-access) has been added to the environment | | `environment_type.access.delete` | An [existing access](https://docs.upsun.com/administration/users.md#manage-project-access) to the environment has been deleted | | `environment_type.access.update` | An [existing access](https://docs.upsun.com/administration/users.md#manage-project-access) to the environment has been updated | #### `integration` activity types Activities that relate to an integration. The following table presents the possible activity types: | Name | Description | |-----------------------------------------------|-----------------------------------------------------------------------------------------------------------------------| | `integration.bitbucket.fetch` | A fetch has been triggered on your [Bitbucket Cloud](https://docs.upsun.com/integrations/source/bitbucket.md#bitbucket-cloud) repository. | | `integration.bitbucket.register_hooks` | An integration hook has been registered with [Bitbucket Cloud](https://docs.upsun.com/integrations/source/bitbucket.md#bitbucket-cloud). | | `integration.bitbucket_server.fetch` | A fetch has been triggered on your [Bitbucket Server](https://docs.upsun.com/integrations/source/bitbucket.md#bitbucket-server) repository. | | `integration.bitbucket_server.register_hooks` | An integration hook has been registered with [Bitbucket Server](https://docs.upsun.com/integrations/source/bitbucket.md#bitbucket-server). | | `integration.github.fetch` | A fetch has been triggered on your [GitHub](https://docs.upsun.com/integrations/source/github.md) repository. | | `integration.gitlab.fetch` | A fetch has been triggered on your [GitLab](https://docs.upsun.com/integrations/source/gitlab.md) repository. | | `integration.health.email` | A [health notification](https://docs.upsun.com../notifications.md) was sent by email. | | `integration.health.pagerduty` | A [health notification](https://docs.upsun.com../notifications.md) was sent to PagerDuty. | | `integration.health.slack` | A [health notification](https://docs.upsun.com../notifications.md) was sent to Slack. | | `integration.health.webhook` | A [health notification](https://docs.upsun.com../notifications.md) was sent to a webhook. | | `integration.script` | An [activity script](https://docs.upsun.com/integrations/activity.md) has been triggered. | | `integration.webhook` | A [webhook](https://docs.upsun.com/integrations/activity/webhooks.md) was triggered. | #### `maintenance` activity types Activities that relate to a maintenance. The following table presents the possible types: | Name | Description | |-----------------------|-----------------------------------------------------------| | `maintenance.upgrade` | An upgrade is triggered for API Server and Metrics Server | ### `environments` An array listing the environments that were involved in the activity. It's usually only a single value representing one environment. ### `state` The current state of the activity. Its value can be `pending`, `in_progress`, `complete`, `cancelled`, or `scheduled`. ### `completion_percent` What percentage of the activity is complete. ### `result` Whether or not the activity completed successfully. If it did, the value is `success`. Note that certain activities, such as deploy hooks, can be marked as successful activities even if some commands failed. ### `timings` The amount of time required by the activity. It can include the following properties: | Name | Description | |-----------|--------------------------------------------------------------| | `wait` | The delay if a command is set to wait before being executed. | | `build` | The execution time for the build hook. | | `deploy` | The execution time for the deploy hook. | | `execute` | The execution time for your script or cron job. | ### `log` A human-friendly record of what happened in the activity. The log shouldn't be parsed for data as its structure isn't guaranteed. ### `description` A short machine-readable description of the activity. ### `text` A short human-readable description of the activity. ### `payload` Contains settings and details related to the completed activity. Its content varies based on the activity type. | Name | Description | |-------------------------|---------------------------------------------------------------------------------------------------------------------------------| | `payload.user` | The user that triggered the activity. For details on its properties, see the [`user` payload](#user-payload). | | `payload.environment` | The environment affected by the activity. For details on its properties, see the [`environment` payload](#environment-payload). | | `payload.commits` | A list of changes with their Git metadata. | | `payload.commits_count` | The number of Git commits. | | `payload.deployment` | Information about the deployed environment. For details on its properties, see the [`deployment` payload](#deployment-payload). | | `payload.project` | Information about the project. For details on its properties, see the [`project` payload](#project-payload). | #### `user` payload Contains information about the Upsun user that triggered the activity. | Name | Description | |-----------------------------|---------------------------------------------| | `payload.user.created_at` | The date the user was created. | | `payload.user.display_name` | The user's name in a human-friendly format. | | `payload.user.id` | The user's ID. | | `payload.user.updated_at` | The date the user was last updated. | #### `environment` payload Contains information about the environment associated with the activity, including its settings, state, and deployment. The following table presents the most notable properties of the environment: | Name | Description | |-------------------------------------|---------------------------------------------------------------------------------------------| | `payload.environment.name` | The environment name. | | `payload.environment.type` | The [environment type](https://docs.upsun.com../../administration/users.md#environment-type-roles). | | `payload.environment.head_commit` | The ID of the environment's latest Git commit. | | `payload.environment.edge_hostname` | The URL you should target when setting up a [custom domain](https://docs.upsun.com../../domains/steps.md). | Different from [`environment` activities](#type). #### `project` payload Contains information about the project associated with the activity, including plan details, timezone, and region. The following table presents the most notable properties of the project: | Name | Description | |--------------------------------|-----------------------------------------------------------------------------------------| | `payload.project.timezone` | Your project's [timezone](https://docs.upsun.com../../projects/change-project-timezone.md). | | `payload.project.region` | Your project's [region](https://docs.upsun.com../../development/regions.md#regions). | | `payload.project.title` | Your project's name. | | `payload.project.subscription` | All of the details about your project's [plan](https://docs.upsun.com../../administration/pricing.md). | Different from [`project` activities](#type). #### `deployment` payload Contains information about the deployed environment, if one is associated with the activity. The following table presents the most notable properties of the deployment: | Name | Description | |--------------------------------|----------------------------------------------------------------------------------------------------------------------------------------| | `payload.deployment.routes` | All the URLs connected to the environment. The list includes redirects. To exclude redirects, find objects whose `type` is `upstream`. | | `payload.deployment.services` | All the services on your environment. | | `payload.deployment.variables` | All the [variables for the environment](https://docs.upsun.com../../development/variables.md). | The `payload.deployment` property includes the configuration extracted from the following sources: - Your [app configuration](https://docs.upsun.com../../create-apps.md) - Your [routes](https://docs.upsun.com../../define-routes.md) - Your [services](https://docs.upsun.com../../add-services.md) ## Maximum activities and parallelism Project activities are distributed across separate queues, which enables *two* simultaneous activities to occur in parallel across your environments. For a given environment, only one activity can run at a time. Those queues include the following types of activities: | Name | Description | |----------------|------------------------------------------------------------------------------------------------------| | `default` | The most common activities on repositories (pushes, merges) and environments (syncs, redeployments). | | `integrations` | Source and webhook integration activities. | | `backup` | Backup activities. | | `cron` | Cron activities. | Production activities are prioritized across all queues. When an activity for the production environment is triggered, it's placed at the top of the queue. This makes it unlikely that activities on preview environments block activities for the production environment for long, though there may be a temporary wait. ## Examples The response is often usually long, so the following examples are shortened using ellipses. Remember that the response differs depending on the activity and not all fields are always available. To test responses, [set up a webhook](https://docs.upsun.com/integrations/activity/webhooks.md#setup). ### Cron When a cron job is triggered, the activity contains all the [job's information](https://docs.upsun.com/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. To get details about the configured cron job, see the `parameters` property: ```json {no-copy="true"} ... "parameters": { "user": "admin", "cluster": "abcdefgh1234567-main-abcd123", "environment": "main", "application": "app", "cron": "saybye", "spec": { "spec": "5 * * * *", "commands": { "start": "sleep 60 && echo sleep-60-finished && date", "stop": null }, "shutdown_timeout": null, "timeout": 86400 } ... ``` The following example shows the full activity response to a cron job: ```json {no-copy="true"} { "id": "ypalrypnezbye", "_links": { "self": { "href": "https://eu-3.upsun.com/api/projects/abcdefgh1234567/activities/ypalrypnezbye" }, "log": { "href": "/api/projects/abcdefgh1234567/activities/ypalrypnezbye/log" } }, "created_at": "2026-12-13T16:06:08.081312+00:00", "updated_at": null, "type": "environment.cron", "parameters": { "user": "admin", "cluster": "abcdefgh1234567-main-abcd123", "environment": "main", "application": "app", "cron": "saybye", "spec": { "spec": "5 * * * *", "commands": { "start": "sleep 60 && echo sleep-60-finished && date", "stop": null }, "shutdown_timeout": null, "timeout": 86400 } }, "project": "abcdefgh1234567", "environments": [ "main" ], "state": "complete", "result": "success", "started_at": "2026-12-13T16:06:08.258090+00:00", "completed_at": "2026-12-13T16:07:09.658339+00:00", "completion_percent": 100, "cancelled_at": null, "timings": { "wait": 0, "execute": 61.244 }, "log": "hello world\nTue Jan 01 16:07:09 UTC 2026", "payload": { "user": { "id": "admin", "created_at": "2026-12-13T16:06:08.066085+00:00", "updated_at": null, "display_name": "Upsun Bot" }, "project": { "id": "abcdefgh1234567", "created_at": "2026-03-22T15:47:28.739099+00:00", "updated_at": "2026-12-01T09:42:19.860188+00:00", "attributes": {}, "title": "php-test", "description": "", "owner": "c9926428-44dc-4b10-be03-a26dd43b44c1", "namespace": "upsun", "organization": "01FF4NBNVMMDWP1NVK0G4EGJW0", "default_branch": "main", "status": { "code": "provisioned", "message": "ok" }, "timezone": "Europe/Dublin", "region": "eu-3.upsun.com", "repository": { "url": "abcdefgh1234567@git.eu-3.upsun.com:abcdefgh1234567.git", "client_ssh_key": "ssh-rsa aaaaaaabbbbbbbcccccccddddddd abcdefgh1234567@upsun" }, "default_domain": null, "subscription": { "license_uri": "https://accounts.upsun.com/api/v1/licenses/2291467", "plan": "development", "environments": 3, "storage": 5120, "included_users": 1, "subscription_management_uri": "https://console.upsun.com-/users/abcd12345/billing/plan/12345678", "restricted": false, "suspended": false, "user_licenses": 1 } }, "environment": { "id": "main", "created_at": "2026-03-22T15:47:43.750880+00:00", "updated_at": "2026-11-29T16:16:37.085719+00:00", "name": "main", "machine_name": "main-abcd123", "title": "Main", "attributes": {}, "type": "production", "parent": null, "default_domain": null, "clone_parent_on_create": true, "deployment_target": "local", "is_pr": false, "status": "active", "enable_smtp": true, "restrict_robots": true, "edge_hostname": "main-abcd123-abcdefgh1234567.eu-3.platformsh.site", "deployment_state": { "last_deployment_successful": true, "last_deployment_at": "2026-11-29T16:16:37.085609+00:00", "crons": { "enabled": true, "status": "running" } }, "resources_overrides": {}, "last_active_at": "2026-12-13T15:07:10.862854+00:00", "last_backup_at": null, "project": "abcdefgh1234567", "is_main": true, "is_dirty": false, "has_code": true, "head_commit": "6aac318907b50252976c47e4e62ed95d438af0ea", "merge_info": { "commits_ahead": 0, "commits_behind": 0, "parent_ref": null }, "has_deployment": true }, "cron": "saybye" }, "description": "Upsun Bot ran cron **saybye**", "text": "Upsun Bot ran cron **saybye**", "expires_at": "2026-01-12T16:06:08.081293+00:00" } ``` ### Push A push activity contains several properties. The `commits` property contains everything related to the Git push that triggered the activity: ```json {no-copy="true"} ... "commits": [ { "sha": "2bab04e050279ac078d5d34016f5dd9c466e948d", "author": { "email": "cloeweber@example.com", "name": "Cloé Weber", "date": 1671032461 }, "parents": [ "6aac318907b50252976c47e4e62ed95d438af0ea" ], "message": "Add cron" } ], ... ``` The `environment` property contains the settings for the environment that was pushed to: ```json {no-copy="true"} ... "environment": { "id": "main", "created_at": "2026-03-22T15:47:43.750880+00:00", "updated_at": "2026-11-29T16:16:37.085719+00:00", "name": "main", "machine_name": "main-abcd123", "title": "Main", "attributes": {}, "type": "production", "parent": null, "default_domain": null, "clone_parent_on_create": true, "deployment_target": "local", "is_pr": false, "status": "active", "enable_smtp": true, "restrict_robots": true, "edge_hostname": "main-abcd123-abcdefgh1234567.eu-3.platformsh.site", "deployment_state": { "last_deployment_successful": true, "last_deployment_at": "2026-11-29T16:16:37.085609+00:00", "crons": { "enabled": true, "status": "sleeping" } }, "resources_overrides": {}, "last_active_at": "2026-12-13T16:07:09.788910+00:00", "last_backup_at": null, "project": "abcdefgh1234567", "is_main": true, "is_dirty": false, "has_code": true, "head_commit": "6aac318907b50252976c47e4e62ed95d438af0ea", "merge_info": { "commits_ahead": 0, "commits_behind": 0, "parent_ref": null }, "has_deployment": true }, ... ``` The `deployment` property contains the settings for the deployment, including the [image type](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#types) and [resource allocation](https://docs.upsun.com/manage-resources/adjust-resources.md). The following example shows a shortened excerpt of the `deployment` property: ```json {no-copy="true"} ... "deployment": { "id": "current", "created_at": "2026-03-22T15:48:05.396979+00:00", "updated_at": "2026-12-14T15:41:57.264813+00:00", "cluster_name": "abcdefgh1234567-main-abcd123", "project_info": { "deployment": { "id": "current", "created_at": "2026-03-22T15:48:05.396979+00:00", "updated_at": "2026-12-14T15:41:57.264813+00:00", "cluster_name": "abcdefgh1234567-main-abcd123", "project_info": { "name": "abcdefgh1234567", "settings": { "initialize": { "values": { "initialize": true, "start": false, "base": { "files": [], "profile": "PHP", "config": null, "repository": "https://github.com/platformsh-templates/php.git@master", "title": "PHP" } } }, ... "application_config_file": ".upsun/config.yaml", "project_config_dir": ".upsun", ... "development_service_size": "S", "development_application_size": "S", "enable_certificate_provisioning": true, "certificate_style": "ecdsa", "certificate_renewal_activity": true, ... "cron_minimum_interval": 5, "cron_maximum_jitter": 20, "concurrency_limits": { "internal": null, "integration": 4, "backup": 2, "cron": 10, "default": 2 }, ... "build_resources": { "cpu": 1, "memory": 2048 }, ... "max_allowed_routes": 50000, "max_allowed_redirects_paths": 50000, "enable_incremental_backups": true, ... } }, ... ``` The following example shows the full activity response to a Git push: ```json {no-copy="true"} { "id": "a1kz6ffxui7em", "_links": { "self": { "href": "https://eu-3.upsun.com/api/projects/abcdefgh1234567/activities/a1kz6ffxui7em" }, "log": { "href": "/api/projects/abcdefgh1234567/activities/a1kz6ffxui7em/log" } }, "created_at": "2026-12-14T15:41:05.821145+00:00", "updated_at": null, "type": "environment.push", "parameters": { "user": "c9926428-44dc-4b10-be03-a26dd43b44c1", "environment": "main", "old_commit": "6aac318907b50252976c47e4e62ed95d438af0ea", "new_commit": "2bab04e050279ac078d5d34016f5dd9c466e948d" }, "project": "abcdefgh1234567", "environments": [ "main" ], "state": "complete", "result": "success", "started_at": "2026-12-14T15:41:05.969872+00:00", "completed_at": "2026-12-14T15:41:57.635442+00:00", "completion_percent": 100, "cancelled_at": null, "timings": { "wait": 0, "parse_commits": 0.63, "build": 0.506, "deploy": 49.954, "execute": 51.516 }, "log": "Found 1 new commit\n\nBuilding application 'myapp' (runtime type: php:8.5, tree: 9851a01)\n Reusing existing build for this tree ID\n\nProvisioning certificates\n Certificates\n - certificate 5093946: expiring on 2026-02-23 11:09:20+00:00, covering {,www}.main-abcd123-abcdefgh1234567.eu-3.platformsh.site\n\n\nRedeploying environment main\n Preparing deployment\n Closing service myapp\n Opening application myapp and its relationships\n Executing deploy hook for application myapp\n hello world\n\n Opening environment\n Environment configuration\n myapp (type: php:8.5, size: S, disk: 2048)\n\n Environment routes\n http://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/ redirects to https://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/\n http://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/ redirects to https://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/\n https://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/ is served by application `myapp`\n https://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/ redirects to https://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/\n", "payload": { "user": { "id": "c9926428-44dc-4b10-be03-a26dd43b44c1", "created_at": "2026-12-14T15:40:16.891889+00:00", "updated_at": null, "display_name": "Cloé Weber" }, "environment": { "id": "main", "created_at": "2026-03-22T15:47:43.750880+00:00", "updated_at": "2026-11-29T16:16:37.085719+00:00", "name": "main", "machine_name": "main-abcd123", "title": "Main", "attributes": {}, "type": "production", "parent": null, "default_domain": null, "clone_parent_on_create": true, "deployment_target": "local", "is_pr": false, "status": "active", "enable_smtp": true, "restrict_robots": true, "edge_hostname": "main-abcd123-abcdefgh1234567.eu-3.platformsh.site", "deployment_state": { "last_deployment_successful": true, "last_deployment_at": "2026-11-29T16:16:37.085609+00:00", "crons": { "enabled": true, "status": "sleeping" } }, "resources_overrides": {}, "last_active_at": "2026-12-13T16:07:09.788910+00:00", "last_backup_at": null, "project": "abcdefgh1234567", "is_main": true, "is_dirty": false, "has_code": true, "head_commit": "6aac318907b50252976c47e4e62ed95d438af0ea", "merge_info": { "commits_ahead": 0, "commits_behind": 0, "parent_ref": null }, "has_deployment": true }, "commits": [ { "sha": "2bab04e050279ac078d5d34016f5dd9c466e948d", "author": { "email": "cloeweber@example.com", "name": "Cloé Weber", "date": 1671032461 }, "parents": [ "6aac318907b50252976c47e4e62ed95d438af0ea" ], "message": "Add cron" } ], "commits_count": 1, "deployment": { "id": "current", "created_at": "2026-03-22T15:48:05.396979+00:00", "updated_at": "2026-12-14T15:41:57.264813+00:00", "cluster_name": "abcdefgh1234567-main-abcd123", "project_info": { "name": "abcdefgh1234567", "settings": { "initialize": { "values": { "initialize": true, "start": false, "base": { "files": [], "profile": "PHP", "config": null, "repository": "https://github.com/platformsh-templates/php.git@master", "title": "PHP" } } }, "product_name": "Upsun", "product_code": "upsun", "variables_prefix": "PLATFORM_", "bot_email": "bot@upsun.com", "application_config_file": ".upsun/config.yaml", "project_config_dir": ".upsun", "use_drupal_defaults": false, "use_legacy_subdomains": false, "development_service_size": "S", "development_application_size": "S", "enable_certificate_provisioning": true, "certificate_style": "ecdsa", "certificate_renewal_activity": true, "development_domain_template": null, "enable_state_api_deployments": true, "temporary_disk_size": null, "cron_minimum_interval": 5, "cron_maximum_jitter": 20, "concurrency_limits": { "internal": null, "integration": 4, "backup": 2, "cron": 10, "default": 2 }, "flexible_build_cache": false, "strict_configuration": true, "has_sleepy_crons": true, "crons_in_git": true, "custom_error_template": null, "app_error_page_template": null, "environment_name_strategy": "name-and-hash", "data_retention": null, "enable_codesource_integration_push": true, "enforce_mfa": false, "systemd": true, "router_gen2": false, "chorus": { "enabled": true, "exposed": true }, "build_resources": { "cpu": 1, "memory": 2048 }, "outbound_restrictions_default_policy": "allow", "self_upgrade": true, "additional_hosts": {}, "max_allowed_routes": 50000, "max_allowed_redirects_paths": 50000, "enable_incremental_backups": true, "sizing_api_enabled": false, "enable_cache_grace_period": true, "enable_zero_downtime_deployments": false, "enable_admin_agent": true, "certifier_url": "https://docs.upsun.com/api/", "centralized_permissions": false, "glue_server_max_request_size": 10 } }, "environment_info": { "name": "main", "is_main": true, "is_production": false, "reference": "refs/heads/main", "machine_name": "main-abcd123", "environment_type": "production" }, "deployment_target": "local", "vpn": null, "http_access": { "is_enabled": true, "addresses": [], "basic_auth": {} }, "enable_smtp": true, "restrict_robots": true, "variables": [ { "name": "php:memory_limit", "value": "512M", "is_sensitive": false } ], "access": [ { "entity_id": "c9926428-44dc-4b10-be03-a26dd43b44c1", "role": "admin" } ], "subscription": { "license_uri": "https://accounts.upsun.com/api/v1/licenses/12345678", "plan": "development", "environments": 3, "storage": 5120, "included_users": 1, "subscription_management_uri": "https://console.upsun.com//-/users/abcd12345/billing/plan/12345678", "restricted": false, "suspended": false, "user_licenses": 1 }, "services": {}, "routes": { "https://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/": { "primary": true, "id": null, "production_url": "https://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/", "attributes": {}, "type": "upstream", "tls": { "strict_transport_security": { "enabled": null, "include_subdomains": null, "preload": null }, "min_version": null, "client_authentication": null, "client_certificate_authorities": [] }, "original_url": "https://{default}/", "restrict_robots": true, "cache": { "enabled": true, "default_ttl": 0, "cookies": [ "*" ], "headers": [ "Accept", "Accept-Language" ] }, "ssi": { "enabled": false }, "upstream": "myapp:http", "redirects": { "expires": "-1s", "paths": {} } }, "https://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/": { "primary": false, "id": null, "production_url": "https://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/", "attributes": {}, "type": "redirect", "tls": { "strict_transport_security": { "enabled": null, "include_subdomains": null, "preload": null }, "min_version": null, "client_authentication": null, "client_certificate_authorities": [] }, "original_url": "https://www.{default}/", "restrict_robots": true, "to": "https://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/", "redirects": { "expires": "-1s", "paths": {} } }, "http://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/": { "primary": false, "id": null, "production_url": "http://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/", "attributes": {}, "type": "redirect", "tls": { "strict_transport_security": { "enabled": null, "include_subdomains": null, "preload": null }, "min_version": null, "client_authentication": null, "client_certificate_authorities": [] }, "original_url": "http://{default}/", "restrict_robots": true, "to": "https://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/", "redirects": { "expires": "-1s", "paths": {} } }, "http://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/": { "primary": false, "id": null, "production_url": "http://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/", "attributes": {}, "type": "redirect", "tls": { "strict_transport_security": { "enabled": null, "include_subdomains": null, "preload": null }, "min_version": null, "client_authentication": null, "client_certificate_authorities": [] }, "original_url": "http://www.{default}/", "restrict_robots": true, "to": "https://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/", "redirects": { "expires": "-1s", "paths": {} } } }, "webapps": { "app": { "resources": null, "size": "AUTO", "disk": 2048, "access": { "ssh": "contributor" }, "relationships": {}, "additional_hosts": {}, "mounts": { "/web/uploads": { "source": "local", "source_path": "uploads" }, "/private": { "source": "local", "source_path": "private" } }, "timezone": null, "variables": {}, "firewall": null, "initial_size": null, "container_profile": null, "instance_count": null, "name": "app", "type": "php:8.5", "runtime": {}, "preflight": { "enabled": true, "ignored_rules": [] }, "tree_id": "9851a01081f3c2f943f75f62c38b67f8bc0ec15c", "slug_id": "abcdefgh1234567-app-9851a01081f3c2f943f75f62c38b67f8bc0ec15c-73985064e66fd2299f4b83931cff46891249a964", "app_dir": "/app", "web": { "locations": { "/": { "root": "web", "expires": "-1s", "passthru": "/index.php", "scripts": true, "allow": true, "headers": {}, "rules": {} } }, "move_to_root": false }, "hooks": { "build": "set -e\n", "deploy": "set -e\n", "post_deploy": null }, "crons": { "saybye": { "spec": "5 * * * *", "commands": { "start": "sleep 60 && echo sleep-60-finished && date", "stop": null }, "shutdown_timeout": null, "timeout": 86400 } } } }, "workers": {}, } } }, "description": "Cloé Weber pushed to Main", "text": "Cloé Weber pushed to Main", "expires_at": "2026-12-14T15:41:05.821145+00:00" } ``` --- # Source: https://docs.upsun.com/projects/region-migration.md # Change a project's region To host your project data, Upsun offers several [regions](https://docs.upsun.com../development/regions.md). You specify a region when you create a project. You can also change the project's region after it's created. ## Why migrate between regions - Different data centers are located in different geographic areas. You may want your site close to your users for improved performance. - You may want to move to a region with a lower [environmental impact](https://docs.upsun.com../development/regions.md#environmental-impact). ## 1. Plan the migration Before starting the migration process, you need to plan for it: - Plan a time frame in which to handle the migration. Your code shouldn't change during this time to ensure all changes are copied to the new project. Prepare for a brief site outage when you migrate, just as with a relaunch of a site. - Set your DNS Time-to-Live as low as possible. This ensures the switch to the new site propagates as quickly as possible. ## 2. Create a new project In the target region, [create a new project from scratch]( https://console.upsun.com/org/create-project/info?_utm_campaign=cta_deploy_marketplace_template&utm_source=public_documentation&_utm_medium=organic ). If you plan to test for long, start with the least amount of resources on the project and then upsize it before switching the DNS. ## 3. Add code and environments Select your newly created blank project. - Push the code for your production branch: ```bash {} upsun push --target ``` - (Optional) Checkout other branches and then push their code: ```bash {} upsun push --activate --target --parent ``` For a [source integration](https://docs.upsun.com/integrations/source.md) with GitHub, BitBucket, or GitLab, add the integration to your new project. Your new project then mirrors the configured repository automatically. ## 4. Copy files If you have files in a mount, first download them: ```bash upsun mount:download ``` Then upload them to your new project: ```bash upsun mount:upload ``` See more options on [how to export files](https://docs.upsun.com/learn/tutorials/exporting.md) and [how to import files](https://docs.upsun.com/learn/tutorials/migrating/from-fixed.md#6-import-data). ## 5. Copy data from services For services with generated data such as Solr and Redis, you don't need to copy data directly. Just rebuild the data in the new project. To download data from persistent services such as databases, see how to export and then import data for each service: - [InfluxDB](https://docs.upsun.com../add-services/influxdb.md#export-data) - [MongoDB](https://docs.upsun.com../add-services/mongodb.md#exporting-data) - [MariaDB/MySQL](https://docs.upsun.com../add-services/mysql.md#exporting-data) - [PostgreSQL](https://docs.upsun.com../add-services/postgresql.md#exporting-data) ## 6. Migrate variables and project settings Make sure anything else connected to your old project is moved to your new project: - If you have project or environment variables defined on your old project, add them to your new project. Get a list of all variables set outside of code by running `upsun variables`. - Add any users to your new project that you want to continue to have access. - Add any existing [integrations](https://docs.upsun.com../integrations.md). ## 7. Test the site Verify that the new site is working as desired before continuing. You can leave the two projects running for as long as you need. After you have finished all your testing, sync all your data (code, files, database) for the last time. ## 8. Switch to the new site Now that you know the new project works, switch public traffic to that site: 1. Make sure your new project has the [necessary resources](https://docs.upsun.com/manage-resources/adjust-resources.md). 2. If possible, put your site into read-only mode or maintenance mode. 3. Add your domain names to your new project and remove them from the old project. 4. (Optional) Add any custom SSL certificates you have. 5. Update your DNS provider's records to point to the new site. See more on [setting custom domains](https://docs.upsun.com../domains/steps.md). It may take some time for the DNS change and SSL change to propagate. Until it does, some browsers may not see the new site or may get an SSL mismatch error. In most cases that resolves itself in 1--3 hours. ## 9. Remove the old project Once the new project is running and the DNS has fully propagated, delete the old project. ## Alternative process We have open-sourced [the Upsun cloning tool](https://github.com/upsun/clonsun), which allows you to clone a project from one region to another. This cloning tool helps you migrate most of your project assets from one region to another with some remaining manual steps like moving your domain names from one region to the other (or at the CDN level) and update your DNS records. We also have [the Upsun converting tool](https://github.com/upsun/convsun), which allows you to change existing configuration files to another format. It converts details from files like `services.yaml` and `routes.yaml`, and generates a new `config.yaml` file. This streamlines the conversion process by significantly reducing the manual effort required to adapt your app’s infrastructure setup. **Note**: To learn more about the converter tool and how it works, read the [converting projects](https://docs.upsun.com/learn/tutorials/migrating/from-fixed.md) page. Although not directly supported by Upsun, an agency named [Contextual Code](https://www.contextualcode.com/) has built a bash migration script. This script automates most common configurations. If your site is a typical single app with a single SQL database, the script should take care of most of the process for you. See more at the [Upsun Project Migration repository](https://gitlab.com/contextualcode/platformsh-migration). --- # Source: https://docs.upsun.com/development/regions.md # Regions Upsun offers several regions for hosting project data. You can choose a region based on criteria such as its closeness to your users and its environmental impact. ## Environmental impact Whenever you create a project with us, we provide information about the electricity grid provider for that region. You can view the average carbon intensity of the energy grid in grams of CO2 equivalent per kilowatt-hour. These data are sourced from an annual average, which we update as new information becomes available. If you want to see real-time emissions generated by each power grid, we recommend checking out [Electricity Maps](https://app.electricitymap.org/map). You can also access a public GitHub page of Electricity Maps [data sources](https://github.com/electricitymap/electricitymap-contrib/blob/master/DATA_SOURCES.md). Summary of data being used in Upsun’s Region Picker when creating a new Project: | Source | Last update of this page | Previous versions of this page | |--------|--------------------------|--------------------------------| | Electricity Maps 2022 annual averages (previous to May 2023, we had used annual averages from the IEA).
See our [blog post](https://devcenter.upsun.com/posts/platformsh-is-now-using-annual-carbon-intensities-from-electricity-maps/) for more information.| 11 May 2023 | Available [here](https://github.com/platformsh/platformsh-docs/commits/main/docs/src/development/regions.md) | Information on carbon intensity is also available in the Upsun API. For example, to get a list of the regions and their carbon intensities, run the following command: ```bash upsun api:curl regions | jq -r '.regions[] | select(.available != false) | "\(.label): \(.environmental_impact.carbon_intensity)"' ``` See all available information in the [API documentation](https://api.platform.sh/docs/#tag/Regions). ### Carbon Emissions dashboard The Carbon Emissions dashboard provides an overview of the carbon footprint associated with your cloud resource usage. This dashboard calculates emissions using a Carbon Price List (CPL) methodology, inspired by the Cloud Carbon Footprint model. Users can view total emissions over time and project specific emissions for the current year, broken down by kilograms of CO2 equivalent (kg CO2e). The dashboard also includes information about how emissions are calculated and what factors (server location, usage etc.) can influence those totals. #### Access the dashboard This dashboard is accessible via the Emissions tab within the Billing section in Console. #### How is this calculated? We collect detailed billing data from our cloud service providers (including associated costs and quantities) and this information is represented as line items. Our carbon management partner, Greenly, calculates the energy use and embodied emissions for each line item. This is done through data gathering and modeling that estimates energy consumption, power usage effectiveness (PUE), and carbon intensity for the cloud providers. Using cost allocation models, your project’s share of emissions is then estimated. We have been working closely with Greenly to build upon the model, tailoring it to better reflect our specific data and technical requirements to ensure your emissions data is credible, compliant and supports your progress toward real, measurable sustainability targets. **Note**: [OVH](https://docs.upsun.com/development/regions.md#france-fr-3-fr-3) region data is not available in this dashboard. #### What affects emissions? - **Where you run:** Data center regions vary greatly in grid-carbon intensity. Selecting a cleaner region is the most impactful way to reduce footprint. - **What you provision:** Emissions rise in proportion to the resources you allocate. **Note**: Optimizing code or app performance reduces emissions only if it leads to lower resource allocation. ### Greener Region Discount You can get a 3% discount on your resource usage if you host your project in one of Upsun's eco-friendly regions: - Quebec, Canada (`ca-central-1`), - Stockholm, Sweden (`eu-north-1`), - Paris, France (`francecentral`), - OVH (`gra7`), - Quincy, Washington (`westus2`), - Zurich, Switzerland (`europe-west6`). The 3% discount covers application CPU, application memory, service CPU, service memory, and build resources. It **doesn’t** apply to the project fee or other billing aspects. It can be combined with other offers or discounts. See [more information on the greener region discount](https://upsun.com/blog/announcing-greener-region-discount/). ## Region availability The regions listed here may be different from those available to you when you create a new project. Each organization can have its own rules for what regions to allow. When adding a new project, you only see regions allowed by your organization. ## Region location | Name | Provider | Geographic Zone | Timezone | | ------- | ------ | ------------------ |------------------|-----------------------| | au-2.platform.sh | Azure | Australia | Australia/Sydney | | au.platform.sh | AWS | Australia | Australia/Sydney | | bnpp-1.platform.sh | none | | UTC | | ca-1.platform.sh | AWS | North America | America/Toronto | | ch-1.platform.sh | Google | Europe | Europe/Zurich | | de-2.platform.sh | Google | Europe | Europe/Berlin | | eu-5.platform.sh | AWS | Europe | Europe/Stockholm | | eu.platform.sh | AWS | Europe | Europe/Dublin | | fr-3.platform.sh | OVH | Europe | Europe/Paris | | fr-4.platform.sh | Azure | Europe | Europe/Paris | | uk-1.platform.sh | Google | Europe | Europe/London | | us-2.platform.sh | AWS | North America | America/New_York | | us-3.platform.sh | Azure | North America | America/Los_Angeles | | us-4.platform.sh | Google | North America | America/New_York | | us.platform.sh | AWS | North America | America/New_York | **Note**: As an alternative, you can also use the following command with the Upsun CLI to find out where a given region is hosted: ```bash {} upsun api:curl regions | jq '.regions[] | select(.available) | .id + ": " + .provider.name + " - " + .zone + " - " + .timezone' | sort ``` The returned list contains, for each available region, its name, provider, geographic zone and its timezone - as shown above. ## Public IP addresses The public IP addresses for regions are stable, but not guaranteed to never change. Before any change, you are notified well in advance regarding affected projects. They're useful for cases such as when you have a corporate firewall that blocks outgoing SSH connections. In such cases, add the inbound IP addresses for your region to your allow list. ## Regions ### Europe Region | Provider | Available to new orgs | Outbound IPs | Inbound IPs | Region #### [Switzerland (ch-1)](#switzerland-ch-1-ch-1) ch-1.upsun.com Provider Google Cloud Platform Available to new orgs ✅ Outbound ips - 34.65.197.163 - 34.65.144.16 - 34.65.72.28 Inbound ips ``gw.ch-1.platformsh.site`` - 34.65.236.213 - 34.65.152.61 - 34.65.244.185 Region #### [Germany (de-2)](#germany-de-2-de-2) de-2.upsun.com Provider Google Cloud Platform Available to new orgs ✅ Outbound ips - 34.159.207.210 - 34.159.181.149 - 34.107.79.7 Inbound ips ``gw.de-2.platformsh.site`` - 35.246.248.138 - 35.246.184.45 - 35.242.229.239 Region #### [Ireland (eu)](#ireland-eu-eu) eu.upsun.com Provider AWS Available to new orgs ✅ Outbound ips - 54.72.94.105 - 54.76.137.67 - 54.76.137.94 Inbound ips ``gw.eu.platformsh.site`` - 54.76.137.79 - 54.76.136.188 - 54.76.137.151 Region #### [Sweden (eu-5)](#sweden-eu-5-eu-5) eu-5.upsun.com Provider AWS Available to new orgs ✅ Outbound ips - 13.48.116.14 - 13.51.46.87 - 13.48.202.56 Inbound ips ``gw.eu-5.platformsh.site`` - 13.51.62.86 Region #### [France (fr-3)](#france-fr-3-fr-3) fr-3.upsun.com Provider OVHcloud Available to new orgs ✅ Outbound ips - 135.125.91.125 - 135.125.89.47 - 135.125.90.255 Inbound ips ``gw.fr-3.platformsh.site`` - 94.23.123.122 Region #### [France (fr-4)](#france-fr-4-fr-4) fr-4.upsun.com Provider Azure Available to new orgs ✅ Outbound ips - 20.188.46.156 - 20.188.46.158 - 20.188.46.165 Inbound ips ``gw.fr-4.platformsh.site`` - 20.74.41.190 - 20.74.41.218 - 20.74.42.30 Region #### [United Kingdom (uk-1)](#united-kingdom-uk-1-uk-1) uk-1.upsun.com Provider Google Cloud Platform Available to new orgs ✅ Outbound ips - 35.246.36.142 - 34.147.217.161 - 34.89.33.176 Inbound ips ``gw.uk-1.platformsh.site`` - 35.242.142.110 - 35.189.126.202 - 35.242.183.249 - 34.147.168.147 Region #### [Ireland (eu-2)](#ireland-eu-2-eu-2) eu-2.upsun.com Provider AWS Available to new orgs Outbound ips - 52.208.123.9 - 52.214.63.84 - 52.30.200.164 Inbound ips ``gw.eu-2.platformsh.site`` - 34.248.104.12 - 34.241.191.143 - 52.210.208.94 Region #### [Ireland (eu-4)](#ireland-eu-4-eu-4) eu-4.upsun.com Provider AWS Available to new orgs Outbound ips - 18.200.158.188 - 18.200.157.200 - 18.200.184.206 Inbound ips ``gw.eu-4.platformsh.site`` - 52.215.88.119 - 52.208.179.40 - 18.200.179.139 ### United States Region | Provider | Available to new orgs | Outbound IPs | Inbound IPs | Region #### [East (us)](#east-us-us) us.upsun.com Provider AWS Available to new orgs ✅ Outbound ips - 54.88.149.31 - 54.209.114.37 - 54.210.53.51 Inbound ips ``gw.us.platformsh.site`` - 54.210.49.244 - 54.88.225.116 - 54.210.55.162 Region #### [East (us-2)](#east-us-2-us-2) us-2.upsun.com Provider AWS Available to new orgs ✅ Outbound ips - 34.238.64.193 - 52.4.246.137 - 54.157.66.30 Inbound ips ``gw.us-2.platformsh.site`` - 34.226.46.235 - 34.238.11.122 - 54.89.106.200 Region #### [West (us-3)](#west-us-3-us-3) us-3.upsun.com Provider Azure Available to new orgs ✅ Outbound ips - 52.148.128.255 - 52.250.13.106 - 40.91.69.215 Inbound ips ``gw.us-3.platformsh.site`` - 52.137.90.183 - 52.156.93.30 - 51.143.107.76 Region #### [East (us-4)](#east-us-4-us-4) us-4.upsun.com Provider Google Cloud Platform Available to new orgs ✅ Outbound ips - 104.196.203.234 - 34.148.171.57 - 35.243.131.172 Inbound ips ``gw.us-4.platformsh.site`` - 34.73.189.215 - 34.74.8.155 - 34.75.104.115 ### Canada Region | Provider | Available to new orgs | Outbound IPs | Inbound IPs | Region #### [Canada (ca-1)](#canada-ca-1-ca-1) ca-1.upsun.com Provider AWS Available to new orgs ✅ Outbound ips - 35.182.24.224 - 52.60.213.255 - 35.182.220.113 Inbound ips ``gw.ca-1.platformsh.site`` - 35.182.174.169 - 35.182.59.77 - 52.60.219.22 ### Australia Region | Provider | Available to new orgs | Outbound IPs | Inbound IPs | Region #### [Australia (au)](#australia-au-au) au.upsun.com Provider AWS Available to new orgs ✅ Outbound ips - 13.55.135.0 - 13.54.121.225 - 13.55.215.151 Inbound ips ``gw.au.platformsh.site`` - 13.54.88.239 - 13.55.140.143 - 13.54.222.56 Region #### [Australia (au-2)](#australia-au-2-au-2) au-2.upsun.com Provider Azure Available to new orgs ✅ Outbound ips - 104.210.116.116 - 40.126.245.226 - 104.210.117.92 Inbound ips ``gw.au-2.platformsh.site`` - 20.92.240.74 - 20.191.224.199 - 20.92.240.236 **Historic changes**: On March 17, 2025, the outbound IP addresses for regions running on Google Cloud Platform and Microsoft Azure services were changed. This change was made to separate the inbound and outbound IP addresses for these regions. If you have external services relying on outbound IP whitelisting from your Upsun project, you should update your external whitelists to reflect this change. Please see the relevant region information above for the new regional outbound IP addresses. --- # Source: https://docs.upsun.com/create-apps/multi-app/relationships.md # Source: https://docs.upsun.com/create-apps/image-properties/relationships.md # relationships A dictionary of relationships that defines the connections to other services and apps. Optional in [single-runtime](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](https://docs.upsun.com/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](https://docs.upsun.com/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](https://docs.upsun.com/create-apps/multi-app/relationships.md). **Availability**: 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” Upsun configuration noted at the bottom of this section. To define a relationship between your app and a service: ```yaml {} applications: : # ... relationships: : ``` The ``SERVICE_NAME`` is the name of the service as defined in its [configuration](https://docs.upsun.com/add-services.md). It is used as the relationship name, and associated with a ``null`` value. This instructs Upsun to use the service’s default endpoint to connect your app to the service. For example, if you define the following configuration: .upsun/config.yaml ```yaml {} applications: : # ... relationships: mariadb: ``` Upsun looks for a service named ``mariadb`` in your ``.upsun/config.yaml`` 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: .upsun/config.yaml ```yaml {} applications: : # ... relationships: mariadb: service: mariadb endpoint: mysql ``` You can define any number of relationships in this way: .upsun/config.yaml ```yaml {} applications: : # ... relationships: mariadb: redis: elasticsearch: ``` **Tip**: An even quicker way to define many relationships is to use the following single-line configuration: .upsun/config.yaml ```yaml {} applications: : # ... relationships: {, , } services: : type: mariadb:11.8 : type: redis:8.0 : type: elasticsearch:7.10 ``` Use the following configuration: .upsun/config.yaml ```yaml {} applications: : # ... relationships: : service: endpoint: ``` - ``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](https://docs.upsun.com/add-services.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: .upsun/config.yaml ```yaml {} applications: : # ... 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](https://docs.upsun.com/add-services/mysql.md#multiple-databases) (multiple databases and permissions) - [PostgreSQL](https://docs.upsun.com/add-services/postgresql.md#multiple-databases) (multiple databases and permissions) - [Redis](https://docs.upsun.com/add-services/redis.md#multiple-databases) (multiple databases) - [Solr](https://docs.upsun.com/add-services/solr.md#solr-6-and-later) (multiple cores) - [Vault KMS](https://docs.upsun.com/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: .upsun/config.yaml ```yaml {} applications: : # ... relationships: database1: service: mariadb endpoint: admin database2: service: mariadb endpoint: legacy cache: service: redis search: service: elasticsearch ``` **Legacy**: The following legacy syntax for specifying relationships is still supported by Upsun: .upsun/config.yaml ```yaml {} applications: : # ... relationships: : ":" services: SERVICE_NAME_A: type: mariadb:11.8 ``` For example: ```yaml {} applications: : # ... relationships: database: "db:mysql" services: db: type: mariadb:11.8 ``` Feel free to use this until the default and explicit endpoint syntax is supported on all images. --- # Source: https://docs.upsun.com/request-features.md # Request features We’re always open to new and fresh ideas that can help improve our product. Learn how to make a feature request and engage with the Upsun community here. ## How to submit a feature request If you'd like to submit a feature request, there are two ways for you to do so: ### If you already have an Upsun account You can open a [support ticket](https://docs.upsun.com/learn/overview/get-support.md) directly from [your Console](https://console.upsun.com/). Simply describe your needs and our team will take it from there. ### For non-account holders or those who prefer a chat Join us on our Discord server! We have a dedicated [feedback channel](https://discord.com/channels/1121795479785721957/1130486723630088272) where you can share your ideas and discuss them with our community and team members. **We love to hear from you!**: Your input helps us make our platform even better. Thank you for contributing. --- # Source: https://docs.upsun.com/environments/restore.md # Restore an environment from a backup Once you have [backups of your environment](https://docs.upsun.com/environments/backup.md), you can restore data from a previous point. To restore an environment, you need an [Admin role for that environment type](https://docs.upsun.com../administration/users.md). ## 1. List available backups To restore an environment, first select one of the available backups: You get a response similar to the following: ```bash {} Backups on the project My Project (1234567abcdef), environment main (type: production): +---------------------------+----------------------------+------------+ | Created | Backup ID | Restorable | +---------------------------+----------------------------+------------+ | 2026-08-15T09:48:58+01:00 | 5ouvtgo4v75axijww7sqnftste | true | | 2026-07-09T14:17:17+01:00 | 7jks7dru5xpx5p5id5wtypur2y | true | | 2026-06-22T18:33:29+01:00 | f3jbyxlhtmalco67fmfoxs7n4m | true | +---------------------------+----------------------------+------------+ ``` Select one of the backups marked as **Restorable** and copy its **Backup ID**. - Navigate to the environment where you want to see backups. - Click **Backups**. Select one of the backups marked as having completed successfully . ## 2. Restore from a backup To restore the backup you've selected, follow these steps: - Press ``enter`` to agree with the consequences and continue. - Next to the backup you’ve selected, click **More** More. - Click **Restore**. - Read through the consequences and click **Yes, Restore**. The data is restored and your backed-up environment is deployed. This deployment uses the built app, including variables, from when the backup was taken. **Warning**: The code is also initially restored, but Upsun doesn’t modify your Git repository. So any future (re)deployments use the current Git repository to build the environment. To restore your code to its previous state when the backup was taken, use Git commands such as [revert](https://git-scm.com/docs/git-revert). Note that you can also opt out of restoring the code entirely by using the ``--no-code`` flag. For more information, see [how backup and restore works on Upsun](https://docs.upsun.com/environments/backup.md#how-backup-and-restore-works). Also, see [how resource allocation works](https://docs.upsun.com/manage-resources/resource-init.md#backup-restoration) when you restore a backup. ## Restore to a different environment You can restore backups to a different environment than they were created on using the CLI: 1. Switch to the branch where the backup was created. 2. To restore your backup to an existing environment, run the following command: ```bash upsun backup:restore --target= ``` If your target environment doesn't exist yet, you can create it by [branching an existing environment](https://docs.upsun.com/glossary.md#branch). The new target environment will be an exact copy of the existing (parent) environment. To do so, use the `--branch-from` option to specify the parent of your new target environment: ```bash upsun backup:restore --target= --branch-from= ``` --- # Source: https://docs.upsun.com/learn/tutorials/restrict-service-access.md # Restrict access to a service Upsun allows you to restrict access to a service. In this tutorial, learn how to grant your Data team `read-only` access to your production database. ## Before you start You need: - A project with a database service - A `viewer` user on your project ## 1. Add a read-only endpoint to your database service Edit your `.upsun/config.yaml` file and add the following [endpoints](https://docs.upsun.com/add-services/mysql/_index.md#define-permissions): - `website` with `admin` access to the `main` database - `reporting` with read-only `ro` access to the `main` database ```yaml {location=".upsun/config.yaml"} services: maindb: type: mariadb:11.8 configuration: schemas: - main endpoints: website: default_schema: main privileges: main: admin reporting: privileges: main: ro ``` ## 2. Grant your app access to the new endpoints Edit your app configuration and add new relationships to your new endpoints: ```yaml {location=".upsun/config.yaml"} applications: myapp: # ... relationships: database: service: maindb endpoint: website reports: service: maindb endpoint: reporting ``` ## 3. Create a worker with access to the read-only endpoint Edit your app configuration to add a new worker which: - Does nothing (`sleep infinity`) - Can access the read-only `reporting` endpoint - Allows SSH access to `viewer` ```yaml {location=".upsun/config.yaml"} applications: myapp: workers: data_access: mounts: {} commands: start: | sleep infinity relationships: reports: service: maindb endpoint: reporting access: ssh: viewer ``` You're done! From now on, your `viewer` users can SSH in to the worker application, and connect to your database with read-only permissions. --- # Source: https://docs.upsun.com/create-apps/web/rewrite-requests.md # Rewrite requests without redirects You might want to rewrite requests so they're served by specific sections of your app without having to redirect users. For example, you might want to make URLs seem semantic to users without having to rewrite your app architecture. In such a case, you might want requests to `/shoes/great-shoe/` to be served as if they were requests to `/?category=shoes&product=great-shoe`. If so, add a [rule](https://docs.upsun.com/create-apps/image-properties/web.md#rules) similar to the following: ```yaml {location=".upsun/config.yaml"} applications: myapp: source: root: "/" web: locations: '/': ... rules: '^/(?[^/]+)/(?[^/]+)/$': passthru: '/?category=$category&product=$product' ``` Or you might organize your images by file type, but don't want to expose the organization externally. You could rewrite requests to do that behind the scenes: ```yaml {location=".upsun/config.yaml"} applications: myapp: source: root: "/" web: locations: '/': ... rules: '^/img/(?.*)\.(?.*)$': passthru: '/$type/$name.$type' ``` Now a request to `/img/image.png` returns the file found at `/png/image.png`. ## Query parameters Query parameters in the request are untouched by rules and will be passed to the app. For example, if you have the category and product rule from previously, a request to `/shoes/great-shoe/?product=terrible-shoe` is rewritten to `?category=shoes&product=great-shoe&product=terrible-shoe`. In that case, the `product` query parameter sent to the app will contain the value `terrible-shoe`. --- # Source: https://docs.upsun.com/create-apps/multi-app/routes.md # Define routes for your multiple apps When you set up a project containing multiple applications, all of your apps are served by a single [router for the project](https://docs.upsun.com/define-routes.md). Each of your apps must have a `name` that's unique within the project. To define specific routes for one of your apps, use this `name`. There are various ways you can define routes for multiple app projects. In this project, you have a CMS app, two frontend apps (one using Symfony and another using Gatsby), and a Mercure Rocks server app, defined as follows: ```yaml {location=".upsun/config.yaml"} applications: admin: source: root: admin type: nodejs:24 api: source: root: api type: php:8.5 gatsby: source: root: gatsby type: nodejs:24 mercure: source: root: mercure/.config type: golang:1.25 ``` **Note**: You don’t need to define a route for each app in the repository. If an app isn’t specified, then it isn’t accessible to the web. One good example of defining an app with no route is when you [use Git submodules](https://docs.upsun.com/create-apps/multi-app/project-structure.md#split-your-code-source-into-multiple-git-submodule-repositories) and want to [use a source operation to update your submodules](https://docs.upsun.com/development/submodules.md#update-submodules). You can also achieve the same thing by defining the app as a [worker](https://docs.upsun.com/create-apps/image-properties/workers.md). Depending on your needs, you could configure the router container [using subdomains](#define-routes-using-subdomains) or using [subdirectories](#define-routes-using-subdirectories). ### Define routes using subdomains You could define routes for your apps as follows: ```yaml {location=".upsun/config.yaml"} routes: "https://mercure.{default}/": type: upstream upstream: "mercure:http" "https://{default}/": type: upstream upstream: "api:http" ``` So if your default domain is `example.com`, that means: - `https://mercure.example.com/` is served by your Mercure Rocks app (`mercure`). - `https://example.com/` is served by your Symfony frontend app (`api`). **Note**: Using a subdomain might [double your network traffic](https://www.nickolinger.com/blog/2021-08-04-you-dont-need-that-cors-request/), so consider using a path like ``https://{default}/api`` instead. ### Define routes using subdirectories Alternatively, you could define your routes as follows: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": type: upstream upstream: "api:http" "https://{default}/admin": type: upstream upstream: "admin:http" ``` Then you would need to configure each app's `web.locations` property to match these paths: ```yaml {location=".upsun/config.yaml"} applications: admin: source: root: admin type: nodejs:24 ... web: locations: '/admin': passthru: '/admin/index.html' root: 'build' index: - 'index.html' api: source: root: api type: php:8.5 ... web: locations: "/": passthru: "/index.php" root: "public" index: - index.php routes: "https://{default}/": type: upstream upstream: "api:http" "https://{default}/admin": type: upstream upstream: "admin:http" ``` So if your default domain is `example.com`, that means: - `https://example.com/` is served by your Symfony frontend app (`api`). - `https://example.com/admin` is served by your Admin app (`admin`). Note that in this example, for the configuration of your `admin` app, you need to add the URL suffix `/admin` as both an index in the `web.locations` and a value for the `passhtru` setting. For a complete example, [go to this project on GitHub](https://github.com/platformsh-templates/bigfoot-multiapp/tree/submodules-root-subfolders-applications). --- # Source: https://docs.upsun.com/languages/ruby.md # Ruby p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. Upsun supports deploying any Ruby application. Your application can use any Ruby application server such as Puma or Unicorn and deploying a Rails or a Sinatra app is very straight forward. ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. ### Ruby - 4.0 - 3.4 - 3.3 - 3.2 ### Specify the language To use Ruby, specify `ruby` as your [app's `type`](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#types): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. : type: 'ruby:' ``` For example: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'ruby:4.0' ``` ### Deprecated versions The following versions are [deprecated](https://docs.upsun.com/glossary.md#deprecated-versions). They're available, but they don't receive security updates from upstream and aren't guaranteed to work. They'll be removed in the future – consider migrating to a [supported version](#supported-versions). - 3.1 - 3.0 - 2.7 - 2.6 - 2.5 - 2.4 - 2.3 ## Puma based Rails configuration This example uses Puma to run a Ruby application. You could use any Ruby application server such as Unicorn. Configure the `.upsun/config.yaml` file with a few key settings as listed below. A complete example is included at the end of this section. 1. Specify the language of your application (available versions are listed above): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'ruby:4.0' ``` 2. Setup environment variables. Rails runs by default on a preview environment. You can change the Rails/Bundler via those environment variables, some of which are defaults on Upsun. ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'ruby:4.0' variables: env: PIDFILE: "tmp/server.pid" # Allow to start puma directly even if `tmp/pids` directory is not created RAILS_ENV: "production" BUNDLE_WITHOUT: 'development:test' TARGET_RUBY_VERSION: '~>4.0' # this will allow to not fail on PATCH update of the image ``` The `SECRET_KEY_BASE` variable is generated automatically based on the [`PLATFORM_PROJECT_ENTROPY` variable](https://docs.upsun.com../development/variables/use-variables.md#use-provided-variables) but you can change it. Based on TARGET_RUBY_VERSION, we recommand to set on your Gemfile so next PATCH release of ruby doesn't fail the build: ```ruby ruby ENV["TARGET_RUBY_VERSION"] || File.read(File.join(File.dirname(__FILE__), ".ruby-version")).strip ``` 3. Build your application with the build hook. Assuming you have your dependencies stored in the `Gemfile` at [your app root](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory), create a hook like the following: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'ruby:4.0' ... hooks: build: | set -e bundle install bundle exec rails assets:precompile deploy: bundle exec rake db:migrate ``` These are installed as your project dependencies in your environment. You can also use the `dependencies` key to install global dependencies. These can be Ruby, Python, NodeJS, or PHP libraries. If you have assets, it's likely that you need NodeJS/yarn. ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'ruby:4.0' ... dependencies: nodejs: yarn: "*" ``` 4. Configure the command to start serving your application (this must be a foreground-running process) under the `web` section: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'ruby:4.0' ... web: upstream: socket_family: unix commands: # for puma start: "bundle exec puma -b unix://$SOCKET" # for unicorn # start: "bundle exec unicorn -l $SOCKET" ``` This assumes you have Puma as a dependency in your Gemfile: ```ruby gem "puma", ">= 5.0" ``` 5. Define the web locations your application is using: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'ruby:4.0' ... web: locations: "/": root: "public" passthru: true expires: 1h allow: true ``` This configuration sets the web server to handle HTTP requests at `/static` to serve static files stored in `/app/static/` folder. Everything else is forwarded to your application server. 6. Create any Read/Write mounts. The root file system is read only. You must explicitly describe writable mounts. ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'ruby:4.0' ... mounts: "/log": source: tmp source_path: log "/storage": source: storage source_path: storage "/tmp": source: tmp source_path: tmp ``` This setting allows your application writing temporary files to `/app/tmp`, logs stored in `/app/log`, and active storage in `/app/storage`. You can define other read/write mounts (your application code itself being deployed to a read-only file system). Note that the file system is persistent and when you backup your cluster these mounts are also backed up. 7. Then, setup the routes to your application in `.upsun/config.yaml`. ```yaml {location=".upsun/config.yaml"} applications: ... routes: "https://{default}/": type: upstream upstream: "myapp:http" ``` ### Complete app configuration Here is a complete `.upsun/config.yaml` file: ```yaml {location=".upsun/config.yaml"} # The name of the app, which must be unique within a project. applications: myapp: type: 'ruby:4.0' dependencies: nodejs: yarn: "*" relationships: mysql: variables: env: BUNDLE_CACHE_ALL: '1' # Default, Cache all gems, including path and git gems. BUNDLE_CLEAN: '1' # /!\ if you are working with Ruby<2.7 this doesn't work well, but should be safe on modern Rubies. BUNDLE_DEPLOYMENT: '1' # Default, Disallow changes to the Gemfile. BUNDLE_ERROR_ON_STDERR: '1' # Default. BUNDLE_WITHOUT: 'development:test' PIDFILE: "tmp/server.pid" # Allow to start puma directly even if `tmp/pids` directory is not created DEFAULT_BUNDLER_VERSION: "2.5.14" # In case none is mentioned in Gemfile.lock EXECJS_RUNTIME: 'Node' # If you need one on your assets https://github.com/rails/execjs#readme NODE_ENV: 'production' NODE_VERSION: v14.17.6 NVM_VERSION: v0.38.0 RACK_ENV: 'production' RAILS_ENV: 'production' RAILS_LOG_TO_STDOUT: '1' # Default RAILS_TMP: '/tmp' # Default hooks: build: | set -e echo "Installing NVM $NVM_VERSION" unset NPM_CONFIG_PREFIX export NVM_DIR="$PLATFORM_APP_DIR/.nvm" # install.sh will automatically install NodeJS based on the presence of $NODE_VERSION curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/$NVM_VERSION/install.sh | bash [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # we install the bundled bundler version and fallback to a default (in env vars above) export BUNDLER_VERSION="$(grep -A 1 "BUNDLED WITH" Gemfile.lock | tail -n 1)" || "$DEFAULT_BUNDLER_VERSION" echo "Install bundler $BUNDLER_VERSION" gem install --no-document bundler -v $BUNDLER_VERSION echo "Installing gems" # We copy the bundle directory to the Upsun cache directory for # safe keeping, then restore from there on the next build. That allows # bundler to skip downloading code it doesn't need to. [ -d "$PLATFORM_CACHE_DIR/bundle" ] && \ rsync -az --delete "$PLATFORM_CACHE_DIR/bundle/" vendor/bundle/ mkdir -p "$PLATFORM_CACHE_DIR/bundle" bundle install # synchronize updated cache for next build [ -d "vendor/bundle" ] && \ rsync -az --delete vendor/bundle/ "$PLATFORM_CACHE_DIR/bundle/" # precompile assets echo "Precompiling assets" # We copy the webpacker directory to the Upsun cache directory for # safe keeping, then restore from there on the next build. That allows # bundler to skip downloading code it doesn't need to. # https://guides.rubyonrails.org/asset_pipeline.html mkdir -p "$PLATFORM_CACHE_DIR/webpacker" mkdir -p "$RAILS_TMP/cache/webpacker" [ -d "$PLATFORM_CACHE_DIR/webpacker" ] && \ rsync -az --delete "$PLATFORM_CACHE_DIR/webpacker/" $RAILS_TMP/cache/webpacker/ # We dont need secret here https://github.com/rails/rails/issues/32947 SECRET_KEY_BASE=1 bundle exec rails assets:precompile rsync -az --delete $RAILS_TMP/cache/webpacker/ "$PLATFORM_CACHE_DIR/webpacker/" deploy: bundle exec rake db:migrate mounts: "/log": source: tmp source_path: log "/storage": source: storage source_path: storage "/tmp": source: tmp source_path: tmp web: upstream: socket_family: unix commands: # for puma start: "bundle exec puma -b unix://$SOCKET" # for unicorn # start: "bundle exec unicorn -l $SOCKET" locations: "/": root: "public" passthru: true expires: 1h allow: true routes: "https://{default}/": type: upstream upstream: "myapp:http" services: ... ``` ## Configuring services This example assumes there is a MySQL instance. To configure it, [create a service](https://docs.upsun.com../add-services.md) such as the following: ```yaml {location=".upsun/config.yaml"} applications: ... routes: ... services: mysql: type: mysql:11.8 ``` ## Connecting to services Once you have a service, link to it in your [app configuration](https://docs.upsun.com../create-apps/_index.md): ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'ruby:4.0' relationships: mysql: [...] routes: [...] services: mysql: type: mysql:11.8 ``` By using the following Ruby function calls, you can obtain the database details. ```ruby require "base64" require "json" relationships= JSON.parse(Base64.decode64(ENV['PLATFORM_RELATIONSHIPS'])) ``` This should give you something like the following: ```json { "mysql" : [ { "path" : "main", "query" : { "is_master" : true }, "port" : 3306, "username" : "user", "password" : "", "host" : "mysql.internal", "ip" : "246.0.241.50", "scheme" : "mysql" } ] } ``` For Rails, you can use the standard Rails `config/database.yml` with the values found with the snippet provided before. ## Other tips - To speed up boot you can use the [Bootsnap gem](https://github.com/Shopify/bootsnap) and configure it with the local `/tmp`: ```ruby {location="config/boot.rb"} Bootsnap.setup(cache_dir: "/tmp/cache") ``` - For garbage collection tuning, you can read [this article](https://shopify.engineering/17489064-tuning-rubys-global-method-cache) and look for [discourse configurations](https://github.com/discourse/discourse_docker/blob/b259c8d38e0f42288fd279c9f9efd3cefbc2c1cb/templates/web.template.yml#L8) - New images are released on a regular basis to apply security patches. While the minor version will not change (as you are specifying it in the `type` property), the patch version will be updated. You may encounter this kind of error: ``` bundler: failed to load command: puma (/app/vendor/bundle/ruby/3.2.0/bin/puma) /app/.global/gems/bundler-2.4.22/lib/bundler/definition.rb:447:in `validate_ruby!': Your Ruby version is 3.2.9, but your Gemfile specified 3.2.8 (Bundler::RubyVersionMismatch) ``` To avoid issues when such updates are performed, use ```ruby ruby ENV["TARGET_RUBY_VERSION"] || File.read(File.join(File.dirname(__FILE__), ".ruby-version")).strip ``` in your `Gemfile`, where `TARGET_RUBY_VERSION` has been defined as above. ## Troubleshooting By default, deployments have `BUNDLE_DEPLOYMENT=1` to ensure projects have a `Gemfile.lock` file. This is safer for version yank issues and other version upgrade breakages. You may encounter an error like the following during a build: ```txt {no-copy="true"} W: bundler: failed to load command: rake (/app/.global/bin/rake) W: /app/.global/gems/bundler-2.3.5/lib/bundler/resolver.rb:268:in `block in verify_gemfile_dependencies_are_found!': Could not find gem 'rails (= 5.2.6)' in locally installed gems. (Bundler::GemNotFound) ``` To resolve this error: 1. Run `bundle install` with the same `ruby` and `bundler` versions defined in your `.upsun/config.yaml` file. 2. Push the `Gemfile.lock` to your repository. --- # Source: https://docs.upsun.com/create-apps/runtime-operations.md # Runtime operations Runtime operations allow you to trigger one-off commands or scripts on your project. Similar to [crons](https://docs.upsun.com/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](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md) and [trigger them](#run-a-runtime-operation) at any time through the Upsun CLI. For example, if you have a static website, you may want to set up a runtime operation to occasionally fetch content from a backend system without having to rebuild your whole app. ## Define a runtime operation To define a runtime operation, add a configuration similar to the following: ```yaml {location=".upsun/config.yaml"} applications: myapp: source: root: "/" operations: : role: commands: start: ``` When you define a runtime operation, you can specify which users can trigger it according to their user `role`: - `viewer` - `contributor` - `admin` If you don't set the `role` option when configuring your runtime operation, by default all users with the `contributor` role can trigger it. For example, to allow admin users to clear the cache of a Drupal site, you could define an operation like the following: ```yaml {location=".upsun/config.yaml"} applications: myapp: source: root: "/" operations: clear-rebuild: role: admin commands: start: drush cache:rebuild ``` The name of the runtime operation in this case is `clear-rebuild`. For more possibilities, see other [runtime operation examples](#runtime-operation-examples). ## Run a runtime operation A runtime operation can be triggered through the Upsun CLI once it has been [defined](#define-a-runtime-operation). Run the following command: ```bash {} upsun operation:run --project --environment ``` You can only trigger a runtime operation if you have permission to do so. Permissions are granted through the ``role`` option specified in the [runtime operation configuration](#define-a-runtime-operation). This can only be done if a [runtime operation has been defined](#define-a-runtime-operation). For example, to trigger the runtime operation [defined previously](#define-a-runtime-operation), you could run the following command: ```bash {} upsun operation:run clear-rebuild --project --environment ``` ## List your runtime operations To list all the runtime operations available on an environment, run the following command: ```bash upsun operation:list --project --environment ``` ## Runtime operation examples ### Build your app when using a static site generator During every Upsun deployment, a standard [`build` step](https://docs.upsun.com/learn/overview/build-deploy.md#the-build) is run. When you use a static site generator like Gatsby or Next.js with a headless backend you need to run a second `build` step to get your app ready for production. This is because, as its framework is being built, your frontend needs to pull content-related data from your backend’s API (to generate all the static HTML pages your site is to serve). To accomplish this on Upsun, where each app goes through a build-deploy pipeline in parallel, your frontend’s build must be delayed _until after_ your backend has fully deployed. It's often delayed up until the [`post_deploy` hook](https://docs.upsun.com../create-apps/hooks/hooks-comparison.md#post-deploy-hook) stage, when the filesystem is read-only. You can use a runtime operation to trigger the second `build` step after the initial deployment of your app or after a redeployment. You can also trigger it when you need to fetch content from your backend but want to avoid going through the whole Upsun [build and deploy processes](https://docs.upsun.com/learn/overview/build-deploy.md) again. **Note**: The following examples assume that the frontend and backend containers are included in the same environment. This isn’t necessary for the commands to run successfully.
What is necessary is that the build destination for your frontend **is writable at runtime** (meaning, you must [define a mount](https://docs.upsun.com/create-apps/image-properties/mounts.md) for it). If you don’t want to include a build within a mount (especially if your data source **isn’t** on Upsun), you can use [source operations](https://docs.upsun.com/create-apps/source-operations.md) to achieve a similar effect, but through generating a new commit. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" operations: gatsby-build: role: viewer commands: start: gatsby build ``` To trigger your runtime operation, run a command similar to the following: ```bash {} upsun operation:run gatsby-build --project --environment ``` To run the [Next.js build](https://nextjs.org/docs/deployment#nextjs-build-api) step, define a runtime operation similar to the following: .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" operations: next-build: role: admin commands: # All below are valid, depending on your setup start: next build # start: npx next build # start: npm run build ``` To trigger your runtime operation, run a command similar to the following: ```bash {} upsun operation:run next-build --project --environment ``` ### Execute actions on your Node.js app You can define runtime operations for common [pm2](https://pm2.io/docs/runtime/overview/) process manager tasks. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" operations: pm2-ping: role: admin commands: start: | # Assuming pm2 start npm --no-daemon --watch --name $APP -- start -- -p $PORT APP=$(cat package.json | jq -r '.name') pm2 ping $APP ``` To trigger your runtime operation, run a command similar to the following: ```bash {} upsun operation:run pm2-ping --project --environment ``` To reload your Node.js app, define a runtime operation similar to the following: .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" operations: pm2-reload: role: admin commands: start: | # Assuming pm2 start npm --no-daemon --watch --name $APP -- start -- -p $PORT APP=$(cat package.json | jq -r '.name') pm2 reload $APP ``` To trigger your runtime operation, run a command similar to the following: ```bash {} upsun operation:run pm2-reload --project --environment ``` To restart your Node.js app, define a runtime operation similar to the following: .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" operations: pm2-restart: role: admin commands: start: | # Assuming pm2 start npm --no-daemon --watch --name $APP -- start -- -p $PORT APP=$(cat package.json | jq -r '.name') pm2 restart $APP ``` To trigger your runtime operation, run a command similar to the following: ```bash {} upsun operation:run pm2-restart --project --environment ``` ### Define management commands on your Django project On a Django project, you can [define custom `django-admin` commands](https://docs.djangoproject.com/en/4.2/howto/custom-management-commands/), for example to run a one-off management command (`manual migration` in the example above) outside of the Django ORM migration framework. To do so, define a runtime operation similar to the following: ```yaml {location=".upsun/config.yaml"} applications: myapp: source: root: "/" type: python:3.14 operations: manual-migration: role: admin commands: start: python manage.py manual_migration ``` To trigger your runtime operation, run a command similar to the following: ```bash upsun operation:run manual-migration --project --environment ``` --- # Source: https://docs.upsun.com/languages/rust.md # Rust p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. Upsun supports building and deploying applications written in Rust. ## Supported versions You can select the major version. But the latest compatible minor version is applied automatically and can’t be overridden. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 1 ## Dependencies The recommended way to handle Rust dependencies on Upsun is using Cargo. Commit a `Cargo.toml` and a `Cargo.lock` file in your repository so the system automatically downloads dependencies using Cargo. ## Building and running your app Assuming your `Cargo.toml` and `Cargo.lock` files are present in your repository, you can build your app using the `cargo build` command to produce a working executable. You can then start it from the `web.commands.start` directive. Note that the start command _must_ run in the foreground. If the program terminates for any reason it is automatically restarted. The following basic [app configuration](https://docs.upsun.com../../create-apps.md) is sufficient to run most Rust apps. See the [complete example](#complete-example) below for more details. ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: # The language and version for your app. type: 'rust:1' hooks: build: cargo build web: commands: # Customize the start command with your own target. start: './target/debug/hello' locations: /: # Route all requests to the Rust app, unconditionally. allow: false passthru: true ``` Note that there is still an Nginx proxy server sitting in front of your application. If desired, certain paths may be served directly by Nginx without hitting your application (for static files, primarily) or you may route all requests to the Rust app unconditionally, as in the example above. ## Built-in variables Upsun exposes relationships and other configuration as [environment variables](https://docs.upsun.com../development/variables.md). To get the `PORT` environment variable (the port on which your app is supposed to listen), use the following snippet: ```rust let port : String = env::var("PORT").unwrap_or(String::from("8888")); ``` Note that some of the environment variables are in JSON format and are base64 encoded. For example, to decode the `PLATFORM_RELATIONSHIPS` environment variable, use the following snippet: ```rust use base64::{Engine as _, engine::{general_purpose}}; use serde_json::Value; let bytes = general_purpose::STANDARD.decode(env::var("PLATFORM_RELATIONSHIPS").unwrap_or(String::new())).unwrap(); let psh_config: Value = serde_json::from_slice(&bytes).unwrap(); println!("{}", psh_config["database"]); ``` ## Complete example Here is a basic hello world app to illustrate how you can use Rust with Upsun. It builds from a `hello.rs` file to serve a static `index.html`. Follow these steps: 1. [Install Rust and Cargo](https://www.rust-lang.org/tools/install). 2. Create a repository for your app and add the following `Cargo.toml` file: ```toml [package] name = "hello_world" version = "0.1.0" edition = "2021" [[bin]] name = "hello" path = "hello.rs" [dependencies] time = "0.1.12" regex = "0.1.41" base64 = "0.21.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" ``` 3. Add the following [app configuration](https://docs.upsun.com../../create-apps/_index.md): ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: # The language and version for your app. type: 'rust:1' hooks: build: cargo build web: commands: # Customize the start command with your own target. start: './target/debug/hello' locations: /: # Route all requests to the Rust app, unconditionally. allow: false passthru: true ``` 4. To generate a `Cargo.lock` file, run the following command: ```bash cargo generate-lockfile ``` 5. Add the following `hello.rs` file: ```rust /* Simple HTTP Server */ /* Author : Ramesh Vyas */ use std::io::prelude::*; use std::net::TcpListener; use std::net::TcpStream; use std::fs; use std::env; fn main() { /* Creating a Local TcpListener at Port 8888 */ const HOST : &str ="127.0.0.1"; let port : String = env::var("PORT").unwrap_or(String::from("8888")); /* Concating Host address and Port to Create Final Endpoint */ let end_point : String = HOST.to_owned() + ":" + &port; /*Creating TCP Listener at our end point */ let listener = TcpListener::bind(end_point).unwrap(); println!("Web server is listening at port {}",port); /* Connecting to any incoming connections */ for stream in listener.incoming() { let _stream = stream.unwrap(); // Call Function to process any incomming connections handle_connection(_stream); } } fn handle_connection(mut stream: TcpStream) { let mut buffer = [0; 1024]; stream.read(&mut buffer).unwrap(); let get = b"GET / HTTP/1.1\r\n"; if buffer.starts_with(get) { let contents = fs::read_to_string("index.html").unwrap(); let response = format!( "HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{}", contents.len(), contents ); stream.write(response.as_bytes()).unwrap(); stream.flush().unwrap(); } else { // some other request } } ``` --- # Source: https://docs.upsun.com/development/sanitize-db.md # Sanitize databases When working on a new feature on your website, you want to use a new branch. Using a new branch makes sure that you don't risk breaking your live, production website. Creating a branch on Upsun copies both the code and the database to that new development branch. These code and database changes need to be tested before being merged into production. Depending on your processes, internal or external teams may interact with the preview environment branch. Databases of live websites often contain personally identifiable information (PII) such as full names, mailing addresses, and phone numbers. To ensure people reviewing code changes can't access information they shouldn't, sanitize your databases of any PII that they may contain. ## Examples --- # Source: https://docs.upsun.com/environments/search-engine-visibility.md # Set an environment's visibility to search engines When you have preview environments, you don't want search engines indexing them and diluting the SEO of your production site. Search engine indexers are told to ignore all preview environments. When you're ready to go live, give your production environment a [custom domain](https://docs.upsun.com../domains/steps.md) and then set it to be visible to search engines. To change your production environment's visibility to search engines, follow these steps: - Select the project where you want to change visibility. - From the **Environment** menu, select your production environment. - Click Settings **Settings**. - In the row with **Hide from search engines**, click **Edit **. - Select or clear the **Hide from search engines** checkbox. Upsun can't guarantee that indexers follow the instructions. If you're concerned about access, set up [HTTP access control](https://docs.upsun.com/environments/http-access-control.md). ## How it's done When the **Hide from search engines** is activated, search engines are turned away from environments by including a `X-Robots-Tag` header: ```txt X-Robots-Tag: noindex, nofollow ``` That tells search engine indexers to not index these sites and not traverse links from these sites. This helps keep non-Production sites out of search engine indexes. It's automatically on for all `upsun.site` domains, and it's automatically off for production environments with a custom domain. ## Alternative method You can also send instructions to search engine indexers using a `robots.txt` file. Your app can serve this as a static file from its disk or as a dynamic response from its `passthru`. Control either with the [`location` section of your app configuration](https://docs.upsun.com/create-apps/image-properties/web.md#locations). If your `robots.txt` file includes instructions to ignore a page, search engine indexers may ignore it even if you have configured Upsun to not send the header. --- # Source: https://docs.upsun.com/security.md # Source: https://docs.upsun.com/administration/security.md # Security --- # Source: https://docs.upsun.com/create-apps/web/serve-different-directories.md # Serve directories at different paths In some cases you might want to depart from the common practice of serving directories directly. You might want to create a URL structure different than the structure on your disk. For example, in Git you might have a folder for your app and another folder that builds your documentation. Your entire Git repository might look like the following: ```text {no-copy="true"} .upsun config.yaml application/ [app-code-files] docs-src/ [docs-code-files] ``` And your build process might build the documentation with an output folder such as `docs-public`. If so, you can serve all requests by your app code except for those that start with `/docs`, which you serve with your generated docs. Use a [`web` configuration](https://docs.upsun.com/create-apps/image-properties/web.md) similar to the following: ```yaml {location=".upsun/config.yaml"} applications: docs: source: root: "/" web: locations: '/': passthru: true '/docs': root: 'docs-public' index: - "index.html" expires: 24h scripts: false allow: true ``` This way, your app can safely coexist with static files as if it were a single site hierarchy. And you can keep the static pages separate from your app code. --- # Source: https://docs.upsun.com/languages/python/server.md # Web servers p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. The Python ecosystem offers a number of web servers that can be used to deploy to Upsun. The following examples deploy a Django project named `myapp`. They assume a `myapp/wsgi.py` or `myapp/asgi.py` file with a callable `application`. Adjust the examples to fit your framework and app. ## Gunicorn [Gunicorn](https://docs.gunicorn.org/) is a Python WSGI HTTP Server for Unix that operates on a pre-fork worker model. The Gunicorn server is broadly compatible with various web frameworks, light on server resource usage, and fast. To deploy with Gunicorn on Upsun , use one of the following examples to update your [app configuration](https://docs.upsun.com../../create-apps.md). The examples vary based on both your package manager (Pip, Pipenv, or Poetry) and whether your app listens on a TCP (default) or Unix (for running behind a proxy server) socket. For more information on upstream sockets and protocols, see the [application reference](https://docs.upsun.com/create-apps/image-properties/web.md#upstream). The snippets below assume that Gunicorn has been added as a dependency to your `requirements.txt`, `Pipfile.lock`, or `poetry.lock`. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: commands: start: "gunicorn -w 4 -b localhost:$PORT app.wsgi:application" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: upstream: socket_family: unix commands: start: "gunicorn -w 4 -b unix:$SOCKET app.wsgi:application" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: commands: start: "pipenv run gunicorn -w 4 -b localhost:$PORT app.wsgi:application" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: upstream: socket_family: unix commands: start: "pipenv run gunicorn -w 4 -b unix:$SOCKET app.wsgi:application" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: commands: start: "poetry run gunicorn -w 4 -b localhost:$PORT app.wsgi:application" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: upstream: socket_family: unix commands: start: "poetry run gunicorn -w 4 -b unix:$SOCKET app.wsgi:application" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` ### Gunicorn workers These examples define four worker processes with `-w 4`. For more details on what you can configure, see the [Gunicorn documentation](https://docs.gunicorn.org/en/stable/faq.md#worker-processes). Workers can also be defined with a custom [worker class](https://docs.gunicorn.org/en/latest/settings.md#worker-class), such as [Uvicorn](https://www.uvicorn.org/#running-with-gunicorn), [gevent](https://www.gevent.org/), or [Tornado](https://www.tornadoweb.org/). For example, to add a Uvicorn worker class to the pip example for Unix, adjust the start command to the following: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' web: upstream: socket_family: unix commands: start: "gunicorn -w 4 -k uvicorn.workers.UvicornWorker -b unix:$SOCKET app.wsgi:application" ``` ## Daphne [Daphne](https://github.com/django/daphne) is a HTTP, HTTP2 ,and WebSocket protocol server for ASGI and ASGI-HTTP, developed to power Django Channels. To deploy with Daphne on Upsun , use one of the following examples to update your [app configuration](https://docs.upsun.com../../create-apps.md). The examples vary based on both your package manager (Pip, Pipenv, or Poetry) and whether your app listens on a TCP (default) or Unix (for running behind a proxy server) socket. For more information on upstream sockets and protocols, see the [application reference](https://docs.upsun.com/create-apps/image-properties/web.md#upstream). The snippets below assume that Daphne has been added as a dependency to your `requirements.txt`, `Pipfile.lock`, or `poetry.lock`. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: commands: start: "daphne -p $PORT app.asgi:application" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: upstream: socket_family: unix commands: start: "daphne -u $SOCKET app.asgi:application" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: commands: start: "pipenv run daphne -p $PORT app.asgi:application" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: upstream: socket_family: unix commands: start: "pipenv run daphne -u $SOCKET app.asgi:application" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: commands: start: "poetry run daphne -p $PORT app.asgi:application" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: upstream: socket_family: unix commands: start: "poetry run -u $SOCKET app.asgi:application" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` ## Uvicorn [Uvicorn](https://www.uvicorn.org/) is an ASGI web server implementation for Python. To deploy with Uvicorn on Upsun , use one of the following examples to update your [app configuration](https://docs.upsun.com../../create-apps.md). The examples vary based on both your package manager (Pip, Pipenv, or Poetry) and whether your app listens on a TCP (default) or Unix (for running behind a proxy server) socket. For more information on upstream sockets and protocols, see the [application reference](https://docs.upsun.com/create-apps/image-properties/web.md#upstream). The snippets below assume that Uvicorn has been added as a dependency to your `requirements.txt`, `Pipfile.lock`, or `poetry.lock`. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: commands: start: "uvicorn app.asgi:application --port $PORT --workers 4" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: upstream: socket_family: unix commands: start: "uvicorn app.asgi:application --uds $SOCKET --workers 4" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: commands: start: "pipenv run uvicorn app.asgi:application --port $PORT --workers 4" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: upstream: socket_family: unix commands: start: "pipenv run uvicorn app.asgi:application --uds $SOCKET --workers 4" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: commands: start: "poetry run uvicorn app.asgi:application --port $PORT --workers 4" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: upstream: socket_family: unix commands: start: "poetry run uvicorn app.asgi:application --uds $SOCKET --workers 4" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` ### Uvicorn workers These examples define four worker processes with `-w 4`. For more recommendations on this and other settings, see the [Uvicorn documentation](https://www.uvicorn.org/settings/#timeouts). Instead of the `-w` flag, you can also use the `WEB_CONCURRENCY` variable. See how to [set variables](https://docs.upsun.com../../development/variables/set-variables.md). ## Hypercorn [Hypercorn](https://hypercorn.readthedocs.io/) is an ASGI and WSGI web server inspired by Gunicorn. To deploy with Hypercorn on Upsun , use one of the following examples to update your [app configuration](https://docs.upsun.com../../create-apps.md). The examples vary based on both your package manager (Pip, Pipenv, or Poetry) and whether your app listens on a TCP (default) or Unix (for running behind a proxy server) socket. For more information on upstream sockets and protocols, see the [application reference](https://docs.upsun.com/create-apps/image-properties/web.md#upstream). The snippets below assume that Hypercorn has been added as a dependency to your `requirements.txt`, `Pipfile.lock`, or `poetry.lock`. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: commands: start: "hypercorn app.asgi:application -b localhost:$PORT -w 4" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: upstream: socket_family: unix commands: start: "hypercorn app.asgi:application -b unix:$SOCKET -w 4" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: commands: start: "pipenv run hypercorn app.asgi:application -b localhost:$PORT -w 4" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: upstream: socket_family: unix commands: start: "pipenv run hypercorn app.asgi:application -b unix:$SOCKET -w 4" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: commands: start: "poetry run hypercorn app.asgi:application -b localhost:$PORT -w 4" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "/" type: 'python:3.14' web: upstream: socket_family: unix commands: start: "poetry run hypercorn app.asgi:application -b unix:$SOCKET -w 4" locations: "/": passthru: true "/static": root: "static" expires: 1h allow: true ``` ### Hypercorn workers These examples define four worker processes with `-w 4`. For more details on what you can configure, see the [Hypercorn documentation](https://hypercorn.readthedocs.io/en/latest/how_to_guides/configuring.md). Workers can also be defined with a custom [worker class](https://hypercorn.readthedocs.io/en/latest/how_to_guides/configuring.md#configuration-options), such as Asyncio, Uvloop, or Trio. For example, to add a Asyncio worker class to the pip example for Unix, adjust the start command to the following: ```yaml {location=".upsun/config.yaml"} applications: # The app's name, which must be unique within the project. myapp: type: 'python:3.14' web: upstream: socket_family: unix commands: start: "hypercorn app.asgi:application -b unix:$SOCKET -w 4 -k asyncio" ``` --- # Source: https://docs.upsun.com/administration/servers.md # Server upgrades To ensure your projects get the latest features, improvements, and bug fixes, Upsun updates the servers that deliver services. No action is needed on your part, and no downtime occurs for your projects. To view these upgrade events, go to the [activity logs](https://docs.upsun.com../increase-observability/logs/access-logs.md#activity-logs) for any project or environment and then select **Upgrade** from the **Filter** list. ## Affected servers ### Project API server The project API server responds to API calls to make the CLI and Console work for your project. It acts as the Git server, mirroring the source repository in the case of [source integrations](https://docs.upsun.com../integrations/source.md). It stores your app code and project configuration, provides API interfaces, and orchestrates the build and deploy process and other tasks for your environments. ### Project metrics server The project metrics server retrieves information about your environments' use of RAM, CPU, and disk. You can view this information as part of [environment metrics](https://docs.upsun.com../increase-observability/metrics.md). --- # Source: https://docs.upsun.com/development/variables/set-variables.md # Set variables To set variables, determine which [type of variable](https://docs.upsun.com/development/variables.md#variable-types) to use. Remember to take into account the order of precedence. All of the variables can also be [overridden via script](#set-variables-via-script). ## Set variables in your app Set variables [in code](https://docs.upsun.com/create-apps/image-properties/variables.md) using the `.upsun/config.yaml` file. These values are the same across all environments and present in the Git repository, which makes them a poor fit for API keys and other such secrets. They're better fits for uses such as configuration for consistent builds across every environment, including setting [PHP configuration values](https://docs.upsun.com/development/variables.md#php-specific-variables). Application variables are available at both build time and runtime. ## Create project variables Add secrets for all environments in project variables using [the Console](https://docs.upsun.com../../administration/web/configure-project.md#variables) or the [CLI](https://docs.upsun.com../../administration/cli.md). For example, you may need to vary API credentials between production and other environments. To do so, set the non-production credentials as a project variable and then override these credentials for the production environment by setting a [variable specific to that environment](#create-environment-specific-variables). To specify other options, use the [flags for variable options](#variable-options). To add a project variable, follow these steps: - Select the project where you want to create a variable. - Click Settings **Settings**. - Under **Project settings**, click **Variables**. - Click **+ Create variable**. - Enter a name for the variable. - Enter the variable value. - Ensure you have selected the right [other options](#variable-options). - Click **Create variable**. When naming variables, be sure to take [variable prefixes](https://docs.upsun.com/development/variables.md#variable-prefixes) into account. In particular, to expose a variable as its own environment variable, [use the prefix `env:`](https://docs.upsun.com../../development/variables.md#top-level-environment-variables). ### Variable options Variables have several Boolean options you can set in the Console or the CLI: | Option | CLI flag | Default | Description | |---------------------|-----------------------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------| | JSON | `--json` | `false` | Whether the variable is a JSON-serialized value (`true`) or a string (`false`). | | Sensitive | `--sensitive` | `false` | If set to `true`, the variable's value is hidden in the Console and in CLI responses for added security. It's still readable within the app container. | | Runtime | `--visible-runtime` | `true` | Whether the variable is available at runtime. | | Build | `--visible-build` | `true` | Whether the variable is available at build time. | | Application scope | `--app-scope` | — | Limits the variable visibility to specific apps. By default, the variable is available across all applications. | So if you want the `foo` variable to be visible at build time but hidden during runtime, you can set it by running the following command: ```bash upsun variable:create --level project --name foo --value bar --visible-build true --visible-runtime false ``` You can also change the variable options after you create them (except for sensitive values, which can't be set to non-sensitive). For example, to make the `foo` variable visible at runtime and hidden during the build, run the following command: ```bash upsun variable:update foo --visible-build false --visible-runtime true ``` #### Limiting variables to specific applications If you want the `foo` variable to be available only to certain applications, you can limit its scope using the `--app-scope` option: ```bash upsun variable:create --level project --name foo --value bar --app-scope frontend1,frontend2 ``` Where `frontend1` and `frontend2` are the names of your applications. **Note**: Note that for changes to project variables to have effect, you need to [redeploy](https://docs.upsun.com/development/troubleshoot.md#force-a-redeploy) your environments. ## Create environment-specific variables Set variables for specific environments using [the Console](https://docs.upsun.com../../administration/web/configure-environment.md#variables) or the CLI. Variables can be inherited or overridden from parent environments and project variables. See [more on overriding values](https://docs.upsun.com/development/variables.md#overrides). To specify the environment for the variable, use the ``-e`` flag to specify its name. To specify other options, use the [flags for variable options](#environment-variable-options). To add a project variable, follow these steps: - Select the project where you want to create a variable. - Click Settings **Settings**. - Under **Environments**, click the environment where you want to create a variable. - Click **Variables**. - Click **+ Create variable**. - Enter a name for the variable. - Enter the variable value. - Ensure you have selected the right [other options](#environment-variable-options). - Click **Create variable**. When naming variables, be sure to take [variable prefixes](https://docs.upsun.com/development/variables.md#variable-prefixes) into account. In particular, to expose a variable as its own environment variable, [use the prefix `env:`](https://docs.upsun.com../../development/variables.md#top-level-environment-variables). ### Environment variable options Environment variables share all of the [options available for project variables](#variable-options). Environment variables have one additional option: | Option | CLI flag | Default | Description | |-------------|-----------------|---------|----------------------------------------------------------| | Inheritable | `--inheritable` | `true` | Whether the variable is inherited by child environments. | This option is useful for setting production-only values such as credentials. For example, to set a PayPal secret value for only the `main` branch and have it not be readable elsewhere, run the following command: ```bash upsun variable:create -e main --name paypal_id --inheritable false --sensitive true ``` Other environments don't inherit it and get either a project variable of the same name if it exists or no value at all. Note that changing an environment variable causes that environment to be redeployed so the new value is available. But child environments are *not* redeployed. To make the new value accessible to those environments, [trigger a redeploy](https://docs.upsun.com../troubleshoot.md#force-a-redeploy). ### Example environment variable Environment variables are a good place to store values that apply only on Upsun and not on your local development environment. This includes API credentials for third-party services, mode settings, and which server (development vs. production) to use. One example would be to define a Node.js application's build on a production branch (`NODE_ENV=production`), but use development mode (`NODE_ENV=development`) for each of your preview environments. Assuming you have a `main` environment for production and a `staging` environment with more child environments for development, run the following commands: ```bash upsun variable:create -l environment -e main --prefix env: --name NODE_ENV --value production --visible-build true --inheritable false upsun variable:create -l environment -e staging --prefix env: --name NODE_ENV --value development --visible-build true --inheritable true ``` Now `NODE_ENV` is `production` on the default branch but `development` on `staging` and each of its child environments. Note that build visible environment variables change the application's build configuration ID: value updates trigger a rebuild of the application in the same way that a commit would. ## Set variables via script You can also provide a `.environment` file as in [your app root](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory). This file runs as a script in dash when the container starts and on all SSH logins. It can be used to set any environment variables directly, such as the PATH variable. For example, the following `.environment` file allows any executable installed in the `vendor/bin` directory (such as executables installed using Composer) to be run regardless of the current directory: ```bash {location=".environment"} export PATH="/app/vendor/bin:${PATH}" ``` You can also dynamically define environment variables based on the current environment. For example, you might want to get the [defined route](https://docs.upsun.com../../define-routes.md) with the id `api` for the current environment. To define it as the `URL` environment variable, you might add something like: ```bash {location=".environment"} URL=$(echo $PLATFORM_ROUTES | base64 --decode | jq -r 'to_entries[] | select (.value.id == "api") | .key') ``` Note that the file is sourced after all other environment variables above are defined and so they're available to the script. This also means the `.environment` script has the last word on environment variable values and can override anything it wants to. ### Testing `.environment` scripts You may find that a command that works during an SSH session provides a `bad substitution` error when placed in a `.environment` file. Remember, `.environment` is sourced using dash, not bash. When testing your `.environment` logic, be sure to first enter a `dash` session in your terminal or within the SSH session. When testing, you might print to stdout (using an `echo` or `printf` command) to check what's happening. The following example looks for a `deploy/environment.tracker.txt` file. It displays a different message if it's found or not, which helps you track what variables are being set. ```bash {location=".environment"} if [ -f "deploy/environment.tracker.txt" ]; then echo "File found." export DEPLOY='Friday' else echo "File not found." export DEPLOY='Never on a Friday' fi ``` While sanity checks like this are useful during troubleshooting, you shouldn't include such commands in your final code. Because the `.environment` file is run at the start of an SSH session, the message is printed at the start of the session. Even when your SSH command executes successfully, you might later attempt to download data from one of your mounts, such as by using the CLI command `upsun mount:download`. When you do, you see this error: ```bash protocol version mismatch -- is your shell clean? (see the rsync man page for an explanation) rsync error: protocol incompatibility (code 2) at .../rsync/compat.c(61) [receiver=2.6.9] [ProcessFailedException] The command failed with the exit code: 2 ``` This failure comes because `mount:download` and `rsync` don't expect output when the SSH connection is made. To solve the issue, remove the printed output from your `.environment` file. ## Map variables If your app needs different names for environment variable than those set by Upsun, which is common for database connections, map the Upsun's variable names to those required by the application via a shell script. You can obtain relationship information through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [`PLATFORM_RELATIONSHIPS` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For example, if your application has a relationship named ``database`` to a database service named `mariadb`: ```bash {} export APP_DATABASE_HOST="${DATABASE_HOST}" export APP_DATABASE_USER="${DATABASE_USERNAME}" ``` This sets environment variables with the names your app needs, and the values from [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables).It uses the ``jq`` library, which is included in all app containers for this purpose. .environment ```bash {} export APP_DATABASE_HOST="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode | jq -r '.database[0].host')" export APP_DATABASE_USER="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode | jq -r '.database[0].username')" ``` This sets environment variables with names your app needs, and the values from [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). ## When to use `.env` files {#use-env-files} Upsun does not read `.env files`, as conventionally they are not committed to Git. You can use these for local development, but they will not be sourced on any Upsun environment. Typically, you can add `.env` to your .gitignore file so that its contents can vary for different developers. Read more about [the use cases for `.env` files](https://upsun.com/blog/what-is-env-file/). --- # Source: https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md # Single-runtime image See all of the options for controlling your apps and how they’re built and deployed on Upsun. Use the `.upsun/config.yaml` file, located at the root of your Git repository, to configure the apps in a single-runtime image. See a [comprehensive example](https://docs.upsun.com/create-apps.md#comprehensive-example) of a configuration in a `.upsun/config.yaml` file. [Multi-app projects](https://docs.upsun.com/create-apps/multi-app.md) can be set up in various ways. ## Primary application properties In the `.upsun/config.yaml` file, configure each application as a unique key beneath the top-level `applications` key. For example, if your deployed site requires a Javascript `frontend` application container and a Python `backend` application container, the `.upsun/config.yaml` file would start to look something like this: ```yaml {location=".upsun/config.yaml"} applications: frontend: type: 'nodejs:24' # Additional frontend configuration backend: type: 'python:3.14' # Additional backend configuration ``` The following table presents all of the properties available to each unique app beneath the `applications` key. The **Set in instance** column 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**: The ``build``, ``dependencies``, and ``runtime`` properties are unique to this image type and are described later in this topic. All other properties are available in both single-runtime and composable images — click a property name to view its details in a separate topic. | Name | Type | Required | Set in instance? | Description | |---------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|----------|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | [`type`](#types) | A type | Yes | No | The base image to use with a specific app language. Format: `runtime:version`. | | [`container_profile`](https://docs.upsun.com/create-apps/image-properties/container_profile.md) | A container profile | | Yes | Determines which combinations of CPU and RAM a container can use. | [`relationships`](https://docs.upsun.com/create-apps/image-properties/relationships.md) | A dictionary of relationships | | Yes | Connections to other services and apps. | | [`mounts`](https://docs.upsun.com/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 `upsun resources:set`. | | [`web`](https://docs.upsun.com/create-apps/image-properties/web.md) | A web instance | | N/A | How the web application is served. | | [`workers`](https://docs.upsun.com/create-apps/image-properties/workers.md) | A worker instance | | N/A | Alternate copies of the application to run as background processes. | | [`timezone`](https://docs.upsun.com/create-apps/timezone.md) | `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](https://docs.upsun.com../timezone.md) | | [`access`](https://docs.upsun.com/create-apps/image-properties/access.md) | An access dictionary | | Yes | Access control for roles accessing app environments. | | [`variables`](https://docs.upsun.com/create-apps/image-properties/variables.md) | A variables dictionary | | Yes | Variables to control the environment. | | [`firewall`](https://docs.upsun.com/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 runs. | | [`hooks`](https://docs.upsun.com/create-apps/image-properties/hooks.md) | A hooks dictionary | | No | What commands run at different stages in the `build`, `deploy`, and `post_deploy` phases. | | [`crons`](https://docs.upsun.com/create-apps/image-properties/crons.md) | A cron dictionary | | No | Scheduled tasks for the app. | | [`source`](https://docs.upsun.com/create-apps/image-properties/source.md) | A source dictionary | | No | Details about the app’s source code and available operations. | | [`runtime`](#runtime) | A runtime dictionary | | No | Customizations to your PHP runtime. | | [`additional_hosts`](https://docs.upsun.com/create-apps/image-properties/additional_hosts.md) | An additional hosts dictionary | | Yes | Mappings of hostnames to IP addresses. | | [`operations`](https://docs.upsun.com/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. The root defaults to the root of the repository. ```yaml {location=".upsun/config.yaml"} applications: frontend: type: 'nodejs:24' # Default behavior of source.root source: root: "/" ``` That is, if a custom value for `source.root` is not provided in your configuration, the default behavior is equivalent to the above. To specify another directory, for example for a [multi-app project](https://docs.upsun.com../multi-app.md), use the [`source.root` property](create-apps/image-properties/source.md). ## `type` {#types} **Note**: To install multiple runtimes and tools in your application container, use the Upsun composable image. If you arrived here from another page, you may want to review the supported ``stack`` key where ``type`` was referenced. For details, see the list of [supported Nix runtimes](https://docs.upsun.com/create-apps/app-reference/composable-image.md#supported-nix-packages) that you can define in a composable image ``stack``. The `type` defines the base container image used to run the application. The version is the major (`X`) and sometimes minor (`X.Y`) version numbers, depending on the service, as in the following table. Security and other patches are taken care of for you automatically. Available languages and their supported versions: | **Language** | **``runtime``** | **Supported ``version``** | | [C#/.Net Core](https://docs.upsun.com/languages/dotnet.md) | ``dotnet`` | 10.0, 8.0 | | [Elixir](https://docs.upsun.com/languages/elixir.md) | ``elixir`` | 1.18, 1.15 | | [Go](https://docs.upsun.com/languages/go.md) | ``golang`` | 1.25, 1.24 | | [Java](https://docs.upsun.com/languages/java.md) | ``java`` | 21, 17 | | [JavaScript/Node.js](https://docs.upsun.com/languages/nodejs.md) | ``nodejs`` | 24, 22, 20 | | [PHP](https://docs.upsun.com/languages/php.md) | ``php`` | 8.5, 8.4, 8.3, 8.2 | | [Python](https://docs.upsun.com/languages/python.md) | ``python`` | 3.14, 3.13, 3.12, 3.11, 3.10 | | [Ruby](https://docs.upsun.com/languages/ruby.md) | ``ruby`` | 4.0, 3.4, 3.3, 3.2 | | [Rust](https://docs.upsun.com/languages/rust.md) | ``rust`` | 1 | ### Example configuration These are used in the format `runtime:version`: ```yaml {location=".upsun/config.yaml"} applications: : type: 'php:8.5' ``` ## `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. See what the build flavor is for your language: - [Node.js](https://docs.upsun.com/languages/nodejs.md#dependencies) - [PHP](https://docs.upsun.com/languages/php.md#dependencies) In all languages, you can also specify a flavor of `none` to take no action at all (which is the default for any language other than PHP and Node.js). ```yaml {location=".upsun/config.yaml"} applications: myapp: source: root: "/" type: 'nodejs:24' build: flavor: none ``` ## `dependencies` {#dependencies} Installs global dependencies as part of the build process. They're independent of the code dependencies of your application and are available in the `PATH` during the build process and in the runtime environment. They're installed before the `build` hook runs using a package manager for the language. | Language | Key name | Package manager | |----------|-----------------------|--------------------------------------------------------------------------------------------------------------------| | PHP | `php` | [Composer](https://getcomposer.org/) | | Python 2 | `python` or `python2` | [Pip 2](https://packaging.python.org/tutorials/installing-packages/) | | Python 3 | `python3` | [Pip 3](https://packaging.python.org/tutorials/installing-packages/) | | Ruby | `ruby` | [Bundler](https://bundler.io/) | | Node.js | `nodejs` | [npm](https://www.npmjs.com/) (see [how to use yarn](https://docs.upsun.com/languages/nodejs.md#use-yarn-as-a-package-manager)) | The format for package names and version constraints are defined by the specific package manager. An example of dependencies in multiple languages: ```yaml {location=".upsun/config.yaml"} applications: : type: 'nodejs:24' source: root: "/" dependencies: php: # Specify one Composer package per line. drush/drush: '8.0.0' composer/composer: '^2' python2: # Specify one Python 2 package per line. behave: '*' requests: '*' python3: # Specify one Python 3 package per line. numpy: '*' ruby: # Specify one Bundler package per line. sass: '3.4.7' nodejs: # Specify one NPM package per line. pm2: '^4.5.0' ``` ## `runtime` {#runtime} This applies to PHP only. The following table lists the various possible modifications to your PHP runtime: | Name | Type | Language | Description | |-----------------------------|------------------------------------------------------------|----------|---------------------------------------------------------------------------------------------------------| | `extensions` | List of `string`s OR [extensions definitions](#extensions) | PHP | [PHP extensions](https://docs.upsun.com/languages/php/extensions.md) to enable. | | `disabled_extensions` | List of `string`s | PHP | [PHP extensions](https://docs.upsun.com/languages/php/extensions.md) to disable. | | `request_terminate_timeout` | `integer` | PHP | The timeout (in seconds) for serving a single request after which the PHP-FPM worker process is killed. | | `sizing_hints` | A [sizing hints definition](#sizing-hints) | PHP | The assumptions for setting the number of workers in your PHP-FPM runtime. | | `xdebug` | An Xdebug definition | PHP | The setting to turn on [Xdebug](https://docs.upsun.com/languages/php/xdebug.md). | You can also set your [app's runtime timezone](https://docs.upsun.com/create-apps/timezone.md). ### Extensions **Note**: To install multiple runtimes and tools in your application container, use the Upsun composable image. If you arrived here from another page and you are using the composable image, you enable and disable extensions by using the ``stack.runtimes.extensions``/``stack.runtimes.disabled_extensions`` keys. For details and an example, see the [stack](https://docs.upsun.com/create-apps/app-reference/composable-image.md#stack) section in the “Composable image” topic. You can enable [PHP extensions](https://docs.upsun.com/languages/php/extensions.md) just with a list of extensions: ```yaml {location=".upsun/config.yaml"} applications: : type: 'php:8.5' source: root: "/" runtime: extensions: - geoip - tidy ``` Alternatively, if you need to include configuration options, use a dictionary for that extension: ```yaml {location=".upsun/config.yaml"} applications: : type: 'php:8.5' source: root: "/" runtime: extensions: - geoip - name: blackfire configuration: server_id: : server_token: : ``` In this case, the `name` property is required. ### 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](https://docs.upsun.com/languages/php/fpm.md). ## Resources (CPU, memory, and disk space) {#resources} By default, Upsun assigns a container profile and container size to each application and service on the first deployment of a project. The container _profile_ defines and enforces a specific CPU-to-memory ratio. The default container profile for an app or service in a composable image is ``HIGH_CPU``. Use the Upsun CLI or Console to manually adjust the allocated container _size_ (CPU and memory resources)—that is, to perform a **vertical‑scaling** action. When you redeploy, the container runs with the CPU‑to‑memory ratio defined by its profile, so it enforces the size you specified. Related topics: - For detailed steps for changing the container size, see the [Vertical scaling](https://docs.upsun.com/manage-resources/adjust-resources.md#vertical-scaling) section of the "Resource configuration topic. - For details about container sizes for each resource allocation strategy (shared CPU, guaranteed CPU, and initial allocation), see the [Advanced: Container profiles](https://docs.upsun.com/manage-resources/adjust-resources.md#advanced-container-profiles) section of the "Resource configuration" topic. - To learn more about general resource management in Upsun, see the topics in the [Manage resources](https://docs.upsun.com/manage-resources.md) section. ### Downsize a disk You can reduce the target disk size of an app. Keep in mind: - Backups created before the downsize are incompatible and cannot be used; you must [create new backups](https://docs.upsun.com/environments/backup.md). - The downsize will fail if the disk contains more data than the target size. ### Combine single-runtime and composable images {#combine-single-runtime-and-composable-images} In a [multiple application context](https://docs.upsun.com/create-apps/multi-app.md), you can use a mix of single-runtime images and [composable images](https://docs.upsun.com/create-apps/app-reference/composable-image.md). The following sample configuration includes two applications: - ``frontend`` – uses a single-runtime image - ``backend`` – uses a composable image In this app, PHP is the primary runtime and is started automatically (PHP-FPM also starts automatically when PHP is the primary runtime). For details, see the [PHP as a primary runtime](https://docs.upsun.com/create-apps/app-reference/composable-image.md#php-as-a-primary-runtime) section in the Composable image topic. ```yaml {location=".upsun/config.yaml"} applications: frontend: # this app uses the single-runtime image with a specific node.js runtime type: 'nodejs:24' backend: # this app uses the composable image and specifies two runtimes type: "composable:25.11" stack: runtimes: - "php@8.4": extensions: - apcu - sodium - xsl - pdo_sqlite - "python@3.13" packages: - "python313Packages.yq" # python package specific ``` --- # Source: https://docs.upsun.com/integrations/activity/slack.md # Example: Slack The following example activity script posts a message to a Slack channel every time it's triggered. To use it, follow these steps: 1. In your Slack administrative interface, [create a new Slack webhook](https://api.slack.com/messaging/webhooks). You get a URL starting with `https://hooks.slack.com/`. 2. Replace `SLACK_URL` in the following script with your webhook URL. 3. Paste the code into a `.js` file. 4. Add it as a new [script integration](https://docs.upsun.com/integrations/activity.md#installing). Specify which events should trigger it using the `--events` flag. Optionally specify environments with the `--environments` flag. Now, any activities that meet the events/environment criteria you specified are reported to Slack. Once you have it working, you're free to modify the code below as desired. For formatting more complex messages, see the [Slack messaging documentation](https://api.slack.com/messaging/composing/layouts). ```javascript /** * Sends a color-coded formatted message to Slack. * * To control what events trigger it, use the --events switch in * the Upsun CLI. * * @param {string} title * The title of the message block to send. * @param {string} message * The message body to send. */ function sendSlackMessage(title, message) { const url = SLACK_URL; if (!message) { // No message. Don't send it. return; } const messageTitle = title + ((new Date().getDay() === 5) ? " (On a Friday! :calendar:)" : ""); const color = activity.result === "success" ? "#66c000" : "#ff0000"; const body = { attachments: [ { title: messageTitle, text: message, color: color, }, ], }; const resp = fetch(url, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(body), }); if (!resp.ok) { console.log("Sending slack message failed: " + resp.body.text()); } } sendSlackMessage(activity.text, activity.log); ``` Common properties you may want to send to Slack (in the last line of the script) include: - `activity.text`: A brief, one-line statement of what happened. - `activity.log`: The complete build and deploy log output, as it would be seen in the Console log screen. For more properties, see the [activity reference](https://docs.upsun.com/integrations/activity/reference.md). --- # Source: https://docs.upsun.com/add-services/solr.md # Solr (Search service) Apache Solr is a scalable and fault-tolerant search index. Solr search with generic schemas provided, and a custom schema is also supported. See the [Solr documentation](https://lucene.apache.org/solr/6_3_0/index.md) for more information. ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 9.9 - 9.6 - 9.4 - 9.2 - 9.1 ### Deprecated versions The following versions are [deprecated](https://docs.upsun.com/glossary.md#deprecated-versions). They're available, but they don't receive security updates from upstream and aren't guaranteed to work. They'll be removed in the future – consider migrating to a [supported version](#supported-versions). - 9.0 - 8.11 - 8.0 - 7.7 - 7.6 - 6.6 - 6.3 - 4.10 - 3.6 ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables.md#service-environment-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "username": null, "scheme": "solr", "service": "solr", "fragment": null, "ip": "123.456.78.90", "hostname": "azertyuiopqsdfghjklm.solr.service._.eu-1.platformsh.site", "port": 8080, "cluster": "azertyuiopqsdf-main-afdwftq", "host": "solr.internal", "rel": "solr", "path": "solr\/collection1", "query": [], "password": null, "type": "solr:9.9", "public": false, "host_mapped": false } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_SOLR_HOST="$(echo "$RELATIONSHIPS_JSON" | jq -r '.solr[0].host')" ``` ## Usage example ### 1. Configure the service To define the service, use the ``solr`` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: solr: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. ### 2. Define the relationship To define the relationship, use the following configuration: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container (````) now has access to the service via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: solr ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). ### Example configuration ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: solr: services: # The name of the service container. Must be unique within a project. solr: type: solr:9.9 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: solr: service: solr endpoint: solr services: # The name of the service container. Must be unique within a project. solr: type: solr:9.9 ``` ### Use in app To use the configured service in your app, add a configuration file similar to the following to your project. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" [...] # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: solr: services: # The name of the service container. Must be unique within a project. solr: type: solr:9.9 ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" [...] # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: solr: service: solr endpoint: solr services: # The name of the service container. Must be unique within a project. solr: type: solr:9.9 ``` This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory. `myapp` has access to the `solr` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship) (as per [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships). From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference). ```bash {location="myapp/.environment"} # Set environment variables for individual credentials. # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. export QUEUE_SCHEME="${SOLR_SCHEME}" export QUEUE_USERNAME="${SOLR_USERNAME}" export QUEUE_PASSWORD="${SOLR_PASSWORD}" export QUEUE_HOST="${SOLR_HOST}" export QUEUE_PORT="${SOLR_PORT}" # Set a single RabbitMQ connection string variable for AMQP. export AMQP_URL="${QUEUE_SCHEME}://${QUEUE_USERNAME}:${QUEUE_PASSWORD}@${QUEUE_HOST}:${QUEUE_PORT}/" ``` The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``SEARCH_URL`` can be used within the application to connect to the service. Note that ``SEARCH_URL``, and all Upsun [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) like ``SOLR_HOST``, are environment-dependent. Unlike the build produced for a given commit, they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment. A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](https://docs.upsun.com/get-started.md). ## Solr 4 For Solr 4, Upsun supports only a single core per server called `collection1`. You must provide your own Solr configuration via a `core_config` key in your `.upsun/config.yaml`: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. solr: type: "solr:4.10" configuration: core_config: !archive "" ``` points to a directory in the Git repository, in or below the `.upsun/` folder. This directory needs to contain everything that Solr needs to start a core. At the minimum, `solrconfig.xml` and `schema.xml`. For example, place them in `.upsun/solr/conf/` such that the `schema.xml` file is located at `.upsun/solr/conf/schema.xml`. You can then reference that path like this - ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. solr: type: "solr:4.10" configuration: core_config: !archive "solr/conf/" ``` ## Solr 6 and later For Solr 6 and later Upsun supports multiple cores via different endpoints. Cores and endpoints are defined separately, with endpoints referencing cores. Each core may have its own configuration or share a configuration. It is best illustrated with an example. ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. solr: type: solr:9.9 configuration: cores: mainindex: conf_dir: !archive "core1-conf" extraindex: conf_dir: !archive "core2-conf" endpoints: main: core: mainindex extra: core: extraindex ``` The above definition defines a single Solr 9.9 server. That server has 2 cores defined: - `mainindex` — the configuration for which is in the `.upsun/core1-conf` directory - `extraindex` — the configuration for which is in the `.upsun/core2-conf` directory. It then defines two endpoints: `main` is connected to the `mainindex` core while `extra` is connected to the `extraindex` core. Two endpoints may be connected to the same core but at this time there would be no reason to do so. Additional options may be defined in the future. Each endpoint is then available in the relationships definition in `.upsun/config.yaml`. For example, to allow an application to talk to both of the cores defined above its configuration should contain the following: ```yaml {location=".upsun/config.yaml"} applications: # The name of the app container. Must be unique within a project. myapp: type: "php:8.5" source: root: "myapp" [...] # Relationships enable access from this app to a given service. # The example below shows configuration with explicitly set service names and endpoints. # See the Application reference for all options for defining relationships and endpoints. relationships: solrsearch1: service: solr endpoint: main solrsearch2: service: solr endpoint: extra services: # The name of the service container. Must be unique within a project. solr: type: solr:9.9 configuration: cores: mainindex: conf_dir: !archive "core1-conf" extraindex: conf_dir: !archive "core2-conf" endpoints: main: core: mainindex extra: core: extraindex ``` That is, the application's environment would include a `solrsearch1` relationship that connects to the `main` endpoint, which is the `mainindex` core, and a `solrsearch2` relationship that connects to the `extra` endpoint, which is the `extraindex` core. The relationships array would then look something like the following: ```json { "solrsearch1": [ { "path": "solr/mainindex", "host": "248.0.65.197", "scheme": "solr", "port": 8080 } ], "solrsearch2": [ { "path": "solr/extraindex", "host": "248.0.65.197", "scheme": "solr", "port": 8080 } ] } ``` ### Configsets For even more customizability, it's also possible to define Solr configsets. For example, the following snippet would define one configset, which would be used by all cores. Specific details can then be overridden by individual cores using `core_properties`, which is equivalent to the Solr `core.properties` file. ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. solr: type: solr:9.9 configuration: configsets: mainconfig: !archive "configsets/solr8" cores: english_index: core_properties: | configSet=mainconfig schema=english/schema.xml arabic_index: core_properties: | configSet=mainconfig schema=arabic/schema.xml endpoints: english: core: english_index arabic: core: arabic_index ``` In this example, `.upsun/configsets/solr8` contains the configuration definition for multiple cores. There are then two cores created: - `english_index` uses the defined configset, but specifically the `.upsun/configsets/solr8/english/schema.xml` file - `arabic_index` is identical except for using the `.upsun/configsets/solr8/arabic/schema.xml` file. Each of those cores is then exposed as its own endpoint. Note that not all core properties features make sense to specify in the `core_properties`. Some keys, such as `name` and `dataDir`, aren't supported, and may result in a `solrconfig` that fails to work as intended, or at all. ### Default configuration #### Default for version 9+ If you don't specify any configuration, the following default is used: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. solr: type: solr:9.9 configuration: cores: collection1: conf_dir: !archive "example" endpoints: solr: core: collection1 ``` The example configuration directory is equivalent to the [Solr example configuration set](https://github.com/apache/solr/tree/main/solr/server/solr/configsets/sample_techproducts_configs/conf). This default configuration is designed only for testing. You are strongly recommended to define your own configuration with a custom core and endpoint. #### Default for versions below 9 If you don't specify any configuration, the following default is used: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. solr: type: solr:8.4 configuration: cores: collection1: {} endpoints: solr: core: collection1 ``` The default configuration is based on an older version of the Drupal 8 Search API Solr module that is no longer in use. You are strongly recommended to define your own configuration with a custom core and endpoint. ### Limitations The recommended maximum size for configuration directories (zipped) is 2MB. These need to be monitored to ensure they don't grow beyond that. If the zipped configuration directories grow beyond this, performance declines and deploys become longer. The directory archives are compressed and string encoded. You could use this bash pipeline ```bash echo $(($(tar czf - . | base64 | wc -c )/(1024*1024))) Megabytes ``` inside the directory to get an idea of the archive size. The configuration directory is a collection of configuration data, like a data dictionary, e.g. small collections of key/value sets. The best way to keep the size small is to restrict the directory context to plain configurations. Including binary data like plugin `.jar` files inflates the archive size, and isn't recommended. ## Accessing the Solr server administrative interface Because Solr uses HTTP for both its API and admin interface it's possible to access the admin interface over an SSH tunnel. ```bash upsun tunnel:single --relationship ``` By default, this opens a tunnel at `127.0.0.1:30000`. You can now open `http://localhost:30000/solr/` in a browser to access the Solr admin interface. Note that you can't create indexes or users this way, but you can browse the existing indexes and manipulate the stored data. ## Available plugins This is the complete list of plugins that are available and loaded by default: | Plugin | Description | 8.11 | 9.x | |------------------------------------------------------------------------------------|--------------------------------------------------------|------|-----| | [JTS](https://solr.apache.org/guide/8_1/spatial-search.md#jts-and-polygons-flat) | Library for creating and manipulating vector geometry. |* |* | | [ICU4J](https://solr.apache.org/guide/8_3/language-analysis.md) | Library providing Unicode and globalization support. |* |* | ## Upgrading The Solr data format sometimes changes between versions in incompatible ways. Solr doesn't include a data upgrade mechanism as it is expected that all indexes can be regenerated from stable data if needed. To upgrade (or downgrade) Solr you need to use a new service from scratch. There are two ways of doing that. ### Destructive In your `.upsun/config.yaml` file, change the version of your Solr service *and* its name. Be sure to also update the reference to the now changed service name in it's corresponding application's `relationship` block. When you push that to Upsun, the old service is deleted and a new one with the name is created, with no data. You can then have your application re-index data as appropriate. This approach has the downside of temporarily having an empty Solr instance, which your application may or may not handle gracefully, and needing to rebuild your index afterward. Depending on the size of your data that could take a while. ### Transitional For a transitional approach you temporarily have two Solr services. Add a second Solr service with the new version a new name and give it a new relationship in `.upsun/config.yaml`. You can optionally run in that configuration for a while to allow your application to populate indexes in the new service as well. Once you're ready to cut over, remove the old Solr service and relationship. You may optionally have the new Solr service use the old relationship name if that's easier for your application to handle. Your application is now using the new Solr service. This approach has the benefit of never being without a working Solr instance. On the downside, it requires two running Solr servers temporarily, each of which consumes resources and need adequate disk space. Depending on the size of your data that may be a lot of disk space. --- # Source: https://docs.upsun.com/create-apps/source-operations.md # Source operations On Upsun, you can run automated code updates through a feature called **source operations**. Defined in your [app configuration](https://docs.upsun.com/create-apps.md), source operations let you specify commands that can commit changes to your project's repository when called. For example, you can set up a source operation to [automatically update your application dependencies](https://docs.upsun.com/learn/tutorials/dependency-updates.md), [update a site from an upstream repository](#update-a-site-from-an-upstream-repository-or-template), or [revert to the last commit](#revert-to-the-last-commit) pushed to your Git repository. To run your source operations, you can use the [Upsun CLI](https://docs.upsun.com../administration/cli.md) or the [Console](https://console.upsun.com). If you want to run your source operations and update your code automatically, you can also define [cron jobs](https://docs.upsun.com/create-apps/image-properties/crons.md). ## How source operations work When you trigger a source operation, the following happens in order: 1. The current environment HEAD commit is checked out in Git. It doesn't have any remotes or tags defined in the project. It only has the current environment branch. 2. Sequentially, for each app that has an operation bearing [the name](#define-a-source-operation) of the triggered source operation in its configuration, the operation command is run in the app container. The container isn't part of the environment's runtime cluster and doesn't require that the environment is running. The environment has all of the variables normally available during the build phase. These may be optionally overridden by the variables specified when the operation is run. 3. If any new commits were created, they're pushed to the repository and the normal build process is triggered. If multiple apps in a single project both result in a new commit, there are two distinct commits in the Git history but only a single new build process. ## Define a source operation A source operation requires two things: - A name that must be unique within the application. The name is the key of the block defined under `source.operations` in your [app configuration](https://docs.upsun.com/create-apps/image-properties/source.md). - A `command` that defines what's run when the operation is triggered. The syntax is similar to the following: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: nodejs:24 source: root: "/" operations: : command: ``` For example, to update a file from a remote location, you could define an operation like this: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: nodejs:24 source: root: "/" operations: update-file: command: | set -e curl -O https://example.com/myfile.txt git add myfile.txt git commit -m "Update remote file" ``` The name of the source operation in this case is `update-file`. For more possibilities, see other [source operation examples](#source-operation-examples). ## Run a source operation Run the following command: ```bash {} upsun source-operation:run ``` Replace with the name of your operation, such as ``update-file`` in the [example above](#define-a-source-operation). After running a source operation, to apply the changes to your local development environment run the `git pull` command. Note that you can [cancel pending or running source operations](https://docs.upsun.com../environments/cancel-activity.md). ## Use variables in your source operations You can add [variables](https://docs.upsun.com../development/variables.md) to the environment of the source operation. Use the `env:` prefix to expose each of those variables as a Unix environment variable. In this way, they're referenced by the source operation and interpreted the same way as any other variable set in your project. For example, you might want to have a `FILE` variable available with the value `example.txt` to pass to a source operation similar to the following: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: nodejs:24 source: root: "/" operations: update-file: command: | set -e curl -O https://example.com/$FILE git add $FILE git commit -m "Update remote file" ``` Follow these steps to run the source operation: ```bash {} upsun source-operation:run update-file --variable env:FILE="example.txt" ``` ## Source integrations If your project is using a [source integration](https://docs.upsun.com../integrations/source.md), any new commits resulting from a source operation are first pushed to your external Git repository. Then the source integration pushes those commits to Upsun and redeploys the environment. When using a source integration, you can't run source operations on environments created from pull or merge requests created on the external repository. If you try running a source operation on a non-supported environment, you see the following error: ```text {no-copy="true"} [ApiFeatureMissingException] This project doesn't support source operations. ``` ## Automated source operations using a cron job You can use a cron to automatically run your source operations. Note that it’s best not to run source operations on your production environment, but rather on a dedicated environment where you can test changes. Make sure you have the [Upsun CLI](https://docs.upsun.com../administration/cli.md) installed and [an API token](https://docs.upsun.com../administration/cli/api-tokens.md#2-create-an-api-token) so you can run a cron job in your app container. 1. Set your API token as a top-level environment variable: - Open the environment where you want to add the variable. - Click Settings **Settings**. - Click **Variables**. - Click **+ Add variable**. - In the **Variable name** field, enter ``env:UPSUN_CLI_TOKEN``. - In the **Value** field, enter your API token. - Make sure the **Available at runtime** and **Sensitive variable** options are selected. - Click **Add variable**. **Note**: Once you add the API token as an environment variable, anyone with [SSH access](https://docs.upsun.com/development/ssh.md) can read its value. Make sure you carefully check your [user access on this project](https://docs.upsun.com/administration/users.md#manage-project-users). 2. Add a build hook to your app configuration to install the CLI as part of the build process: ```yaml {location=".upsun/config.yaml"} applications: myapp: hooks: build: | set -e echo "Installing Upsun CLI" curl -fsSL https://raw.githubusercontent.com/platformsh/cli/main/installer.sh | bash echo "Testing Upsun CLI" upsun ``` 3. Then, to configure a cron job to automatically run a source operation once a day, use a configuration similar to the following: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: nodejs:24 source: root: "/" operations: update-file: command: | set -e curl -O https://example.com/$FILE git add $FILE git commit -m "Update remote file" crons: update: # Run the code below every day at midnight. spec: '0 0 * * *' commands: start: | set -e upsun sync -e development code data --no-wait --yes upsun source-operation:run update-file --no-wait --yes ``` The example above synchronizes the `development` environment with its parent and then runs the `update-file` source operation defined [previously](#define-a-source-operation). ## Source operation examples ### Update your application dependencies You can set up a source operation and a cron job to [automate your dependency updates](https://docs.upsun.com/learn/tutorials/dependency-updates.md). ### Update a site from an upstream repository or template The following source operation syncronizes your branch with an upstream Git repository. 1. [Add a project-level variable](https://docs.upsun.com../development/variables/set-variables.md#create-project-variables) named `env:UPSTREAM_REMOTE` with the Git URL of the upstream repository. That makes that repository available as a Unix environment variable in all environments, including in the source operation's environment. - Variable name: `env:UPSTREAM_REMOTE` - Variable example value: `https://github.com/platformsh/platformsh-docs` 2. In your app configuration, define a source operation to fetch from that upstream repository: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: nodejs:24 source: root: "/" operations: upstream-update: command: | set -e git remote add upstream $UPSTREAM_REMOTE git fetch --all git merge upstream/main ``` 3. Now every time you run the `upstream-update` operation on a given branch, the branch fetches all changes from the upstream git repository and then merges the latest changes from the default branch in the upstream repository. If there’s a conflict merging from the upstream repository, the source operation fails and doesn't update from the upstream repository. Run the `upstream-update` operation on a preview environment rather than directly on Production. ### Revert to the last commit The following source operation reverts the last commit pushed to the Git repository. This can be useful if you didn't properly test the changes of another operation and you need to quickly revert to the previous state. ```yaml {location=".upsun/config.yaml"} applications: myapp: type: nodejs:24 source: root: "/" operations: revert: command: | git reset --hard HEAD~ ``` Now every time you run the `revert` operation on a given branch, the operation reverts to the last commit pushed to that branch. ### Update Drupal Core The following source operation uses Composer to update Drupal Core: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: php:8.5 source: root: "/" operations: update-drupal-core: command: | set -e composer update drupal/core --with-dependencies git add composer.lock git commit -m "Automated Drupal Core update." ``` `--with-dependencies` is used to also update Drupal Core dependencies. Read more on how to [update Drupal Core via Composer on Drupal.org](https://www.drupal.org/docs/updating-drupal/updating-drupal-core-via-composer). Now every time you run the `update-drupal-core` operation, it updates Drupal Core. ### Download a Drupal extension The following source operation downloads a Drupal extension. You can define the Drupal extension by setting an `EXTENSION` variable or [overriding it](#use-variables-in-your-source-operations) when running the source operation. ```yaml {location=".upsun/config.yaml"} applications: myapp: type: php:8.5 source: root: "/" operations: download-drupal-extension: command: | set -e composer require $EXTENSION git add composer.json git commit -am "Automated install of: $EXTENSION via Composer." ``` Now every time you run the `download-drupal-extension` operation, it downloads the defined extension. If it's a new extension, after the source operation finishes, you need to enable the new extension via the Drupal management interface or using Drush. ### Update Git submodules The following source operation updates all Git submodules recursively: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: php:8.5 source: root: "/" operations: rebuild: command: | set -e git submodule update --init --recursive git submodule update --remote --checkout SHA=$(git submodule | awk -F' ' '{print $1}' | sed -s 's/+//g') echo -n "$SHA" > .sha git add uppler .sha git commit -m "Updating submodule to commit '$SHA'" ``` Now every time you run the `rebuild` operation, it updates the Git submodules. --- # Source: https://docs.upsun.com/integrations/source.md # Source: https://docs.upsun.com/create-apps/image-properties/source.md # source Contains information about the app’s source code and operations that can be run on it. Optional in [single-runtime](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](https://docs.upsun.com/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](https://docs.upsun.com/create-apps/source-operations.md). | | `root` | `string` | | The path where the app code lives. Useful for [multi-app setups](https://docs.upsun.com/create-apps/multi-app.md).
**Single-runtime image**: Defaults to the directory of the `.upsun/config.yaml` file.
**Composable image**: Defaults to the root project directory.| --- # Source: https://docs.upsun.com/development/ssh/ssh-keys.md # Authenticate with SSH keys To connect to your app using SSH keys, you need two keys: * A **private key** you must keep _secret_ * A **public key** stored in your Upsun account A given SSH key pair can only be linked to a single user account. A key pair is valid for as long as you have access to the private key on the system from which you are connecting. If you have a key pair available, you aren't prompted to login. To keep connection secure, you need to regularly update the keys you use. A well-encrypted key is no substitute for regular key rotation. If you used GitHub to sign up for your Upsun account your public keys from GitHub are automatically synced to your Upsun account. So you can use them already with the CLI or to [connect to your app](https://docs.upsun.com/development/ssh.md#2-connect-to-an-app-with-ssh). ## Add SSH keys If you don't have keys already added, you might be able to [find existing keys](#1a-find-your-keys) or else you need to [generate new keys](#1b-generate-new-keys). ### 1A. Find your keys If you haven't used SSH keys before or it's been a while since you created the key, skip right to [generating new keys](#1b-generate-new-keys). If you have generated SSH keys before and want to find them on your system, follow these instructions. A public key file has a name ending in `.pub`. It contains seemingly random lines of characters, like this example of a public [RSA key](https://en.wikipedia.org/wiki/RSA_%28cryptosystem%29) (note the email address at the end, which wouldn't be present in a private key): ```text {no-copy="true"} ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2nDRLgPANWParTiaGIgySG+thTtnqFGI1tMWyqDdfvH+5hL91w2tK9PzaP+NJ5hA/cOyh30YRFb52Y64toU16Ko5K1mLqNFJajjWEI5Y4VukG6betrWfqdQ7XBr/s7nBuDOFQ5+eKbvug4rRSCSo8CsEI1eI0VNQkC9HJWYK28k7KurMdTN7X/Z/4vknM4/Rm2bnMk2idoORQgomeZS1p3GkG8dQs/c0j/b4H7azxnqdcCaR4ahbytX3d49BN0WwE84C+ItsnkCt1g5tVADPrab+Ywsm/FTnGY3cJKKdOAHt7Ls5lfpyyug2hNAFeiZF0MoCekjDZ2GH2xdFc7AX/ your_email_address@example.com ``` To find your public key file: 1. Open a terminal. 2. Run the following commands: ```bash cd ~/.ssh ls -a ``` If you find a file ending in `.pub`, copy the location and [add it to your Upsun account](#2-add-an-ssh-key-to-your-account). If you don't find an existing key, [generate new keys](#1b-generate-new-keys). ### 1B. Generate new keys If you're logged in using the [Upsun CLI](https://docs.upsun.com/development/ssh.md#1-authenticate-with-the-cli), generate a key and have it added to your Upsun account automatically. 1. In a terminal, run `upsun ssh-key:add`. 1. If necessary, log in to a browser. 1. Press `Y` and `enter` to create a new SSH key. 1. Copy the location of the generated key. 1. Run the following commands (replacing `` with the location you copied): ```bash eval $(ssh-agent) ssh-add '' ``` To generate a key otherwise, GitHub has a good [walk-through for creating SSH key pairs](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) on various operating systems. Then you need to [add it to your Upsun account](#2-add-an-ssh-key-to-your-account). ### 2. Add an SSH key to your account Once you have the location of your public key, add it to your Upsun account. If you're logged in using the [Upsun CLI](https://docs.upsun.com/development/ssh.md#1-authenticate-with-the-cli), in a terminal run the following command (replacing `` with the location of your public key): ```bash upsun ssh-key:add '' ``` You can also add it in the Console. Now you are ready to use the key to [connect to an environment](https://docs.upsun.com/development/ssh.md#2-connect-to-an-app-with-ssh). ### 3. Connect to your server with SSH keys To connect to a server using SSH keys, find the details in the Console: 1. Open the [Upsun Console](https://console.upsun.com/). 1. Select a project. 1. In the **Environment** dropdown, select the environment you want to access. 1. Click the **SSH** dropdown. 1. Copy the ssh command for where you want access. (Example: `ssh abcdefghi5k-main-7rqtwti--app@ssh.us-2.upsun.com`) 1. Enter the command into a terminal. Note that if you have just added your SSH key, you need to [redeploy your environment](https://docs.upsun.com/development/ssh/troubleshoot-ssh.md#redeploy-your-environment) before you can access it using SSH keys. ## Forwarding keys by default It may be helpful to set your SSH client to always forward keys to Upsun servers, which can simplify other SSH or rsync commands. To do so, include a block in your local `~/.ssh/config` file like so: ```text Host *.us.upsun.com ForwardAgent yes Host *.eu.upsun.com ForwardAgent yes ``` Include one `Host` entry for each Upsun region you want to connect to, such as `us-2` or `eu-4`. (You can include other configuration as desired.) --- # Source: https://docs.upsun.com/development/ssh.md # Connect securely with SSH When you interact with a deployed environment, you need to guard your connection against unauthorized access. Use Secure Shell (SSH) to provide a secure channel. You can securely log in to your deployed app to troubleshoot and read logs. And create a tunnel to export data through. And interact with your project through the CLI. All secured through SSH. ## Connect to apps To connect to an app securely with SSH, follow two steps. ### 1. Authenticate with the CLI To authenticate with the CLI: 1. Install the [Upsun CLI](https://docs.upsun.com/administration/cli.md). 2. Run `upsun login`. 3. In the open browser window, log in with your Upsun account credentials. (This webpage is encrypted with [HTTPS](https://docs.upsun.com/define-routes/https.md), making it secure.) 4. Authorize the CLI to use your account. A certificate gets stored in your local SSH configuration. The certificate is automatically cycled every hour for a new certificate as long as your session is active. If you are inactive for an extended period, your certificate expires and you are asked to login again the next time you use a command that requires authentication. You are now ready to run CLI commands and connect to an environment. ### 2. Connect to an app with SSH To access an app in a given environment via the CLI, run the following command: ```bash upsun ssh --project --environment --app ``` Replace each of ````, ````, and ```` with the values you want to access. To find these values in the Console, navigate to the environment you want to access and click **SSH** in the top right-hand corner. Alternatively, just run `upsun ssh` and select the values from each list presented to you. Once you've connected, you get a welcome message detailing which environment you're connected to. Now you can interact with the environment as you want. Note that your app's file system is read-only, except for any [mounts you've defined](https://docs.upsun.com/create-apps/image-properties/mounts.md). ## Connect to services To connect to a service, you need the [service credentials](https://docs.upsun.com../../add-services.md#connect-to-a-service). Then you can connect either with a [direct tunnel](#use-a-direct-tunnel) or a [tunnel in your app](#use-an-app-tunnel). ### Use a direct tunnel To open SSH tunnels for all of your services, run the following command: ```bash upsun tunnel:open ``` You get output similar to the following: ```bash SSH tunnel opened to database at: http://127.0.0.1:30000 Logs are written to: ~/.upsun/tunnels.log List tunnels with: upsun tunnels View tunnel details with: upsun tunnel:info Close tunnels with: upsun tunnel:close Save encoded tunnel details to the PLATFORM_RELATIONSHIPS variable using: export PLATFORM_RELATIONSHIPS="$(platform tunnel:info --encode)" ``` Use the returned host (in this case `http://127.0.0.1:30000`) for your connection and fill in the details with the rest of your [service credentials](https://docs.upsun.com../../add-services.md#connect-to-a-service). The `tunnel:open` command connects all relationships defined in your [app configuration](https://docs.upsun.com../../create-apps.md). To open only one connection when you have multiple relationships defined, run `tunnel:single`. By default, this opens a tunnel at `http://127.0.0.1:30000`. You can specify the port for the connection using the `--port` flag. ### Use an app tunnel Many database applications (such as MySQL Workbench) support establishing their own SSH tunnel. You need to use [SSH keys](https://docs.upsun.com/development/ssh/ssh-keys.md) for authentication. Consult the documentation for your application for how to enter SSH credentials. #### Get SSH connection details To get the host and username for connections, follow these steps: You get output similar to the following: ```bash {} jyu7waly36ncj-main-7rqtwti--app@ssh.us.upsun.com ``` - Navigate to the environment you want to connect to. - Click **SSH** in the top right-hand corner. - You get output similar to the following: ``jyu7waly36ncj-main-7rqtwti--app@ssh.us.upsun.com`` The host is everything after the `@` and the username is what's before it. In this case, the host is `ssh.us.upsun.com` and the username is `jyu7waly36ncj-main-7rqtwti--app`. The host is the same for the entire project, while the username varies by environment. To connect to a service, fill in the details with the rest of your [service credentials](https://docs.upsun.com../../add-services.md#connect-to-a-service). ## Alternative authentication methods There are three basic ways to authenticate with Upsun: * [Through the CLI](#1-authenticate-with-the-cli) * The fastest and easiest method. * Supports multifactor authentication. * Automatically generates new certificates to keep your connection safe. * Necessary when using the CLI and when your organization has multifactor authentication set up. * [Using SSH keys](https://docs.upsun.com/development/ssh/ssh-keys.md) * Requires more setup on your part. * Represents only a single authentication method. * Requires you to regularly change the keys to maintain security. * Useful for checking out code as part of an automated process. * [Using API tokens](https://docs.upsun.com../../administration/cli/api-tokens.md) * Good for letting automation tools use the CLI. * Requires you to regularly change the tokens to maintain security. ## SSH into an MFA-protected environment For enhanced security, as an organization owner or admin user, you can [enforce multifactor authentication (MFA) within your organization](https://docs.upsun.com/administration/security/mfa.md#enforce-mfa-within-your-organization). As a project contributor, if you haven't enabled MFA on your user account and SSH into an environment that is protected by MFA, you get an error message. See how you can [troubleshoot that error message](https://docs.upsun.com/development/ssh/troubleshoot-ssh.md#mfa-related-error-message). --- # Source: https://docs.upsun.com/define-routes/ssi.md # Server Side Includes (SSI) SSI commands enable you to include files within other pages. At its most basic, you can include files within other ones so as not to repeat yourself. Start by enabling SSI: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": type: upstream upstream: "myapp:http" ssi: enabled: true ``` Then create a file you want to include elsewhere: ```html {location="includes/example.html"} This content can be reused ``` And include it in another file: ```html {location="index.html"} This content is unique to this page. ``` And your final rendered page includes the other file: ```html {location="index.html"} This content is unique to this page. This content can be reused ``` ## Caching and dynamic content You can use SSI to have [caching](https://docs.upsun.com/define-routes/cache.md) and dynamic content in one. So one file is cached, while another updates dynamically. For example, you can activate SSI on one route with cache disabled and enable cache on another route: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": type: upstream upstream: "myapp:http" ssi: enabled: true cache: enabled: false "https://{default}/cache": type: upstream upstream: "myapp:http" cache: enabled: true ``` Then create a page that displays the current date and time and is cached for 60 seconds (the example uses PHP, but any server-side language would work): ```php {location="cache/example.php"} ``` Then you can visit `index.php` and refresh the page a few times. You see the first number updating to the current time, while the second (included) one only changes every 60 seconds. For more on SSI, see the [nginx documentation](https://nginx.org/en/docs/http/ngx_http_ssi_module.md). --- # Source: https://docs.upsun.com/administration/security/sso.md # Single Sign-On (SSO) **Feature Availability** This feature is available as part of the Advanced User Management add-on. You can [upgrade your organization to this add-on](https://docs.upsun.com/administration/billing/add-on-subscription.md#upgrade-to-the-advanced-user-management-add-on) in the Console. For details about the other features included in this add-on, see the [Advanced User Management add-on](https://docs.upsun.com/administration/billing/add-on-subscription.md#advanced-user-management-add-on) help topic section; for pricing information, see the [Upsun pricing](https://upsun.com/pricing/) page. Upsun enables you to set up mandatory SSO with a third-party identity provider (IdP) for all your users. Your SSO provider can be enabled for a specific email domain, for example `@example.com`. Every user with a matching email address needs to log in or register on Upsun using your SSO provider. Such users can't use an alternative provider, or register a password, or change their email address. ## Mitigation controls If you deactivate a user on your identity provider, they can't log in or register on Upsun. If the user is already logged in to Upsun, they are automatically deactivated after their access token has expired (generally after 1 hour). A deactivated user can no longer use SSH, Git, or other Upsun APIs. ## Service users If you have a service user with an email address under your SSO domain, such as `machine-user@example.com`, you can exclude that user from the SSO enforcement rule so they aren't required to authenticate through your identity provider. Please open a [support ticket](https://docs.upsun.com/learn/overview/get-support.md) if you need to exclude a service user. ## SSO providers ### Google Enforce your users to authenticate with Google. To enable Google SSO, please open a [support ticket](https://docs.upsun.com/learn/overview/get-support.md). #### Issue with re-authenticating every 15 minutes If your organization has Google SSO enabled on Upsun, you may be required to re-authenticate with Google every 15 minutes. This happens when Upsun doesn't possess a valid refresh token from your Google account. To resolve this issue: 1. Go to [https://myaccount.google.com/permissions](https://myaccount.google.com/permissions) and revoke the access from the `Upsun` application that has `Access given to auth.api.platform.sh`. 2. Go to [https://auth.upsun.com/auth/authorize/google?prompt=consent](https://auth.upsun.com/auth/authorize/google?prompt=consent) for the system to obtain a valid refresh token for your Google account. ### OpenId Connect Enforce your users to authenticate with your OpenID Connect (OIDC) provider, such as Microsoft (Entra ID), Okta, Ory, or Ping Identity. To enable SSO with your OIDC provider, please [create a Support ticket](https://console.upsun.com/-/users/~/tickets). --- # Source: https://docs.upsun.com/create-apps/web/static.md # Serve static sites Static site generators are a popular way to create fast sites. Because there's no need to wait for responses from servers, the sites may load faster. To learn how to serve your static site using Upsun, you can start with the required [minimal app configuration](#minimal-app-configuration) and build on it, or jump straight to an [example of a complete configuration](#complete-example-configuration). ## Minimal app configuration To successfully serve a static site using Upsun, you need to set up a minimal app configuration similar to the following: ```yaml {location=".upsun/config.yaml"} applications: myapp: # The type of the application to build. type: "nodejs:24" source: root: "/" # The web key configures the web server running in front of your app. web: locations: /: # Static site generators usually output built static files to a specific directory. # Define this directory (must be an actual directory inside the root directory of your app) # as the root for your static site. root: "public" # Files to consider when serving a request for a directory. index: - index.html ``` See more information on the required minimal settings: - [Top-level properties](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#primary-application-properties). - [`web` property](https://docs.upsun.com/create-apps/image-properties/web.md). - [`locations` properties](https://docs.upsun.com/create-apps/image-properties/web.md#locations). ## Add more features ### Allow static files but not dynamic files on PHP containers If you have a PHP container, you might want to enable client-side scripts but disable server-side scripts. To enable static files that don't match any rule while disabling server-side scripts on a PHP container, use the following configuration: ```yaml {location=".upsun/config.yaml"} applications: myapp: # The type of the application to build. type: "nodejs:24" source: root: "/" web: locations: '/': ... scripts: false allow: true ``` See more information on [`locations` properties](https://docs.upsun.com/create-apps/image-properties/web.md#locations). ### Create cache rules You can create sensible cache rules to improve performance. For example, if you publish new content regularly without updating images or site files much, you might want to cache text files for a day but all image files for longer. To do so, use a configuration similar to the following: ```yaml {location=".upsun/config.yaml"} applications: myapp: # The type of the application to build. type: "nodejs:24" source: root: "/" web: locations: '/': ... expires: 24h rules: \.(css|js|gif|jpe?g|png|svg)$: expires: 4w ``` You can also set a `Cache-Control` header in your rules. ```yaml {location=".upsun/config.yaml"} applications: myapp: web: locations: '/': ... expires: 24h rules: \.(css|js|gif|jpe?g|png|svg)$: headers: Cache-Control: "public, max-age=2419200, immutable" ``` If `expires` and a `Cache-Control` header are set, the rule ignores the `expires` and sets only the `Cache-Control` header. For this reason, make sure to add a `max-age` value, in seconds, for the `Cache-Control` header. ### Conserve the server Because your site is completely static, it doesn't need the server to be running. To set a background process that blocks the server and conserves resources, use the following configuration: ```yaml {location=".upsun/config.yaml"} applications: myapp: # The type of the application to build. type: "nodejs:24" source: root: "/" web: commands: start: sleep infinity ``` You can also use this place to start small programs, such as a [script to handle 404 errors](https://support.platform.sh/hc/en-us/community/posts/16439636723474). ## Complete example configuration ```yaml {location=".upsun/config.yaml"} applications: myapp: # The type of the application to build. type: "python:3.14" source: root: "/" web: locations: '/': # The public directory of the application relative to its root root: 'public' # The files to look for when serving a directory index: - 'index.html' # Disable server-side scripts scripts: false allow: true # Set caching policy expires: 24h rules: \.(css|js|gif|jpe?g|png|svg)$: expires: 4w commands: # Run a no-op process that uses no CPU resources since this is a static site start: sleep infinity ``` --- # Source: https://docs.upsun.com/domains/steps.md # Set up a custom domain Once your project is ready for production, replace the automatically generated domain with your own custom domain. Note that adding a domain disables the automatically generated URL for your Production environment only. You can also [customize the URLs for your preview environments](https://docs.upsun.com/domains/steps/custom-domains-preview-environments.md). ## Before you begin You need: - A project that's ready to go live - A domain with access to its settings with the registrar - A registrar that allows `CNAME` records or [one of the alternatives](https://docs.upsun.com/domains/steps/dns.md) on [apex domains](https://docs.upsun.com/glossary.md#apex-domain) - Optional: The [CLI](https://docs.upsun.com../../administration/cli.md) installed locally If you are planning to use several subdomains of the same domain on different projects, see how to [manage multiple subdomains](https://docs.upsun.com/domains/steps/subdomains.md) *before* you add your domain to Upsun. ## 1. Get the target for your project You want to point your DNS record to the automatically generated URL. Your domain needs to point to that target for your site to go live. - Navigate to your production environment and click **Settings Settings**. - Select the **Domains** tab. - In the **Configure your domain** section, copy the content of the **CNAME record** field. ## 2. Configure your DNS provider Your DNS provider (usually your registrar) is where you manage your domain. Most registrars offer similar functionalities regarding DNS configuration but use different terminology or configuration. For example, some registrars require you to use an `@` to create custom records on the apex domain, while others don't. Check your registrar's documentation. Note that depending on your registrar and the time to live (TTL) you set, it can take anywhere from 15 minutes to 72 hours for DNS changes to be taken into account. To configure your CDN and your domain name to point to your project: - Open your CDN’s management system. - Point the CDN at your [target](#1-get-the-target-for-your-project). - Open your registrar’s domain management system. - Open your registrar’s domain management system and configure your DNS zone settings to point at your CDN. The address or ``CNAME`` record to use varies by CDN provider. Refer to the official documentation of your DNS provider and CDN provider. - Check that redirects and subdomains are set correctly for the [TLS certificate ownership verification](https://docs.upsun.com/domains/troubleshoot.md#ownership-verification). - [Disable the router cache](https://docs.upsun.com/domains/cdn.md#disable-the-router-cache). - Optional: For increased security and to prevent the CDN from being bypassed, you can force all traffic to [go through the CDN](https://docs.upsun.com/domains/cdn.md#prevent-direct-access-to-your-server). - Optional: If you have multiple domains you want to be served by the same app, add a ``CNAME`` record for each of them. That includes the ``www`` subdomain if you are using it in your [routes configuration](https://docs.upsun.com/define-routes.md). Adding a custom domain sets your site as [visible to search engines](https://docs.upsun.com/environments/search-engine-visibility.md#how-its-done). See how you can further [configure your CDN](https://docs.upsun.com/domains/cdn.md). ## 3. Set your domain Add a single domain to your project: - Select the project where you want to add a domain. - Click Settings **Settings**. - Click **Domains**. - In the **Domain** field, enter your domain. - Click **Add domain**. ## What's next * [Use a content delivery network](https://docs.upsun.com../cdn.md) * [Use subdomains across multiple projects](https://docs.upsun.com/domains/steps/subdomains.md) * [Use a custom TLS certificate](https://docs.upsun.com/domains/steps/tls.md) --- # Source: https://docs.upsun.com/learn/overview/structure.md # Structure Each environment you deploy on Upsun is built as a set of containers. Each container is an isolated instance with specific resources. Each environment has 2 to 4 types of containers, all usually configured from your `.upsun/config.yaml` file. - One [*router*](#router) - One or more [*app* containers](#apps) - Zero or more [*service* containers](#services) - Zero or more [*worker* containers](#workers) If you have two app containers, two services (a database and a search engine), and a worker, requests to your environment might look something like this: ![A user request goes to the router, which sends it to either a Node.js app or a Python app. Each app communicates separately with the database and search services and sends responses to the user. The Node.js app triggers actions in a worker, which communicates separately with the database.](https://docs.upsun.com/images/config-diagrams/structure-diagram.png) If you have only one app container, your repository might look like this: ```text {no-copy="true"} project ├── .git ├── .upsun │ └── config.yaml └── ``` ## Router Each environment always has exactly one router. This router maps incoming requests to the appropriate app container and provides basic caching of responses, unless configured otherwise. The router is configured in a `.upsun/config.yaml` file. If you don't include configuration, a single [default route is deployed](https://docs.upsun.com/define-routes.md#default-route-definition). Read more about how to [define routes](https://docs.upsun.com/define-routes.md). ## Apps You always need at least one app container, but you can have more. App containers run the code you provide via your Git repository. They handle requests from the outside world and can communicate with other containers within the environment. Each app container is built from a specific language image with a given version for the language. To configure your apps, you usually create a single `.upsun/config.yaml` file and place it in the repository root. Read more about how to [configure apps](https://docs.upsun.com/create-apps.md). ## Services You don't need any service containers, but you can add them as you like. Service containers run predefined code for specific purposes, such as a database or search service. You don't need to add their code yourself, just set up how your apps communicate with them. Service containers are configured by the `.upsun/config.yaml` file. Read more about how to [add services](https://docs.upsun.com/add-services.md). ## Workers You don't need any worker containers, but you can add them as you like. Worker containers are copies of an app containers that have no access to the outside world and can have a different start command. They're useful for continually running background processes. Read more about how to [work with workers](https://docs.upsun.com/create-apps/workers.md). --- # Source: https://docs.upsun.com/domains/steps/subdomains.md # Handle subdomains across different projects You can host multiple subdomains, such as `foo.example.com` and `bar.example.com`, within a single project using [routes](https://docs.upsun.com../../define-routes.md). If you try to use a subdomain that's used in another project, you get an error like the following: ```text {no-copy="true"} This domain is already claimed by another service ``` You need to add a DNS record to make it clear you explicitly allow multiple projects to use the domain. ## Enable subdomains across multiple projects To ensure multiple projects can use subdomains of the same apex domain, add a specific `TXT` DNS record for your apex domain. The `TXT` record should look like the following: ```text {no-copy="true"} _public-suffix-root. TXT "public-suffix-root=" ``` This adds your domain to the [Upsun implementation of the Public Suffix List](#why-this-is-necessary). After you add your subdomains, remove the `TXT` record to reinstate [subdomain hijacking protection](#subdomain-hijacking-protection). This ensures no other users can possibly add a subdomain of your domain to their project. Even if you don’t remove the record, your DNS records should prevent others from using a subdomain as long as you don’t use wildcards records pointing at Upsun. However, if you don't remove the `TXT` record, restrictions apply on the apex domain. For example, you can't add the apex domain to another project until you remove the `TXT` record. ## Bypass locked domains In certain cases (such as if your domain was added manually by Upsun support), your domain may be reserved for the project you added it to. Then you can't set up a second project with the bare domain (`example.com`) or a subdomain (`foo.example.com`). If that happens, [contact support](https://docs.upsun.com/learn/overview/get-support.md). Include the project ID of the project that already has the domain. ## Why this is necessary ### The Public Suffix List Domain names are segmented into different hierarchical levels, separated by a `.`. The right-most portion of the domain, such as `.com`, `.edu`, and `.fr`, is known as the top-level domain (TLD). Most applications, including web browsers, handle TLDs specially, such as by restricting certain actions. For example, a webpage at `foo.bar.baz.example.com` can usually set a cookie that's keyed to any of the following: - `foo.bar.baz.example.com` - `bar.baz.example.com` - `baz.example.com` - `example.com` So a single site can be segmented across different subdomains but use a single account login cookie. But this webpage *can't* set cookies keyed to all `.com` domains, which would be a security risk. Other restrictions apply to TLDs, but cookies are the most basic example. Aside from true TLDs, browser makers have a list of domain suffixes that should get the same special handling called the [Public Suffix List (PSL)](https://publicsuffix.org/). If you add the `example.com` domain to the PSL, browsers refuse to set a cookie on `example.com` from a page at `foo.example.com`. They still accept cookies from a page at `example.com`. ### Subdomain hijacking protection By default, a given domain can be used by only one project at a time. This security measure prevents malicious actions such as registering a project with the `evil.example.com` subdomain and using that to set cookies on your `example.com` website. When you add a domain to a project, the first level of the domain not in the [PSL](#the-public-suffix-list) is reserved. So if you add `foo.bar.baz.example.com` to a project, that project has `example.com` reserved within Upsun and no other project can have a domain anywhere in `*.example.com`. You can add multiple subdomains within that one project. Subdomain hijacking protection ensures that no other users can add a subdomain to their project as long as you don't use wildcard DNS records pointing at Upsun. In most cases, that's a desirable added layer of security. But you may run into a problem when you want multiple subdomains from the same organization as separate projects. One option would be to add `example.com` to the PSL, but you might not want or be able to do that. To limit what domains get protected, Upsun supports a small extension to the PSL. When you add a `TXT` record for your domain, Upsun treats that domain as part of the PSL. So when you add a `TXT` record for `example.com`, Upsun treats `example.com` as a top-level domain. That means it isn't reserved and is open for other projects. Then when you add a domain, the next level down from `example.com` is reserved. So if you add `foo.bar.baz.example.com` to a project, `*.baz.example.com` is reserved for that project. You can add `beep.example.com` to a different project without any issues. You can do the same for any level of subdomain. So if you set a `TXT` record for `baz.example.com` and add `foo.bar.baz.example.com` to a project, `*.bar.baz.example.com` is reserved for that project. Nothing at a higher level is reserved. --- # Source: https://docs.upsun.com/development/submodules.md # Use Git submodules ## Clone submodules during deployment Upsun allows you to use submodules in your Git repository. They're usually listed in a `.gitmodules` file at the root of your Git repository. When you push via Git, Upsun tries to clone them automatically. Say you have a multi-app project that includes the following submodules: - A BigFoot app - An API Platform v3, Admin component - A Gatsby frontend - A Mercure Rocks server To import all the submodules, run the following commands from your multiple application project's root folder: ```bash touch .gitmodules git submodule add --name admin https://github.com/platformsh-templates/bigfoot-multiapp-admin.git admin git submodule add --name api https://github.com/platformsh-templates/bigfoot-multiapp-api.git api git submodule add --name gatsby https://github.com/platformsh-templates/bigfoot-multiapp-gatsby.git gatsby git submodule add --name mercure https://github.com/platformsh-templates/bigfoot-multiapp-mercure.git mercure git add . git commit -m "Adding submodules for Bigfoot App, API Platform Admin, Gatsby frontend and Mercure Rocks server" git push ``` Here is an example of a `.gitmodules` file: ```ini [submodule "admin"] path = admin url = https://github.com/platformsh-templates/bigfoot-multiapp-admin.git [submodule "api"] path = api url = https://github.com/platformsh-templates/bigfoot-multiapp-api.git [submodule "gatsby"] path = gatsby url = https://github.com/platformsh-templates/bigfoot-multiapp-gatsby.git [submodule "mercure"] path = mercure url = https://github.com/platformsh-templates/bigfoot-multiapp-mercure.git ``` When you run `git push`, you can see the output of the logs: ```bash Validating submodules Updating submodule ttps://github.com/platformsh-templates/bigfoot-multiapp-admin.git Updated submodule https://github.com/platformsh-templates/bigfoot-multiapp-admin.git: 549 references updated. Updating submodule ttps://github.com/platformsh-templates/bigfoot-multiapp-api.git Updated submodule https://github.com/platformsh-templates/bigfoot-multiapp-api.git: 898 references updated. Updating submodule https://github.com/platformsh-templates/bigfoot-multiapp-gatsby.git Updated submodule https://github.com/platformsh-templates/bigfoot-multiapp-gatsby.git: 257 references updated. Updating submodule https://github.com/platformsh-templates/bigfoot-multiapp-mercure.git Updated submodule https://github.com/platformsh-templates/bigfoot-multiapp-mercure.git: 124 references updated. ... ``` **Note**: If your submodule contains an independent app, see [how to configure it properly](https://docs.upsun.com/create-apps/multi-app/project-structure.md#split-your-code-source-into-multiple-git-submodule-repositories). ## Update submodules **Note**: To specify which submodule needs to be updated, replace ``[submodule]`` with your submodule path. **Note**: Deploy keys only grant access to a single repository, which can cause issues when attempting to pull several repositories to the same server. If your server needs access to multiple repositories, follow these steps: - [Create a machine user](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/managing-deploy-keys#machine-users) with access rights to each of the private repositories. - Attach the deploy key to your machine user. ## Removing submodules These steps aren't specific to Upsun, but kept as a reference for Git so that submodules are effectively removed before entering the build process. 1. In your `.gitmodules` and `.git/config` files, delete the information related to the submodule you want to remove. ```bash git submodule deinit -f path_to_submodule ``` 2. Stage changes to `.gitmodules`: ```bash git add .gitmodules ``` 3. Remove the submodule from the repository (without trailing slash): ```bash git rm --cached path_to_submodule ``` 4. Remove the submodule files in `.git` from the repository (without trailing slash): ```bash rm -rf .git/modules/path_to_submodule ``` 5. Commit the changes: ```bash git commit -m "Removed submodule." ``` 6. Remove the submodule code locally, now no longer tracked: ```bash rm -rf path_to_submodule ``` --- # Source: https://docs.upsun.com/languages/php/swoole.md # Swoole p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. Swoole is a PHP extension that extends PHP core with a coroutine based asynchronous network application framework designed for building large scale concurrent systems. Unlike PHP-FPM’s stateless operating, Swoole relies on establishing persistent connections with every user, sending and receiving data in real-time. [Swoole](https://github.com/swoole/swoole-src) and [Open Swoole](https://openswoole.com/) are two forked libraries pursuing that goal. **Note**: The ``swoole`` and ``openswoole`` extensions are [available by default](https://docs.upsun.com/languages/php/extensions.md) on Upsun PHP 8.2 Upsun containers. For other versions of PHP, you can install both extensions manually by following the instructions on this page. You need: - PHP 7.3+ for Swoole - PHP 7.4.0+ for Open Swoole - The [Swoole installation script](https://raw.githubusercontent.com/platformsh/snippets/main/src/install_swoole.sh). **Note**: Currently, the installation script is compatible with PHP <=8.0. It is **not** compatible with PHP 8.3, and the ``swoole`` and ``openswoole`` extensions are **not** available on Upsun PHP 8.3 containers yet. ## Install Install the PHP extension for Swoole or Open Swoole during the build. Take advantage of an [installation script](https://raw.githubusercontent.com/platformsh/snippets/main/src/install_swoole.sh). You need to pass 2 parameters: * Which Swoole project to use: `openswoole` or `swoole` * Which version to install ```yaml {location=".upsun/config.yaml"} applications: app: type: 'php:' hooks: build: | set -e ... curl -fsS https://raw.githubusercontent.com/platformsh/snippets/main/src/install_swoole.sh | { bash /dev/fd/3 openswoole 4.11.0 ; } 3<&0 ``` ## Use Override the default web server with a [custom start command](https://docs.upsun.com/languages/php.md#alternate-start-commands). Octane should listen on a TCP socket. ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'php:8.5' web: upstream: socket_family: tcp protocol: http commands: start: php --port=$PORT locations: "/": passthru: true scripts: false allow: false ``` --- # Source: https://docs.upsun.com/administration/teams.md # Administer teams **Feature Availability** This feature is available as part of the Advanced User Management add-on. You can [upgrade your organization to this add-on](https://docs.upsun.com/administration/billing/add-on-subscription.md#upgrade-to-the-advanced-user-management-add-on) in the Console. For details about the other features included in this add-on, see the [Advanced User Management add-on](https://docs.upsun.com/administration/billing/add-on-subscription.md#advanced-user-management-add-on) help topic section; for pricing information, see the [Upsun pricing](https://upsun.com/pricing/) page. Organizations on Upsun are made up of both [projects](https://docs.upsun.com/projects/) and [users](https://docs.upsun.com/administration/users.md). While organizations by themselves allow you to assign project and environment type permissions to individual users on individual projects, having many users and many projects calls for another method to group common access control settings. **Teams** provide a grouping that connects a subset of an organization's users to another subset of that organization's projects. That relationship enables organization owners to set default project and environment type access settings for each user and project from one place. There is no limit to the number of teams that can be defined within a single organization. ## Create a new team As an organization owner or member with **Manage users** permissions, you can create new teams. Teams must belong to an organization, so [create one](https://docs.upsun.com/administration/organizations.md) first. You can create new organizations with different payment methods and billing addresses and organize your projects as you want, but keep in mind that both users and teams are restricted to single organizations. - Run the following command: ```bash {} upsun team:create -o ``` - Enter a team name. - Define your team’s project role (admin or viewer). - If your team has viewer rights on the project, define its role on each type of environment. - Enter ``Y`` to confirm. **Note**: To view a list of all the existing teams in your organization, run the following command: ```bash {} upsun team:list -o ``` ## Delete an existing team As an organization owner or member with **Manage users** permissions, you can delete existing teams. Note that deleting teams and deleting users are not equivalent. Deleting a team will remove member access permissions to projects described by the team, but it will _not_ [remove users from the organization](https://docs.upsun.com/administration/users.md#remove-a-user-from-an-organization) (or your billing). - Run the following command: ```bash {} upsun team:delete -o ``` - Select the team you want to delete. - Enter ``Y`` to confirm. ## Manage team settings As an organization owner or member with **Manage users** permissions, you can manage the settings of existing teams such as: - [It's name](#team-name) - [The environment type permissions granted to members on individual projects](#project--environment-type-permissions) - [Team members](#team-members) - [Project access](#team-access-to-projects) ### Team name - Run the following command: ```bash {} upsun team:update -o ``` - Select the team you want to rename. - Enter the new name. - Confirm or adjust the team permissions. - Enter ``Y`` to confirm. ### Project & environment type permissions The primary purpose of teams is to allow organizations to quickly apply, audit, and update project and environment type permissions for groups of users. - Run the following command: ```bash {} upsun team:update -o ``` - Select the team whose permissions you want to update. - Confirm or adjust the team name. - Adjust the team permissions. - Enter ``Y`` to confirm. ### Team members #### Add users to a team To join a team, a user must already have been added [to the organization](https://docs.upsun.com/administration/users.md#manage-organization-access), where their [organization permissions](https://docs.upsun.com/administration/users.md#organization-permissions) are defined. - Run the following command: ```bash {} upsun team:user:add -o ``` - Select the team you want to add a user to. - Enter the user’s email address. - Enter ``Y`` to confirm. **Note**: To view a list of all the users on a team, follow these steps: - Run the following command: ```bash {} upsun team:user:list -o ``` - Select the team whose users you want to display. #### Remove users from a team Note that deleting users from teams and deleting users from organizations are not equivalent. Deleting users from a team will remove member access permissions to projects described by the team, but it will _not_ [remove users from the organization](https://docs.upsun.com/administration/users.md#remove-a-user-from-an-organization) (or your billing). - Run the following command: ```bash {} upsun team:user:delete -o ``` - Select a team. - Select the user you want to remove from the team. - Enter ``Y`` to confirm. ### Team access to projects #### Adding projects to a team's access - Run the following command: ```bash {} upsun team:project:add -o ``` - Select a team. - Select the project you want the team to access. - Enter ``Y`` to confirm. **Note**: To view a list of all the projects added to a team, follow these steps: - Run the following command: ```bash {} upsun team:project:list -o ``` - Select the team whose projects you want to display. #### Remove project from team's access - Run the following command: ```bash {} upsun team:project:delete -o ``` - Select a team. - Select the project whose access you want to revoke for the team. - Enter ``Y`` to confirm. --- # Source: https://docs.upsun.com/development/local/tethered.md # Tethered local development To test changes locally, you can connect your locally running web server to service containers on an active Upsun environment. This method requires less configuration than tools such as [DDEV](https://docs.upsun.com/development/local/ddev.md), but may not perform well enough for everyday use. Because it replies on a local web server, it's also less consistent across your team. ## Before you begin You need: - A local copy of the repository for a project running on Upsun. To get one, run ``upsun get ``. Alternatively, you can clone an integrated source repository and set the remote branch. To do so, run ``upsun project:set-remote ``. - The [Upsun CLI](https://docs.upsun.com/administration/cli.md) ## Create the tethered connection 1. Create a new environment based on production. ```bash upsun branch new-feature ``` If you're using a [source integration](https://docs.upsun.com/integrations/source.md), open a merge/pull request. 1. To open an SSH tunnel to the new environment's services, run the following command: ```bash upsun tunnel:open ``` This command returns the addresses for SSH tunnels to all of your services. 1. Export the `PLATFORMSH_RELATIONSHIPS` environment variable with information from the open tunnel: ```bash export PLATFORM_RELATIONSHIPS="$(upsun tunnel:info --encode)" ``` 1. Run your application locally. Make sure it's set up to read configuration from Upsun environment variables. If you app relies on other Upsun environment configuration, such as routes or secret variables, make sure to mock those variables as well. Your options for running the app depend on the language and configuration. You can use the server for your language, install a copy of Nginx, or use a virtual machine or Docker image. 1. When you've finished your work, close the tunnels to your services by running the following command: ```bash upsun tunnel:close --all -y ``` ## Connect to services directly With open tunnels to all your services, you can also connect to the running services directly. To get information on all running services, run the following command: ```bash upsun tunnels ``` You get a response similar to the following: ```bash +-------+---------------+-------------+-----+--------------+ | Port | Project | Environment | App | Relationship | +-------+---------------+-------------+-----+--------------+ | 30000 | abcdefg123456 | new-feature | app | cache | | 30001 | abcdefg123456 | new-feature | app | database | +-------+---------------+-------------+-----+--------------+ ``` You can use the port information to connect directly to a service. If you need more detailed information, such as a path or password, run the following command: ```bash upsun tunnel:info ``` You can use the information returned to connect to the remote database as if it were local. For example, the following command would connect to a MySQL database running through a tethered connection: ```bash mysql --host=127.0.0.1 --port= --user= --password= --database= ``` ## Next steps You can now use your local environment to develop changes for review on Upsun environments. The following examples show how you can take advantage of that. ### Onboard collaborators It's essential for every developer on your team to have a local development environment to work on. Place the local configuration into a script to ensure everyone has this. You can merge this change into production. 1. Create a new environment called `local-config`. 1. To set up a local environment for a new Upsun environment, create an executable script. ```bash touch init-local.sh && chmod +x init-local.sh ``` 1. Fill it with something similar to the following example, depending on your app and configuration: ```bash {location="init-local.sh"} #!/usr/bin/env bash ENVIRONMENT=$1 PARENT=$2 # Create the new environment upsun branch $ENVIRONMENT $PARENT # Open a tunnel to the current environment upsun tunnel:open --no-interaction # Mock Upsun environment variables export PLATFORM_RELATIONSHIPS="$(upsun tunnel:info --encode)" # Add any other variables you need # If necessary, install dependencies here # Add the command to run the server ``` 1. To commit and push the revisions, run the following command: ```bash git add . && git commit -m "Add local configuration" && git push upsun local-config ``` 1. Merge the change into production. Once the script is merged into production, any user can set up their local environment by running the following commands: ```bash upsun cd ./init-local.sh another-new-feature ``` --- # Source: https://docs.upsun.com/create-apps/timezone.md # Timezones On Upsun, there are several timezones you might want to keep in mind. All timezones default to UTC time. You can customize some of them, but in most cases, it's best if you leave them in UTC and store user data with an associated timezone instead. The different timezones on Upsun are the following: | Timezone | Description |Customizable | |----------------------|----------------------------------------------|--------------| | Container timezone | The timezone for all Upsun containers (UTC). |No | | App runtime timezone | [Set an app runtime timezone](#set-an-app-runtime-timezone) if you want your app runtime to use a specific timezone instead of the container timezone.
The app runtime timezone only affects your app itself. | Yes | | Cron timezone | [Set a cron timezone](#set-a-cron-timezone) if you want your crons to run in a specific timezone instead of the app runtime timezone (or instead of the container timezone if no app runtime timezone is set on your project).
The cron timezone only affects your cron jobs. | Yes | | Log timezone | The timezone for all Upsun logs (UTC). | No | **Note**: Each Upsun project also has a **project timezone** that only affects [automated backups](https://docs.upsun.com/environments/backup.md#automated-backups). By default, the project timezone is based on the [region](https://docs.upsun.com/development/regions.md) where your project is hosted. You can [change it from the Console](https://docs.upsun.com/projects/change-project-timezone.md) at any time. ## Set an app runtime timezone How you can set an app runtime timezone depends on your actual app runtime: ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "myapp" variables: php: "date.timezone": "Europe/Paris" ``` Start the server with ``env TZ=’’ node server.js``.Start the server with ``env TZ=’’ python server.py``. - Start the server with ``env TZ=’’ java -jar …`` OR. - Set the Java virtual machine argument ``user.timezone``. This Java virtual machine argument takes precedence over the environment variable TZ. For example, you can use the flag ``-D`` when running the application: ``java -jar -D user.timezone=GMT`` or ``java -jar -D user.timezone="Asia/Kolkata"`` ## Set a cron timezone You can set a specific timezone for your crons so they don't run in your app runtime timezone (or container timezone if no app runtime timezone is set on your project). To do so, [set the `timezone` top-level property](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#primary-application-properties) in your app configuration. --- # Source: https://docs.upsun.com/domains/steps/tls.md # Configure a third-party TLS certificate Upsun automatically provides standard Transport Layer Security (TLS) certificates for all sites and environments. These certificates are issued at no charge by [Let's Encrypt](https://letsencrypt.org/) and cover most needs. To use them, you need to [specify HTTPS routes](https://docs.upsun.com../../define-routes/https.md#enable-https). Note that some [limitations](https://docs.upsun.com../../define-routes/https.md#lets-encrypt-limitations) apply. Upsun allows you to use third-party TLS certificates free of charge. You can use many kinds of custom certificates, including domain-validated, extended validation, high-assurance, or wildcard certificates. Consult your TLS issuer for pricing and instructions on how to generate a TLS certificate. Seven days before a third-party custom certificate is due to expire, Upsun replaces it with a new default Let’s Encrypt certificate. This helps prevent downtime. To avoid switching to a default certificate, make sure you replace your custom certificate with an updated one more than seven days before its expiration date. Note that custom certificates aren't necessary for preview environments as we provision Let's Encrypt certificates by default for them. ### Add a custom certificate You can add a custom certificate using the [CLI](https://docs.upsun.com../../administration/cli.md) or in the [Console](https://docs.upsun.com../../administration/web.md). Your certificate has to be in PKCS #1 format and start with `-----BEGIN RSA PRIVATE KEY-----`. If it doesn't start that way, [change the format](#change-the-private-key-format). To add your custom certificate, follow these steps: For example: ```bash {} upsun domain:add secure.example.com --cert /etc/TLS/private/secure-example-com.crt --key /etc/TLS/private/secure-example-com.key ``` You can optionally include intermediate SSL certificates by adding ``‐‐chain `` for each one. - Redeploy your production environment with the following command: ```bash {} upsun environment:redeploy ``` - Open the project where you want to add a certificate. - Click Settings **Settings**. - Click **Certificates**. - Click **+ Add**. - Fill in your private key, public key certificate, and (optionally) intermediate SSL certificates. - Click **Add Certificate**. - Access your production environment. - Click More **More**. - Click **Redeploy**. ### Change the private key format The expected format for your certificate’s private key is PKCS #1. Private keys in PKCS #1 format start with `-----BEGIN RSA PRIVATE KEY-----`. If your private key starts with `-----BEGIN PRIVATE KEY-----`, it’s in PKCS #8 format, which isn’t appropriate. To convert your private key (`private.key`) from PKCS #8 to PKCS #1 format (`private.rsa.key`), run the following command: ```bash openTLS rsa -in private.key -out private.rsa.key ``` --- # Source: https://docs.upsun.com/create-apps/troubleshoot-disks.md # Troubleshoot disks For more general information, see how to [troubleshoot development](https://docs.upsun.com/development/troubleshoot.md). ## Low disk space If you have set up [health notifications](https://docs.upsun.com../integrations/notifications.md), you may receive a notification of low disk space. To solve this issue: * [Check mount usage](https://docs.upsun.com/create-apps/troubleshoot-mounts.md#disk-space-issues) * [Check your database disk space](#check-your-database-disk-space) (if applicable) * [Increase the available disk space](#increase-available-disk-space) (if necessary) ### Check your database disk space To get approximate disk usage for a database, run the command `upsun db:size`. This returns an estimate such as the following: ```text {no-copy="true"} +----------------+-----------------+--------+ | Allocated disk | Estimated usage | % used | +----------------+-----------------+--------+ | 1.0 GiB | 520.3 MiB | ~ 51% | +----------------+-----------------+--------+ ``` Keep in mind that this estimate doesn't represent the exact real size on disk. But if you notice that the usage percentage is high, you may need to increase the available space. ### Increase available disk space If you find that your application or service is running out of disk space, you can increase the available storage. To increase the space available for applications and services, use the `upsun resources:set` command. For more information, see how to [manage resources](https://docs.upsun.com/manage-resources.md). ## No space left on device During the `build` hook, you may see the following error: ```text {no-copy="true"} W: [Errno 28] No space left on device: ... ``` This is caused by the amount of disk provided to the build container before deployment. Application images are restricted to 8 GB during build, no matter how much writable disk has been set aside for the deployed application. Some build tools (yarn/npm) store cache for different versions of their modules. This can cause the build cache to grow over time beyond the maximum. Try [clearing the build cache](https://docs.upsun.com../development/troubleshoot.md#clear-the-build-cache) and [triggering a redeploy](https://docs.upsun.com../development/troubleshoot.md#force-a-redeploy). If for some reason your application absolutely requires more than 8 GB during build, you can open a [support ticket](https://docs.upsun.com/learn/overview/get-support.md) to have this limit increased. --- # Source: https://docs.upsun.com/create-apps/troubleshoot-mounts.md # Troubleshoot mounts For more general information, see how to [troubleshoot development](https://docs.upsun.com/development/troubleshoot.md). ## Overlapping folders If you have a mount with the same name as a directory you've committed to Git or you create such a directory during the build, you get a message like the following: ```bash W: The mount '/example' has a path that overlaps with a non-empty folder. The content of the non-empty folder either comes from: - your git repository (you may have accidentally committed files). - or from the build hook. Please be aware that this content isn't accessible at runtime. ``` This shows that the files in Git or from your build aren't available after the build. The only files that are available are those in your mount. To make the files available in the mount, move them away and then copy them into the mount: 1. In the `build` hook, use `mv` to move the files to another location. ```bash mv example tmp/example ``` 2. In the `deploy` hook, use `cp` to copy the files into the mount. ```bash cp -r tmp/example example ``` To see the files without copying them, temporarily remove the mount from your app configuration. Then SSH into your app and view the files. You can then put the mount back in place. ## Mounted files not publicly accessible If you've set up mounts to handle files like user uploads, you want to make sure the files are accessible. Do so by managing their [location](https://docs.upsun.com/create-apps/image-properties/web.md#locations). This example defines two mounts, one named `private` and one `upload`: ```yaml {location=".upsun/config.yaml"} applications: myapp: mounts: 'private': source: storage source_path: private 'uploads': source: storage source_path: uploads ``` With only this definition, their behavior is the same. To make `uploads` accessible, define a location with different rules as in the following example: ```yaml {location=".upsun/config.yaml"} applications: myapp: web: locations: '/': # Handle dynamic requests root: 'public' passthru: '/app.php' # Allow uploaded files to be served, but don't run scripts. '/uploads': root: 'uploads' expires: 300s scripts: false allow: true ``` ## Mounts starting with a dot ignored Upsun ignores YAML keys that start with a dot. This causes a mount like `.myhiddenfolder` to be ignored. To mount a directory starting with a dot, put a `/` at the start of its definition: ```yaml {location=".upsun/config.yaml"} applications: myapp: web: mounts: '/.myhiddenfolder': source: storage source_path: 'myhiddenfolder' ``` ## Disk space issues If you are worried about how much disk your mounts are using, check the size with the following command: ```bash upsun resources:get ``` --- # Source: https://docs.upsun.com/development/ssh/troubleshoot-ssh.md # Troubleshoot SSH While trying to use SSH, you may get a response indicating permission is denied. Or if you get an error with a code of 255, it means there's a problem with your SSH connection. ```txt {no-copy="true"} The command failed with the exit code: 255 ``` There are several places to check to try to solve such issues. ## Check your environment If your environment is [inactive](https://docs.upsun.com/glossary.md#inactive-environment) or the deployment has failed, you can't log in to it. To make sure the environment is active and the deployment has succeeded, check it using `upsun environment:list` or in the [Console](https://console.upsun.com/) . ## Redeploy your environment If you have just added your SSH key or made changes to [access rules](https://docs.upsun.com/administration/users.md), you need to redeploy your environment before you can access it using SSH keys. You can do this in the [Console](https://console.upsun.com/), by running `upsun redeploy`, or by pushing an empty git commit: ```bash git commit --allow-empty -m 'chore: force redeploy' git push origin main ``` ## Check your public key Make sure your public key has been uploaded to your user account. Check it in the [Upsun Console](https://console.upsun.com/). ## SSH key can not be duplicated A given SSH key pair can only be linked to a single user account. If you add an already used SSH key to another account, you see the error: `SSH key can not be duplicated`. [Generate a new pair of SSH keys](https://docs.upsun.com/development/ssh/ssh-keys.md#add-ssh-keys) for the second user account you want to add. ## Check your SSH agent Check that your key is properly added to your SSH agent. This is an authentication agent that manages your private key. 1. Run `ssh-add -l` in your terminal: ```bash ssh-add -l ``` You get output similar to the following: ```bash 2048 12:b0:13:83:7f:56:18:9b:78:ca:54:90:a7:ff:12:69 /Users/your_username/.ssh/id_rsa (RSA) ``` 1. Check that the file exists and that the file name or comment matches your private key file. 1. If you don't see your private key file, add your private key: ```bash ssh-add path-to-your-key ``` ## Specify your identity file If your identity (SSH key) associated with Upsun isn't in a default file name (as may be explained in your SSH software manual, for example), you may have to append a specification like the one below so that the SSH software finds the correct key. ```bash Host platform.sh IdentityFile ~/.ssh/id_upsun ``` Be aware that, above, `upsun` stands for a hostname. Each different hostname you connect to Upsun at may have to be specified in the host line, separated by spaces. ## Check your Git integrations If your project is integrated with another Git provider (such as GitHub), that provider controls Git operations. Make sure you have added your public SSH key to your provider and that your user there has access. ## Generate SSH debug information If your private key and public key both look OK but you don't have any luck logging in, print debugging information. These lines often give clues about what's going wrong. Run the SSH command with the `-v` option, like so: ```bash ssh -v [SSH-URL] ``` You get output similar to the following: ```bash OpenSSH_6.7.8, OpenSSL 1.2.3 1 Sep 2014 debug1: Connecting to ssh.eu.upsun.com [54.32.10.98] port 22. debug1: Connection established. debug1: identity file /Users/your_username/.ssh/id_rsa type 1 ...(many more lines of this light reading)... debug1: Offering RSA public key: /Users/your_username/.ssh/id_rsa debug1: Authentications that can continue: publickey debug1: No more authentication methods to try. Permission denied (publickey). ``` Alternatively, you can run the following command: ```bash GIT_SSH_COMMAND="ssh -v" git clone ``` You can use this information to make one last check of the private key file. ## MFA-related error message If you haven't enabled MFA on your user account and try to SSH into an environment that is protected by MFA, you get the following error message: ```bash Error: Access denied Service: abcdefg123456-main-bvxea6i--app User: () Parameters: {"amr":["mfa"]} Detail: Additional authentication is required: - Multifactor authentication (MFA) ``` To solve this, [enable MFA on your user account](https://docs.upsun.com../../administration/security/mfa.md#enable-mfa-on-your-user-account). Alternatively, open the Console and select the desired organization. Follow the instructions so you can effectively access its contents. Similarly for bot users and CLI tokens, you may see the message: ```bash [RequestException] Multifactor authentication (MFA) is required. The API token may need to be re-created after enabling MFA. ``` In this case, as described, it will be necessary to: 1. Enable MFA on the (bot) user account associated with the token. 2. Generate a new access token, and then replace its value in your workflow that requires the token (such as updating a GitHub workflow secret variable). ## Something still wrong? For more general information, see how to [troubleshoot development](https://docs.upsun.com/development/troubleshoot.md). If you're still stuck, open a [support ticket](https://docs.upsun.com/learn/overview/get-support.md) and provide the full SSH debug information. --- # Source: https://docs.upsun.com/domains/troubleshoot.md # Source: https://docs.upsun.com/integrations/source/troubleshoot.md # Source: https://docs.upsun.com/development/troubleshoot.md # Source: https://docs.upsun.com/languages/php/troubleshoot.md # Source: https://docs.upsun.com/add-services/mysql/troubleshoot.md # Troubleshoot MySQL For more general information, see how to [troubleshoot development](https://docs.upsun.com/development/troubleshoot.md). ## Lock wait timeout If a process running in your application acquired a lock from MySQL for a long period of time, you receive MySQL error messages like this: ```sql SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; ``` This is typically caused by one of the following: * There are multiple places acquiring locks in different order. For example, code path 1 first locks record A and then locks record B, while code path 2 first locks record B and then locks record A. * There is a long running background process executed by your application that holds the lock until it ends. If you're using [MariaDB 10+](https://docs.upsun.com/add-services/mysql.md), use the SQL query `SHOW FULL PROCESSLIST \G` to list DB queries waiting for locks. To determine where to debug, find output like the following: ```sql Command: Query Time: ... State: Waiting for table metadata lock Info: SELECT ... ``` To find active background processes, run `ps aufx` on your application container. Make sure that locks are acquired in a pre-defined order and released as soon as possible. ## Definer/invoker of view lack rights to use them There is a single MySQL user, so you can not use "DEFINER" Access Control mechanism for Stored Programs and Views. When creating a `VIEW`, you may need to explicitly set the `SECURITY` parameter to `INVOKER`: ```sql CREATE OR REPLACE SQL SECURITY INVOKER VIEW `view_name` AS SELECT ``` ## Server has gone away ### Disk space issues Errors such as `PDO Exception 'MySQL server has gone away'` are usually the result of exhausting your available disk space. Get an estimate of current disk usage using the CLI command `upsun db:size`. Just keep in mind it's an estimate and not exact. Allocate more space to the service by running the `upsun resources:set` command. For more information, see how to [manage resources](https://docs.upsun.com/manage-resources.md). As table space can grow rapidly, it's usually advisable to make your database mount size twice the size reported by the `db:size` command. You may want to add a [low-disk warning](https://docs.upsun.com../../integrations/notifications.md#low-disk-warning) to learn about low disk space before it becomes an issue. ### Packet size limitations `MySQL server has gone away` errors may be caused by the size of the database packets. If so, the logs may show warnings like `Error while sending QUERY packet` before the error. One way to resolve the issue is to use the [`max_allowed_packet` parameter](https://docs.upsun.com/add-services/mysql.md#configure-the-database). ### Worker timeout `MySQL server has gone away` errors may be caused by server timeouts. MySQL has a built-in timeout for idle connections, which defaults to 10 minutes. Most typical web connections end long before that's ever approached, but a long-running worker may idle and not need the database for longer than the timeout, leading to a "server has gone away" message. The best approach is to wrap your connection logic in code that detects a "server has gone away" exception and tries to re-establish the connection. Alternatively, if your worker is idle for too long it can self-terminate. Upsun automatically restarts the worker process and the new process can establish a new database connection. ## Too many connections You may get the following [error message](https://mariadb.com/kb/en/e1040/): `Error 1040: Too many connections`. A common way to solve this issue is to increase the `max_connections` property in your MariaDB service configuration. However, on Upsun, you **cannot** configure `max_connections` directly. ### Quick fix You cannot configure `max_connections` directly in Upsun service configurations. However, to solve `Error 1040`, you can increase `max_connections` indirectly. Given the following services configuration for MariaDB: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. mariadb: type: mariadb:11.8 configuration: properties: max_allowed_packet: 16 ``` And assuming you have set the resources for that service using the following CLI command: ```bash upsun resources:set --size mariadb:1 ``` `max_connections` in this case is `332` as [set by Upsun](#how-it-works): To **increase** `max_connections`, you can **either**: - **decrease** `max_allowed_packet` (for example, `16` → `15` results in `max_connections=355`) - or **increase** `size` using the `resources:set` command (for example, `1` → `2` results in `max_connections=500`) ### How it works Behind the scenes, `max_connections` is calculated from values that you _can_ change: 1. **`max_allowed_packet`**: `max_allowed_packet` is [directly configurable](https://docs.upsun.com/add-services/mysql.md#configure-the-database) in your `.upsun/config.yaml` file with an integer value. The default value of `16` is shown below to illustrate: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. mariadb: type: mariadb:11.8 configuration: properties: max_allowed_packet: 16 ``` 1. **The memory available to the service**: Resources are provisioned to Upsun containers according to your definition via the API, often through the `resources:set` CLI command: ```bash upsun resources:set --size mariadb:1 ``` The memory for a given container from its `size` depends on its [container profile](https://docs.upsun.com/manage-resources/adjust-resources.md#advanced-container-profiles). For example, [MariaDB](https://docs.upsun.com/manage-resources/adjust-resources.md#default-container-profiles) has a [`HIGH_MEMORY` container profile](https://docs.upsun.com/manage-resources/adjust-resources.md#advanced-container-profiles). For `--size mariadb:1`, it means 1 CPU and 2432 MB of memory. If we assume the configuration above, where: - `--size mariadb:1`, which we know is `2432` MB, referred to below as `application_size` - `mariadb.configuration.properties.max_allowed_packet: 16` - You are using the default `HIGH_MEMORY` profile assigned to MariaDB containers. [Changing the container profile](https://docs.upsun.com/manage-resources/adjust-resources.md#adjust-a-container-profile) changes the behavior below. `max_allowed_packet` is `332`, which is determined by Upsun according to: \begin{aligned} \texttt{max_connections} = \text{int}\Biggl[ \min \left( \frac{\texttt{FREE_MEMORY}}{\texttt{max_allowed_packet}}, 500 \right) \Biggr] \end{aligned} This calculation uses three additional calculations: \begin{aligned} \texttt{FREE_MEMORY} = \texttt{AVAILABLE_MEMORY} - \left( 50 + \texttt{innodb_buffer_pool_size} \right) \newline \newline \texttt{AVAILABLE_MEMORY} = (\texttt{application_size} * 2) + 512 \newline \newline \texttt{innodb_buffer_pool_size} = \frac{\text{int}\left( 0.75 \cdot \texttt{application_size} \right)}{1024^{2}} \end{aligned} So for our current example, where: \begin{aligned} \texttt{application_size} = 2432 \newline \texttt{max_allowed_packet} = 16 \end{aligned} You get: \begin{aligned} \texttt{innodb_buffer_pool_size} = \frac{\text{int}\left( 0.75 \cdot \texttt{application_size} \right)}{1024^{2}} = \frac{\text{int}\left( 0.75 \cdot \texttt{1280} \right)}{1024^{2}} \approx 1.7395 \times 10^{-3} \end{aligned} \begin{aligned} \texttt{AVAILABLE_MEMORY} = (\texttt{application_size} * 2) + 512 = (1280 * 2) + 512 = 5376 \end{aligned} \begin{aligned} \texttt{FREE_MEMORY} = \texttt{AVAILABLE_MEMORY} - \left( 50 + \texttt{innodb_buffer_pool_size} \right) \newline \newline \texttt{FREE_MEMORY} = 3072 - \left( 50 + 0.0009155... \right) = 5325.998... \end{aligned} \begin{aligned} \texttt{max_connections} = \text{int}\Biggl[ \min \left( \frac{\texttt{FREE_MEMORY}}{\texttt{max_allowed_packet}}, 500 \right) \Biggr] = \text{int}\Biggl[ \min \left( \frac{3021.999084}{16}, 500 \right) \Biggr] = \text{int}\Biggl[ 332.87... \Biggr] \end{aligned} \begin{aligned} \texttt{max_connections} = 332 \end{aligned} The following table provides additional example calculations of `max_connections` for all `size` settings and for a number of `max_allow_packet` settings. MariaDB ``max_connections`` ``application_size````size`` (memory in MB) 0.1 (448 MB) | 0.25 (832 MB) | 0.5 (1408 MB) | 1 (2432 MB) | 2 (4032 MB) | 4 (6720 MB) | 6 (9024 MB) | 8 (11200 MB) | 1(min) | 500 | 500 | 500 | 500 | 500 | 500 | 500 | 500 | 2 | 500 | 500 | 500 | 500 | 500 | 500 | 500 | 500 | 8 | 169 | 265 | 409 | 500 | 500 | 500 | 500 | 500 | 16(default) | 84 | 132 | 204 | 332 | 500 | 500 | 500 | 500 | 32 | 42 | 66 | 102 | 166 | 266 | 434 | 500 | 500 | 64 | 21 | 33 | 51 | 83 | 133 | 217 | 289 | 357 | 100(max) | 13 | 21 | 32 | 53 | 85 | 139 | 185 | 228 | **Note**: The maximum value for ``max_connections`` is 500, indicated with italicized integers in the table. Also, you can **increase** ``max_connections`` in your environments by either: - **decreasing** the ``max_allow_packet`` value in your service configuration - or **increasing** the service’s resources by using the CLI command ``resources:set`` and the ``--size`` flag --- # Source: https://docs.upsun.com/languages/php/tuning.md # Source: https://docs.upsun.com/languages/java/tuning.md # Performance tuning Java p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. There are a number of settings that can be adjusted for each application to optimize its performance on Upsun. ## Memory limits The JVM generally requires specifying a maximum memory size it is allowed to use, using the `Xmx` parameter. That should be set based on the available memory on the application container, which varies with its size. To extract the container-scaled value on the command line, use `$(jq .info.limits.memory /run/config.json)`. You should also set the `ExitOnOutOfMemoryError`. When you enable this option, the JVM exits on the first occurrence of an out-of-memory error. Upsun will restart the application automatically. These are the recommended parameters for running a Java application. Thus, the command to use to start a Java application is: ```bash java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError //The rest of the arguments and the jar file. ``` ## Garbage collection When migrating the application to a cloud environment, it is often essential to analyze the Garbage Collector's log and behavior. For this, there are two options: * Placing the log into the Upsun `/var/log/app.log` file (which captures `STDOUT`). * Creating a log file specifically for the GC. To use the `STDOUT` log, you can add the parameter `-XX: + PrintGCDetails`, E.g.: ```bash java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails //The rest of the arguments and the jar file. ``` Java supports a number of different garbage collection strategies. Which one is optimal for your application varies depending on your available memory, Java version, and application profile. Determining which is best for your application is out of scope, but the main options and how to enable them are: | Name | Command Flag | Description | | ------------- |:-------------:| -----:| |Serial Garbage Collector|-XX:+UseSerialGC|This is the simplest GC implementation, as it basically works with a single thread.| |Parallel Garbage Collector|-XX:+UseParallelGC|Unlike Serial Garbage Collector, this uses multiple threads for managing heap space. But it also freezes other application threads while performing GC.| |CMS Garbage Collector|-XX:+USeParNewGC|The Concurrent Mark Sweep (CMS) implementation uses multiple garbage collector threads for garbage collection. It's for applications that prefer shorter garbage collection pauses, and that can afford to share processor resources with the garbage collector while the application is running.| |G1 Garbage Collector|-XX:+UseG1GC|Garbage First, G1, is for applications running on multiprocessor machines with large memory space.| The default strategy on Java 9 and later is G1. The GC strategy to use can be set in the start line with: ### Serial ```bash java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails -XX:+UseSerialGC //The rest of the arguments and the jar file. ``` ### Parallel Garbage Collector ```bash java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails -XX:+UseParallelGC //The rest of the arguments and the jar file. ``` ### CMS Garbage Collector ```bash java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails -XX:+USeParNewGC //The rest of the arguments and the jar file. ``` ### G1 ```bash java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails -XX:+UseG1GC //The rest of the arguments and the jar file. ``` ## Java 8 Optimization Ideally, all applications should run the latest LTS release of the JVM at least. That is currently Java 11. Java 11 has a number of performance improvements, particularly on container-based environments such as Upsun. However, in many cases, this isn't possible. If you are still running on Java 8 there are two additional considerations. The default garbage collector for Java 8 is Parallel GC. In most cases G1 will offer better performance. We recommend enabling it, as above. Furthermore, there is the `UseStringDeduplication` flag which works to eliminate duplicate `String`s within the GC process. That flag can save between 13% to 30% of memory, depending on application. However, this can impact on the pause time of your app. ```bash java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails ``` ## References * [Introduction to Garbage Collection Tuning](https://docs.oracle.com/en/java/javase/14/gctuning/introduction-garbage-collection-tuning.md#GUID-326EB4CF-8C8C-4267-8355-21AB04F0D304) --- # Source: https://docs.upsun.com/learn/tutorials.md # Tutorials --- # Source: https://docs.upsun.com/development/local/untethered.md # Untethered local development It's possible to run your entire site locally on your computer. That way you get better performance as there's no extra latency to connect to a remote database and doesn't require an active Internet connection to work. But it does require running all necessary services (databases, search servers, and so on) locally. These can be set up however you prefer, although Upsun recommends using a virtual machine to make it easier to share configuration between developers. If you already have a development workflow in place that works for you, you can keep using it with virtually no changes. To synchronize data from an environment on Upsun, consult the documentation for each [service](https://docs.upsun.com../../add-services.md). Each service type has its own native data import/export process and Upsun doesn't get in the way of that. It's also straightforward to [download user files](https://docs.upsun.com/learn/tutorials/exporting.md) from your application using rsync. --- # Source: https://docs.upsun.com/development/variables/use-variables.md # Use variables Get a list of all variables defined on a given environment in [the Console](https://docs.upsun.com../../administration/web/configure-environment.md#variables) or use the CLI: ```bash upsun var ``` You get output similar to the following: ```bash Variables on the project Example (abcdef123456), environment main: +------+---------+-------+---------+ | Name | Level | Value | Enabled | +------+---------+-------+---------+ | foo | project | bar | true | +------+---------+-------+---------+ ``` ## Access variables in a shell Project and environment variables with the [prefix](https://docs.upsun.com/development/variables.md#top-level-environment-variables) `env:` are available as Unix environment variables in all caps. Access these variables and Upsun-provided variables directly like this: ```bash echo $FOO bar echo $PLATFORM_APPLICATION_NAME Sample Project ``` Other project and environment variables are listed together in the `PLATFORM_VARIABLES` variable as a base64-encoded JSON object. Access them like this: ```bash echo $PLATFORM_VARIABLES | base64 --decode {"theanswer": "42"} ``` You can also get the value for a single variable within the array, such as with this command, which uses the [`jq` processor](https://stedolan.github.io/jq/): ```bash echo $PLATFORM_VARIABLES | base64 --decode | jq '.theanswer' "42" ``` Variable availability depends on the type and configuration. Variables available during builds can be accessed in `build` hooks and those available at runtime can be accessed in `deploy` hooks. ## Access variables in your app To access environment variables in your app, use a built-in method for the given language. * PHP: The [`getenv()` function](https://www.php.net/manual/en/function.getenv.php) * Python: The [`os.environ` object](https://docs.python.org/3/library/os.md#os.environ) * Node.js: The [`process.env` object](https://nodejs.org/api/process.md#process_process_env) * Ruby: The [`ENV` accessor](https://docs.ruby-lang.org/en/master/ENV.md) * Java: The [`System.getenv()` method](https://docs.oracle.com/javase/8/docs/api/java/lang/System.md#getenv-java.lang.String-) ```python {} import os import json import base64 # A simple variable. project_id = os.getenv('PLATFORM_PROJECT') # An encoded JSON object. variables = json.loads(base64.b64decode(os.getenv('PLATFORM_VARIABLES')).decode('utf-8')) ``` ```js {} const { env } = process; // Utility to assist in decoding a packed JSON variable. function read_base64_json(varName) { try { return JSON.parse(Buffer.from(env[varName], "base64").toString()); } catch (err) { throw new Error(`no ${varName} environment variable`); } }; // A simple variable. const projectId = env.PLATFORM_PROJECT; // An encoded JSON object. const variables = read_base64_json('PLATFORM_VARIABLES'); ``` ```ruby {} # A simple variable. project_id = ENV["PLATFORM_PROJECT"] || nil # An encoded JSON object. variables = JSON.parse(Base64.decode64(ENV["PLATFORM_VARIABLES"])) ``` ```java {} import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.Base64; import java.util.Map; import static java.lang.System.getenv; import static java.util.Base64.getDecoder; public class App { public static void main(String[] args) throws IOException { // A simple variable. final String project = getenv("PLATFORM_PROJECT"); // An encoded JSON object. ObjectMapper mapper = new ObjectMapper(); final Map variables = mapper.readValue( String.valueOf(getDecoder().decode(getenv("PLATFORM_VARIABLES"))), Map.class); } } ``` ### Access complex values Variables can have nested structures. The following example shows nested structures in an [app configuration](https://docs.upsun.com/create-apps/image-properties/variables.md): ```yaml {location=".upsun/config.yaml"} applications: : variables: env: BASIC: "a string" INGREDIENTS: - 'peanut butter' - 'jelly' QUANTITIES: "milk": "1 liter" "cookies": "1 kg" stuff: STEPS: ['one', 'two', 'three'] COLORS: red: '#FF0000' green: '#00FF00' blue: '#0000FF' ``` You can access these nested variables as follows: ```php {} string(2) "one" [1]=> string(4) "two" [2]=> string(5) "three" } */ print_r($variables['stuff:COLORS']); /* array(3) { ["red"]=> string(7) "#FF0000" ["green"]=> string(7) "#00FF00" ["blue"]=> string(7) "#0000FF" } */ ``` ```python {} import os import json import base64 print os.getenv('BASIC') # a string print os.getenv('INGREDIENTS') # ["peanut butter", "jelly"] print os.getenv('QUANTITIES') # {"milk": "1 liter", "cookies": "1 kg"} variables = json.loads(base64.b64decode(os.getenv('PLATFORM_VARIABLES')).decode('utf-8')) print variables['stuff:STEPS'] # [u'one', u'two', u'three'] print variables['stuff:COLORS'] # {u'blue': u'#0000FF', u'green': u'#00FF00', u'red': u'#FF0000'} ``` ```java {} scriptconst { BASIC, INGREDIENTS, QUANTITIES, PLATFORM_VARIABLES } = process.env; const { "stuff:STEPS": stuffSteps, "stuff:COLORS": stuffColors } = JSON.parse( Buffer.from(PLATFORM_VARIABLES, "base64").toString() ); console.log(BASIC); // "a string" console.log(INGREDIENTS); // ["peanut butter", "jelly"] console.log(QUANTITIES); // {"cookies": "1 kg", "milk": "1 liter"} console.log(stuffSteps); // [ 'one', 'two', 'three' ] console.log(stuffColors); // { blue: '#0000FF', green: '#00FF00', red: '#FF0000' } ``` ## Use provided variables Upsun also provides a series of variables to inform your app about its runtime configuration. Many of them have a `PLATFORM_` prefix to differentiate them from user-provided values. You can't set or update them directly. The following table presents all available variables and whether they're available at build time (during [build hooks](https://docs.upsun.com../../administration/../create-apps/hooks/hooks-comparison.md#build-hook)) and at runtime. | Variable name | Build | Runtime | Description | |------------------------------------------|-------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `CI` | Yes | No | Available for use in build scripts and tooling to modify build behavior (for example, to disable attempts to connect to other containers during the build phase, or to disable interactivity), which can help to reduce build failures. | | `PLATFORM_APP_COMMAND` | No | Yes | The contents of the [web start command](https://docs.upsun.com/create-apps/image-properties/web.md#web-commands). | | `PLATFORM_APP_DIR` | Yes | Yes | The absolute path to the app directory. | | `PLATFORM_APPLICATION` | Yes | Yes | A base64-encoded JSON object that describes the app. It maps certain attributes from your [app configuration](https://docs.upsun.com../../create-apps.md), some with more structure. See [notes](#platform_application). | | `PLATFORM_APPLICATION_NAME` | Yes | Yes | The app name as set in your [app configuration](https://docs.upsun.com../../create-apps.md). | | `PLATFORM_BRANCH` | No | Yes | The name of the Git branch. | | `PLATFORM_CACHE_DIR` | Yes | No | The directory where files are cached from one build to the next. The directory is shared among all branches, so the same cache is used for all environments. | | `PLATFORM_DOCUMENT_ROOT` | No | Yes | The absolute path to the web document root, if applicable. | | `PLATFORM_ENVIRONMENT` | No | Yes | The name of the Upsun environment. | | `PLATFORM_ENVIRONMENT_TYPE` | No | Yes | The environment type of the Upsun environment (`development`, `staging`, or `production`). | | `PLATFORM_OUTPUT_DIR` | Yes | No | The output directory for compiled languages at build time. Equivalent to `PLATFORM_APP_DIR` in most cases. | | `PLATFORM_POST_APP_COMMAND` | No | Yes | The contents of the [web post_start command](https://docs.upsun.com/create-apps/image-properties/web.md#web-commands). | | `PLATFORM_PRE_APP_COMMAND` | No | Yes | The contents of the [web pre_start command](create-apps/image-properties/web.md#web-commands). | | `PLATFORM_PROJECT` | Yes | Yes | The project ID. | | `PLATFORM_PROJECT_ENTROPY` | Yes | Yes | A random, 56-character value created at project creation and then stable throughout the project's life. Can be used for Drupal hash salts, Symfony secrets, and other similar values. | | `PLATFORM_RELATIONSHIPS` | No | Yes | The `PLATFORM_RELATIONSHIPS` variable is automatically broken down into [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables), so your app can seamlessly connect to databases and other services defined in `.upsun/config.yaml`. For some advanced use cases, you may need to use the `PLATFORM_RELATIONSHIPS` variable itself. It is a base64-encoded JSON object of relationships, with keys that indicate the relationship names, and values that are arrays of relationship endpoint definitions. The exact format is defined differently for each [service](https://docs.upsun.com../../add-services.md). You may need to gather `PLATFORM_RELATIONSHIPS` information in a ``.environment`` file. See how to [use ``.env`` files](https://docs.upsun.com/development/variables/set-variables.md#use-env-files), and refer to [dedicated service pages](https://docs.upsun.com/add-services.md) for examples. | | `PLATFORM_ROUTES` | No | Yes | A base64-encoded JSON object that describes the routes for the environment. It maps the content of your [routes configuration](https://docs.upsun.com../../define-routes.md). Note that this information is also available in your `/run/config.json` file. | | `PLATFORM_SMTP_HOST` | No | Yes | The SMTP host to send email messages through. Is empty when mail is disabled for the current environment. | | `PLATFORM_SOURCE_DIR` | Yes | No | The path to the root directory of your code repository in the context of a running [source operation](https://docs.upsun.com../../create-apps/source-operations.md). The directory contains a writable copy of your repository that you can commit to during the operation. | | `PLATFORM_TREE_ID` | Yes | Yes | The ID of the tree the application was built from, essentially the SHA hash of the tree in Git. Use when you need a unique ID for each build. | | `PLATFORM_VARIABLES` | Some | Some | A base64-encoded JSON object with all user-defined project and environment variables that don't use a [prefix](https://docs.upsun.com/development/variables.md#variable-prefixes). The keys are the variable names and the values are the variable values. Availability during builds and at runtime depends on the settings for each variable. See how to [access individual variables](#access-variables-in-a-shell). | | `PLATFORM_VENDOR` | Yes | No | Allows you to change the behavior of the build according to the vendor (Upsun or Upsun Fixed). | | `PORT` | No | Yes | A `string` representing the port to which requests are sent if the [`web.upstream.socket_family` property](https://docs.upsun.com/create-apps/image-properties/web.md#upstream) is unset or set to `tcp`. | | `SOCKET` | No | Yes | A `string` representing the path to the Unix socket file to use if the [`web.upstream.socket_family` property](https://docs.upsun.com/create-apps/image-properties/web.md#upstream) is set to `unix`. | ### `PLATFORM_APPLICATION` The `PLATFORM_APPLICATION` variable is available both at build time and in the runtime environment. But the specific attributes it contains differ in each case. Each environment's build is associated with a configuration ID that identifies it uniquely so builds can be reused. The ID is a product of your app code and some of its [configuration for Upsun](https://docs.upsun.com../../create-apps.md). Not every attribute your app configuration is relevant to the build. Only those attributes that are relevant to builds are accessible at build time from `PLATFORM_APPLICATION`. Attributes that are **not** available in `PLATFORM_APPLICATION` during builds: - Everything under `access` - Everything under `relationship` - Everything under `firewall` - `hooks.deploy` and `hooks.post_deploy` - Everything under `crons` - Everything under `web`, except `web.mounts` - Everything under `workers`, except `workers.mounts` These attributes aren't visible during build because they aren't included as a part of the configuration component of the build slug. So modifying these values in your [app configuration](https://docs.upsun.com../../create-apps.md) doesn't trigger an app rebuild, only a redeploy. For more information, read about [how builds work](https://docs.upsun.com/learn/overview/build-deploy.md#the-build). ## Use variables in static files Some apps require configuration values to be specified in a static, non-executable file (such as a `.ini`, `.xml`, or `.yaml` file) and don't support reading from environment variables. To populate these files with variables you set yourself, make sure the variables are set to be [visible at build time](https://docs.upsun.com/development/variables/set-variables.md#variable-options). The files can't be populated with Upsun-provided variables not available at build time (such as `PLATFORM_RELATIONSHIPS` or [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables)). You also can't write to them in a `deploy` hook as the file system is read only. One workaround is to create a symbolic link to a writable location and then write to it in a [`deploy` hook](https://docs.upsun.com../../create-apps/hooks/hooks-comparison.md#deploy-hook). The following example shows the process, though you have to modify it to fit your needs. 1. Create a mount that isn't accessible to the web in your [app configuration](https://docs.upsun.com../../create-apps/_index.md): ```yaml {location=".upsun/config.yaml"} applications: mounts: /config: source: storage source_path: config ``` 2. Create a symbolic link from the config file the application wants to a location in that mount: ```bash # From the application root... ln -s config/db.yaml db.yaml ``` This example assumes the app wants a `db.yaml` file in its root for configuration. 3. Commit the symbolic link and an empty `config` directory to Git. 4. Configure a script to read from environment variables and write to `config/db.yaml` through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [`PLATFORM_RELATIONSHIPS` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables).
Create a file with a shell script similar to this: ```bash {} #!/bin/bash # Ensure the file is empty. cat '' > config/db.yaml # Map the database information from the service environment variable into the YAML file. # Use this process to use whatever variable names your app needs. # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. printf "host: %s\n" $(echo $DATABASE_HOST) >> config/db.yaml printf "user: %s\n" $(echo $DATABASE_USERNAME) >> config/db.yaml ``` export-config.sh ```bash {} #!/bin/bash # Ensure the file is empty. cat '' > config/db.yaml # Map the database information from the PLATFORM_RELATIONSHIPS variable into the YAML file. # Use this process to use whatever variable names your app needs. # For more information, please visit https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables. printf "host: %s\n" $(echo $PLATFORM_RELATIONSHIPS | base64 --decode | jq -r ".database[0].host") >> config/db.yaml printf "user: %s\n" $(echo $PLATFORM_RELATIONSHIPS | base64 --decode | jq -r ".database[0].username") >> config/db.yaml ``` 5. Call the script from the `deploy` hook your [app configuration](https://docs.upsun.com../../create-apps/_index.md): ```yaml {location=".upsun/config.yaml"} applications: hooks: deploy: | bash export-config.sh ``` Now, when your app starts and attempts to parse `db.yaml`, the symbolic link redirects it to `config/db.yaml`. Your script writes to that file on each deploy with updated information. Your app reads the exported values and proceeds as expected. --- # Source: https://docs.upsun.com/administration/users.md # Administer users Upsun offers fine-grained and flexible user permissions across projects and organizations. When a user is added to a project, they are automatically added to your organization. **Available add-on**: The Advanced User Management add-on offers [teams](https://docs.upsun.com/administration/teams.md), [MFA enforcement within an organization](https://docs.upsun.com/administration/security/mfa.md) and [single sign-on](https://docs.upsun.com/administration/security/sso.md). See how to [subscribe to this add-on](https://docs.upsun.com/administration/billing/add-on-subscription.md#advanced-user-management-add-on). ## Manage project access If you have set up an external integration to GitHub, GitLab, or Bitbucket and your users can't clone the project locally, see how to [troubleshoot source integrations](https://docs.upsun.com../integrations/source/troubleshoot.md). ### Project roles A user can have one of the following roles to control their access at project level: | Role | View environment | Push code | Manage user access | Change settings | Execute actions on all environments | |----------------|------------------|-----------|--------------------|-----------------|-------------------------------------| | Project admin | Yes | Yes | Yes | Yes | Yes | | Project viewer | Yes | No | No | No | No | By default, organization owners have **Project admin** access on all of the projects within their organization. ### Environment type roles An environment type (Production, Staging, and Development) groups one or more environments together so that you can manage access for all environments of that type: - A role assigned to an environment type applies to all environments of that type. - Only one environment per project can be of the type: Production. It is set automatically as the default branch and can't be overridden separately. - You can change an environment's type (except for the Production environment). - You can have multiple preview (staging and development) environments. A user can have one of the following roles on an environment type which grants them permissions on all environments of this type: | Role | View environment | Force push | Push code | Branch environment | SSH access | Change settings | Execute actions | |-------------|------------------|------------|-----------|--------------------|------------|-----------------|-----------------| | Admin | Yes | Yes | Yes | Yes | Yes | Yes | Yes | | 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](https://docs.upsun.com/create-apps/image-properties/access.md). ### View a user's permissions across all of the projects in your organization For each user, you can view a summary of their roles and permissions across all projects in your organization. - Open the organization menu (your organization name in the upper-left). - Click **Users**. - For the user whose user permissions you want to view, click **More More**. - Click **Edit user**. ### Add a user to a project To invite a user, you need to be a [project admin](#project-roles). To add a user, follow these steps: For example, if you want to add ``user1@example.com`` to the project as a project admin, run the following command: ```bash {} upsun user:add user1@example.com -r admin ``` If you want to add ``user2@example.com`` to the project as a contributor for Development environments and a viewer for Staging environments, run the following command: ```bash {} upsun user:add user2@example.com -r development:contributor -r staging:viewer ``` - Select the project where you want to add a new user. - Click Settings **Settings**. - Click **Access**. - Click **+ Add**. - Add the user’s details and choose their permissions. - Click **Save**. The user has to create an account before they can access the project. Once you add a user to a project, they receive an invitation email with instructions. To apply SSH access changes after you add a user to a project, [trigger a redeploy](https://docs.upsun.com../development/troubleshoot.md#force-a-redeploy). ### Manage project users To manage user permissions on a project, you need to be a [project admin](#project-roles), be an organization owner, or have the [**Manage users** permission for the organization](#organization-permissions). To change user permissions, follow these steps: If you want ``user1@example.com`` to be a viewer for Production environments and a contributor for Development environments, run the following command: ```bash {} upsun user:update user1@example.com -r production:viewer,development:contributor ``` - Select the project where you want to update user access. - Click Settings **Settings**. - Click **Access**. - Click the user you want to update permissions for. - Update environment type permissions, or click **Remove user**. - Click **Accept**. To apply SSH access changes after you add a remove a user from a project or environment type, [trigger a redeploy](https://docs.upsun.com../development/troubleshoot.md#force-a-redeploy). ### Remove a user from a project To remove a user from a project, you need to be a [project admin](#project-roles), be an organization owner, or have the [**Manage users** permission for the organization](#organization-permissions). To remove a user, follow these steps: - Open the organization menu (your organization name in the upper-left). - Click **Users**. - For the user you want to remove, click **More More**. - Click on the **Projects** tab - For the project you want to remove them from, click **More More**. - Click **Remove from project**. - Click **Yes**. To apply SSH access changes after changing a user's permissions for an environment type, [trigger a redeploy](https://docs.upsun.com../development/troubleshoot.md#force-a-redeploy). ## Manage organization access All users who are added to any project within an organization become members of that organization. By default, such users have no [organization permissions](#organization-permissions). You can also have organization users who aren't part of any projects. Users who are a part of an organization with the **List projects** permission can see all projects in that organization at the organization's URL, which takes the form `https://console.upsun.com/`. They can only access projects they've been explicitly invited to. For more information on project access control, see how to [manage project users](#manage-project-users). ### Organization permissions As an organization owner or an organization user with the **Manage users** permission, you can invite other users to your organization and grant them the following permissions: - **Admin** (`owner`): Manage the organization and access all organization permissions, including all listed below. - **Manage billing** (`billing`): Add, remove, and edit billing information. Access invoices and vouchers. Users with this permission receive monthly invoices by email. - **Manage users** (`members`): Add, remove, and edit organization-level users and permissions, except their own. Users with this permission can't grant other users permissions that they themselves don't have. - **Create projects** (`projects:create`): Create new projects within the organization. - **List projects** (`projects:list`): See all projects in an organization, even those the user can't access. **Note**: Users with the **Manage users** (``members``) permission can add, edit, or remove any user’s permissions except their own. Users with the **Manage billing** (``billing``) permission automatically are granted **List projects** (``projects:list``) permission. That is, they are able to see all organization projects once given billing rights. Users without any of these permissions can only access [projects where they're users](#project-roles). They can't access or manage the rest of the organization. Organization owners have all permissions within their organization. Their permission level can't be edited. Organization owners can't be removed from their organization, except through an [ownership transfer](https://docs.upsun.com../administration/organizations.md#transfer-project-ownership). #### Viewer permissions A user is considered a viewer only if **all** of the following are true: - Their organization-level permissions are limited to **view**, `project:list`, or **billing** - They are **not** an admin or contributor on any project - They do **not** have team-level access that grants admin permissions **Note**: If any of these conditions are not met, the user is counted as an **admin** for billing. ### Add a user to an organization For example, to invite ``alice@example.com`` to the ``acme`` organization with the **Manage billing** and **Create projects** permissions, run the following command: ```bash {} upsun organization:user:add alice@example.com --org acme --permission billing,projects:create ``` - Open the organization menu (your organization name in the upper-left). - Click **Users**. - Click **+ Invite users**. - Enter the users’ email addresses separated by commas. - Select which organization-wide permissions they should have. - Click **Invite**. All users you invite receive an invitation email with instructions. ### Manage organization users For example, to update the permissions for ``alice@example.com`` in your ``acme`` organization so that she has only the **Manage billing** permission, run the following command: ```bash {} upsun organization:user:update alice@example.com --org acme --permission billing ``` - Open the organization menu (your organization name in the upper-left). - Click **Users**. - Next to the user you want to manage, click **More More**. - Click **Edit user**. You see all the projects the user is a part of and their permissions in those projects. You also see their permissions across the organization. To edit their organization permissions, follow these steps: - Select or clear the checkboxes for the relevant permissions. - Click **Save**. - Click **Yes**. ### Remove a user from an organization For example, to remove ``alice@example.com`` from your ``acme`` organization, run the following command: ```bash {} upsun organization:user:delete alice@example.com --org acme ``` - Open the organization menu (your organization name in the upper-left). - Click **Users**. - Next to the user you want to remove, click **More More**. - Click **Remove from organization**. To delete users in bulk, select the users to remove and click **Remove users from organization**. Remove a user from an organization will remove them from all projects they were a member of. --- # Source: https://docs.upsun.com/integrations/activity/utility.md # Utility routines The following utility routines can help simplify common tasks in your activity scripts. They’re free to copy, modify, bend, fold, spindle, and mutilate as needed for your own scripts. They also demonstrate some common patterns for working with the ``activity`` and ``project`` data structures. ## Route access ```javascript /** * Returns just those routes that point to a valid upstream. * * This method is similar to routes(), but filters out redirect routes that are rarely * useful for app configuration. If desired it can also filter to just those routes * whose upstream is a given application name. To retrieve routes that point to the * current application where the code is being run, use: * * routes = getUpstreamRoutes(applicationName); * * @param {string} [appName] * The name of the upstream app on which to filter, if any. * @return {object} * An object map of route definitions. The generated URLs of the routes are added as a "url" key. */ function getUpstreamRoutes(appName) { return Object.entries(activity.payload.deployment.routes).reduce( (upstreams, [url, route]) => route.type === "upstream" && (!appName || appName === route.upstream.split(":")[0]) ? { ...upstreams, [url]: { ...route, url, }, } : upstreams, {} ); } ``` ```javascript /** * Returns the primary route. * * The primary route is the one marked primary in `.upsun/config.yaml`, or else * the first non-redirect route in that file if none are marked. * * @return {object} * The route definition. The generated URL of the route is added as a "url" key. */ function getPrimaryRoute() { return Object.entries(activity.payload.deployment.routes).reduce( (primary, [url, route]) => route.primary ? { ...route, url, } : primary, {} ); } ``` ```javascript /** * Returns the route definition that has the specified id. * * Note: If no route ID was specified in .upsun/config.yaml then it will not be possible * to look up a route by ID. * * @param {string} id * The ID of the route to load. * @return {object} * The route definition. The generated URL of the route is added as a "url" key. * @throws {Error} * If there is no route by that ID, an exception is thrown. */ function getRoute(id) { const found = Object.entries(activity.payload.deployment.routes).reduce( (foundRoute, [url, route]) => route.id === id ? { ...route, url, } : foundRoute, null ); if (found === null) { throw new Error(`No such route id found: ${id}`); } return found; } ``` --- # Source: https://docs.upsun.com/add-services/valkey.md # Valkey [Valkey](https://valkey.io/) is an open source datastore that can be used high-performance data retrieval and key-value storage. Upsun supports two different Valkey configurations: - [Persistent](#persistent-valkey): to set up fast persistent storage for your application - [Ephemeral](#ephemeral-valkey): to set up a non-persistent cache for your application ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 8.1 - 8.0 ## Service types Depending on your needs, you can set up Valkey as [persistent](#persistent-valkey) or [ephemeral](#ephemeral-valkey). ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "username": null, "fragment": null, "ip": "169.254.135.174", "cluster": "ptnmwvw4dhgbi-main-bvxea6i", "path": null, "query": {}, "password": null, "port": 6379, "host_mapped": false, "service": "cache", "hostname": "azertyuiopqsdfghjklm.valkey.service._.eu-1.platformsh.site", "epoch": 0, "rel": "valkey", "scheme": "valkey", "type": "valkey:8.1", "public": false } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_VALKEY_HOST="$(echo "$RELATIONSHIPS_JSON" | jq -r '.valkey[0].host')" ``` The format of the relationship is identical whether your Valkey service is [ephemeral](#ephemeral-valkey) or [persistent](#persistent-valkey). **Database access**: It should be noted that when you set up a relationship connection, access to all of the databases is automatically granted. ## Persistent Valkey By default, Valkey is an ephemeral service that stores data in memory. This allows for fast data retrieval,but also means data can be lost when a container is moved or shut down. To solve this issue, configure your Valkey service as persistent. Persistent Valkey stores data on a disk,restoring it if the container restarts. To switch from persistent to ephemeral Valkey, set up a new service with a different name. **Warning**: Upsun sets the maximum amount of memory (``maxmemory``) Valkey can use for the data set,and it cannot be amended. It is defined by comparing the following values and keeping the lower of the two: - Disk size - The amount of memory allocated to the service container For instance, if your Valkey container has 3072 MB of disk space and 1024 MB of memory, only 512 MB of RAM are actually available to the service (3072/6 = 512). But if your Valkey container has 3072 MB of disk space and 256 MB of memory, only 256 MB of Valkey are actually available to the service (as per the container limit). ### Usage example #### 1. Configure the service To define the service, use the `valkey-persistent` endpoint: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: valkey-persistent: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. #### 2. Define the relationship To define the relationship, use the `valkey` endpoint : ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: valkey ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). For PHP, enable the [extension](https://docs.upsun.com/languages/php/extensions) for the service: ```yaml {} applications: # The name of the app container. Must be unique within a project. : # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: valkey ``` ### Configuration example ```yaml {} applications: # The name of the app container. Must be unique within a project. : source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: valkey: services: # The name of the service container. Must be unique within a project. valkey: valkey: valkey-persistent: 8.1" ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : source: root: "myapp" [...] # PHP extensions. runtime: extensions: - valkey # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: valkey: service: valkey endpoint: valkey services: # The name of the service container. Must be unique within a project. valkey: type: valkey-persistent:8.1" ``` ## Ephemeral Valkey By default, Valkey is an ephemeral service that serves as a non-persistent cache. Ephemeral Valkey stores data only in memory and requires no disk space. When the service reaches its memory limit, it triggers a cache cleanup. To customize those cache cleanups, set up an [eviction policy](#eviction-policy). Make sure your app doesn't rely on ephemeral Vedis for persistent storage as it can cause issues. For example, if a container is moved during region maintenance,the `deploy` and `post_deploy` hooks don't run and an app that treats the cache as permanent shows errors. To prevent data from getting lost when a container is moved or shut down, you can use the [persistent Valkey](#persistent-valkey) configuration. Persistent Valkey provides a cache with persistent storage. ### Usage example #### 1. Configure the service To define the service, use the `valkey` endpoint: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: valkey: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. #### 2. Define the relationship To define the relationship, use the `valkey` endpoint : ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : ``` You can define ```` as you like, so long as it’s unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the name of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: valkey ``` You can define ```` and ```` as you like, so long as it’s unique between all defined services and relationships and matches in both the application and services configuration. The example above leverages [explicit endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. Depending on your needs, instead of explicit endpoint configuration, you can use [default endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container now has [access to the service](#use-in-app) via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). For PHP, enable the [extension](https://docs.upsun.com/languages/php/extensions) for the service: ```yaml {} applications: # The name of the app container. Must be unique within a project. : source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : services: # The name of the service container. Must be unique within a project. : type: valkey: ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. : source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: : service: endpoint: valkey services: # The name of the service container. Must be unique within a project. : type: valkey: ``` ### Configuration example ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: valkey: services: # The name of the service container. Must be unique within a project. valkey: type: valkey: 8.1" ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: valkey: service: valkey endpoint: valkey services: # The name of the service container. Must be unique within a project. valkey: type: valkey: 8.1" ``` ### Use in app To use the configured service in your app, add a configuration file similar to the following to your project. ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows simplified configuration leveraging a default service # (identified from the relationship name) and a default endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: valkey: services: # The name of the service container. Must be unique within a project. valkey: type: valkey: 8.1" ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: source: root: "myapp" [...] # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: valkey: service: valkey endpoint: valkey services: # The name of the service container. Must be unique within a project. valkey: type: valkey: 8.1" ``` This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory. `myapp` has access to the `valkey` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship) (as per [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships). From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference). ```bash {location="myapp/.environment"} # Set environment variables for individual credentials. # For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables. export CACHE_HOST="${VALKEY_HOST}" export CACHE_PORT="${VALKEY_PORT}" export CACHE_PASSWORD="${VALKEY_PASSWORD}" export CACHE_SCHEME="${VALKEY_SCHEME}" # Surface a Valkey connection string for use in app. export CACHE_URL="${CACHE_SCHEME}://${CACHE_PASSWORD}@${CACHE_HOST}:${CACHE_PORT}" ``` The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``CACHE_URL`` can be used within the application to connect to the service. Note that ``CACHE_URL``, and all Upsun [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) like ``VALKEY_HOST``, are environment-dependent. Unlike the build produced for a given commit, they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment. A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](https://docs.upsun.com/get-started.md). ## Eviction policy When Valkey reaches its memory limit, it triggers a cache cleanup. To customize those cache cleanups, set up an eviction policy such as the following: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. valkey: type: "valkey:8.1" configuration: maxmemory_policy: allkeys-lfu ``` The following table presents the possible values: | Value | Policy description | |-------------------|-------------------------------------------------------------------------------------------------------------| | `allkeys-lru` | Removes the oldest cache items first. This is the default policy when `maxmemory_policy` isn't set. | | `noeviction` | New items aren’t saved when the memory limit is reached. | | `allkeys-lfu` | Removes least frequently used cache items first. | | `volatile-lru` | Removes least recently used cache items with the `expire` field set to `true`. | | `volatile-lfu` | Removes least frequently used cache items with the `expire` field set to `true`. | | `allkeys-random` | Randomly removes cache items to make room for new data. | | `volatile-random` | Randomly removes cache items with the `expire` field set to `true`. | | `volatile-ttl` | Removes cache items with the `expire` field set to `true` and the shortest remaining `time-to -live` value. | For more information on the different policies, see the official [Valkey documentation](https://valkey.io/topics/lru-cache/). ## Access your Valkey service After you've [configured your Valkey service](#usage-example), you can access it using either the Upsun CLI or through the [Valkey CLI](https://valkey.io/topics/cli/). ### Upsun CLI Unlike the Valkey CLI, connecting via the Upsun CLI does not require additional authentication steps if you are already authenticated in your terminal. Access your Valkey service by running the command: ```bash upsun valkey ``` ### Valkey CLI Retrieve the hostname and port you can connect to through the `PLATFORM_RELATIONSHIPS` [environment variable](https://docs.upsun.com../../development/variables/use-variables.md#use-provided-variables). To do so, run the `upsun relationships` command. After you've retrieved the hostname and port, [open an SSH session](https://docs.upsun.com../development/ssh.md). To access your Valkey service, run the following command: ```bash valkey-cli -h -p ``` To get the current configuration, run the following command: ```bash valkey-cli -h -p info ``` ## Use Valkey as a handler for PHP sessions A PHP session allows you to store different data for each user through a unique session ID. By default, PHP handles sessions using files. But you can use Valkey as a session handler, which means Valkey stores and retrieves the data saved into sessions. To set up Valkey as your session handler, add a configuration similar to the following: ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: source: root: "myapp" type: "php:8.5" # PHP extensions. runtime: extensions: - redis relationships: valkeysession: variables: php: session.save_handler: valkey session.save_path: "tcp://:" web: locations: '/': root: 'web' passthru: '/index.php' services: # The name of the service container. Must be unique within a project. valkeysession: type: "valkey-persistent:8.1" ``` .upsun/config.yaml ```yaml {} applications: # The name of the app container. Must be unique within a project. myapp: source: root: "myapp" type: "php:8.5" # PHP extensions. runtime: extensions: - redis # Relationships enable access from this app to a given service. # The example below shows configuration with an explicitly set service name and endpoint. # See the Application reference for all options for defining relationships and endpoints. relationships: valkeysession: service: valkeysession endpoint: valkey variables: php: session.save_handler: valkey session.save_path: "tcp://:" web: locations: '/': root: 'web' passthru: '/index.php' services: # The name of the service container. Must be unique within a project. valkeysession: type: "valkey-persistent:8.1"" ``` ## Migrate from Redis to Valkey It is possible for a user to switch from `redis-persistent` to `valkey-persistent` without losing data. To make this switch, change the type of the service from `redis-persistent` to `valkey-persistent` (also note the version change), while keeping the same service name. For example, replace this: ```json my_service_name: type: redis-persistent:7.2 disk: 256 ``` with the following: ```json my_service_name: type: valkey-persistent:8.1" disk: 256 ``` ## Further resources ### Documentation - [Valkey documentation](https://valkey.io/topics/) --- # Source: https://docs.upsun.com/development/variables.md # Source: https://docs.upsun.com/create-apps/image-properties/variables.md # variables A variables dictionary that defines variables to control the environment. Optional in [single-runtime](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](https://docs.upsun.com/create-apps/app-reference/composable-image.md#primary-application-properties) images. Upsun provides a number of ways to set [variables](https://docs.upsun.com/development/variables.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](https://docs.upsun.com/development/variables.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](https://docs.upsun.com/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 {} applications: myapp: type: 'python:3.14' source: root: "/" variables: env: AUTHOR: 'Juan' d8config: "system.site:name": 'My site rocks' ``` .upsun/config.yaml ```yaml {} applications: myapp: type: "composable:25.11" source: root: "/" stack: runtimes: [ "python@3.14" ] variables: env: AUTHOR: 'Juan' d8config: "system.site:name": 'My site rocks' ``` You can also define and access more [complex values](https://docs.upsun.com/development/variables/use-variables.md#access-complex-values). --- # Source: https://docs.upsun.com/add-services/varnish.md # Varnish Varnish is a popular HTTP proxy server, often used for caching. You usually don't need it with Upsun as the standard router includes HTTP cache and a CDN would cover more advanced uses. But you can include Varnish as a service. ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 7.6 - 6.0 ## How it works All incoming requests go through the [standard router](https://docs.upsun.com../define-routes.md). The Varnish service sits between the router and all apps in the project. ```mermaid {no-copy="true"} graph LR A(Request) -->B(Router) B --> C{Varnish} C -->D[App 1] C -->E[App 2] ``` ## Usage example ### 1. Configure the service To define the service, use the `varnish` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: varnish: relationships: : ':http' configuration: vcl: !include type: string path: config.vcl ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. The `relationships` block defines the connection between Varnish and your app. You can define ```` as you like. ```` should match your app's `name` in the [app configuration](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md). The `configuration` block must reference a VCL file inside the `.upsun` directory. The `path` defines the file relative to the `.upsun` directory. #### Example configuration ```yaml {location=".upsun/config.yaml"} applications: # The name of the app container. Must be unique within a project. myapp: ... services: # The name of the service container. Must be unique within a project. varnish: type: varnish:7.6 relationships: application: 'myapp:http' configuration: vcl: !include type: string path: config.vcl ``` Notice the `relationship` (`application`) defined for the service `varnish` granting access to the application container `myapp`. ### 2. Create a VCL template To tell Varnish how to handle traffic, in the `.upsun` directory add a [Varnish Configuration Language (VCL) template](https://www.varnish-software.com/developers/tutorials/example-vcl-template/). This template is supplemented by automatic additions from Upsun. So you MUST NOT include certain features that you might elsewhere: - A `vcl_init()` function: The function is automatically generated based on the relationships you defined in Step 1. Each defined relationship results in a backend with the same name. - The VCL version at the start: This is automatically generated. - Imports for `std` or `directors`: These are already imported. You can import other [modules](#include-modules). The file MUST include: - A definition of which backend to use in a `vcl_recv()` subroutine. The logic varies based on whether you have one or more apps. **Note**: Misconfigured VCL files can result in incorrect and confusing behavior that’s hard to debug. Upsun doesn’t help with VCL configuration options beyond the basic connection logic documented here. You can see any compilation errors with the [stats endpoint](#stats-endpoint). #### Example VCL template with one app To serve one app, your VCL template needs at least the following function: ```bash {location="config.vcl" } sub vcl_recv { set req.backend_hint = .backend(); } ``` Where `` is the name of the relationship you defined in [Step 1](#1-configure-the-service). With the [example configuration](#example-configuration), that would be the following: ```bash {location="true/config.vcl"} sub vcl_recv { set req.backend_hint = application.backend(); } ``` #### Example VCL template with multiple apps If you have multiple apps fronted by the same Varnish instance, your VCL templates needs logic to determine where each request is forwarded. For example, you might have the following configuration for two apps: ```yaml {location=".upsun/config.yaml"} # The name of the service container. Must be unique within a project. services: varnish: type: varnish:7.6 relationships: blog: service: blog endpoint: http main: service: myapp endpoint: http configuration: vcl: !include type: string path: config.vcl applications: # The name of the app container. Must be unique within a project. blog: # The location of the application's code. source: root: "backends/blog" # The type of the application to build. type: "php:8.5" # The name of the app container. Must be unique within a project. myapp: # The location of the application's code. source: root: "backends/main" # The type of the application to build. type: "nodejs:8.5" ``` You could then define that all requests to `/blog/` go to the `blog` app and all other requests to the other app: ```bash {location="true/config.vcl"} sub vcl_recv { if (req.url ~ "^/blog/") { set req.backend_hint = blog.backend(); } else { set req.backend_hint = main.backend(); } } ``` ### 3. Route incoming requests to Varnish Edit your [route definitions](https://docs.upsun.com../define-routes.md) to point to the Varnish service you just created. Also disable the router cache as Varnish now provides caching. To forward all incoming requests to Varnish rather than your app, you could have the following: ```yaml {location=".upsun/config.yaml"} routes: "https://{default}/": type: upstream upstream: "varnish:http" cache: enabled: false ``` Varnish forwards requests to your app based on the specified VCL template. ## Include modules You can include the following optional modules in your VCL templates to add additional features: - `cookie` - `header` - `saintmode` - `softpurge` - `tcp` - `var` - `vsthrottle` - `xkey` To use them, add an import to your template such as the following: ```bash {location="true/config.vcl"} import xkey; ``` ## Circular relationships At this time, Upsun doesn't support circular relationships between services and apps. That means you can't add a relationship from an app fronted by Varnish to the Varnish service. If you do so, then one of the relationships is skipped and the connection doesn't work. ## Rate limit connections Sometimes you want to ensure that users, whether human or machine, can't overload your app with requests. One tool to help is using Varnish to limit the rate at which connections can be made. For example, say you want to make sure no one can make more than 20 requests within 10 seconds. If they do, you want to block them from any more requests for 2 minutes. To do so, [import the `vsthrottle` module](#include-modules) and add logic similar to the following to your VCL template: ```bash {location="true/config.vcl"} import vsthrottle; sub vcl_recv { # The Upsun router provides the real client IP as X-Client-IP # This replaces client.identity in other implementations if (vsthrottle.is_denied(req.http.X-Client-IP, 20, 10s, 120s)) { # Client has exceeded 20 requests in 10 seconds. # When this happens, block that IP for the next 120 seconds. return (synth(429, "Too Many Requests")); } # Set the standard backend for handling requests that aren't limited set req.backend_hint = application.backend(); } ``` ## Clear cache with a push You may want at times to clear a specific part of your cache when you know the content is outdated. With Varnish, you can clear the content with [purging and banning](https://varnish-cache.org/docs/trunk/users-guide/purging.md). The following example shows how to set up purging. 1. Add an access control list to your VCL template: ```bash {location="true/config.vcl"} acl purge { "localhost"; "192.0.2.0"/24; } ``` This list ensures that only requests from the listed IPs are accepted. Choose which IPs to allow. If you are sending requests from an app, checkout the [outbound IPs for the region](https://docs.upsun.com../development/regions.md#public-ip-addresses). Alternatively, you could code in a token that must be sent with the request. 2. Add purge handling: ```bash {location="true/config.vcl"} sub vcl_recv { if (req.method == "PURGE") { # The Upsun router provides the real client IP as X-Client-IP # Use std.ip to convert the string to an IP for comparison if (!std.ip(req.http.X-Client-IP, "0.0.0.0") ~ purge) { # Deny all purge requests not from the allowed IPs return(synth(403,"Not allowed.")); } # Purge cache for allowed requests return (purge); } ... } ``` **Note**: The snippet above has been produced for Varnish 7.x. If using a different version, consult the [Varnish documentation](https://varnish-cache.org/docs/) for potential differences in syntax and required parameters. 3. Set up cache purging to suit your needs. The following cURL call gives an example of how this can work: ```bash curl -X PURGE "" ``` ## Stats endpoint The Varnish service also offers an `http+stats` endpoint, which provides access to some Varnish analysis and debugging tools. You can't use it from an app fronted by Varnish because of the restriction with [circular relationships](#circular-relationships). To access the stats, create a **separate app** (`stats-app`) with a relationship *to* Varnish, but not *from* it. Define [app configuration](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md) similar to the following: ```yaml {location=".upsun/config.yaml"} applications: # The name of the app container. Must be unique within a project. stats-app: # The location of the application's code. source: root: "stats" # The type of the application to build. type: "python:3.14" # Unique relationship _to_ Varnish from 'stats-app', where no relationship # is defined _from_ Varnish to the same app, to avoid circular relationships. relationships: varnishstats: service: varnish endpoint: http+stats # The name of the app container. Must be unique within a project. main-app: # The location of the application's code. source: root: "backends/main" # The type of the application to build. type: "nodejs:24" services: # The name of the service container. Must be unique within a project. varnish: type: varnish:7.6 # Unique relationship _from_ Varnish _to_ 'main-app', where no relationship # is defined _to_ Varnish to the same app, to avoid circular relationships. relationships: main: service: "main-app" endpoint: "http configuration: vcl: !include type: string path: config.vcl ``` You choose any valid name and type. When the app is deployed, the app can access the Varnish service over HTTP to get diagnostic information. The following paths are available: - `/`: returns any error logged when generating the VCL template failed - `/config`: returns the generated VCL template - `/stats`: returns the output of `varnishstat` - `/logs`: returns a streaming response of `varnishlog` To access the Varnish stats endpoint from the command line: 1. Connect to your stats app [using SSH](https://docs.upsun.com../development/ssh/_index.md): `upsun ssh --app stats-app` (replace `stats-app` with the name you gave the app). 2. Display the [relationships array](https://docs.upsun.com/create-apps/image-properties/relationships.md) with `echo $PLATFORM_RELATIONSHIPS | base64 -d | jq .`, 3. Query Varnish with `curl :/stats`, replacing `` and `` with the values from Step 2. --- # Source: https://docs.upsun.com/create-apps/hooks/vary-hooks-by-environment.md # Change hooks in different environments You might have certain commands you want to run only in certain environments. For example enabling detailed logging in preview environments or purging your CDN cache for production environments. The `deploy` and `post_deploy` hooks can access all [runtime environment variables](https://docs.upsun.com../../development/variables/use-variables.md#use-provided-variables). Use this to vary those hooks based on the environment. Check the `PLATFORM_ENVIRONMENT_TYPE` variable to see if it's in a production environment: ```yaml {location=".upsun/config.yaml"} applications: myapp: hooks: deploy: | if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then # Run commands only when deploying to production else # Run commands only when deploying to development or staging environments fi # Commands to run regardless of the environment ``` --- # Source: https://docs.upsun.com/add-services/vault.md # Vault key management service The Vault key management service (KMS) provides key management and access control for your secrets. The Upsun Vault KMS offers the [transit secrets engine](https://developer.hashicorp.com/vault/docs/secrets/transit) to sign, verify, encrypt, decrypt, and rewrap information. Vault doesn't store the data sent to the transit secrets engine, so it can be viewed as encryption as a service. To store secrets such as API keys, create sensitive [environment variables](https://docs.upsun.com../development/variables.md). ## Supported versions You can select the major and minor version. Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches. - 1.12 ## Relationship reference For each service [defined via a relationship](#usage-example) to your application, Upsun automatically generates corresponding environment variables within your application container, in the ``$_`` format. Here is example information available through the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) themselves, or through the [``PLATFORM_RELATIONSHIPS`` environment variable](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). For some advanced use cases, you can use the [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables). The structure of the ``PLATFORM_RELATIONSHIPS`` environment variable can be obtained by running ``upsun relationships`` in your terminal: ```json {} { "username": "", "scheme": "http", "service": "vault-kms", "fragment": "", "ip": "123.456.78.90", "instance_ips": [ "123.456.78.90" ], "hostname": "azertyuiopqsdfghjklm.vault-kms.service._.eu-1.platformsh.site", "port": 8200, "cluster": "azertyuiopqsdf-main-7rqtwti", "host": "vault_secret.internal", "rel": "sign", "path": "\/", "query": { "is_master": true }, "password": "ChangeMe", "type": "vault-kms:1.12", "public": false, "host_mapped": false } ``` Here is an example of how to gather [PLATFORM_RELATIONSHIPS](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) information in a [.environment](https://docs.upsun.com/development/variables/set-variables.md#use-env-files): .environment ```bash {} # Decode the built-in credentials object variable. export RELATIONSHIPS_JSON="$(echo "$PLATFORM_RELATIONSHIPS" | base64 --decode)" # Set environment variables for individual credentials. export APP_VAULT_HOST=="$(echo "$RELATIONSHIPS_JSON" | jq -r '.vault_secret[0].host')" ``` ## Usage example ### 1. Configure the service To define the service, use the `vault-kms` type: ```yaml {location=".upsun/config.yaml"} services: # The name of the service container. Must be unique within a project. : type: vault-kms: configuration: endpoints: : - policy: key: type: ``` Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service. - is the name you choose to identify the service. - is a supported version of the service. - is an identifier you choose for the endpoint. - is the name of the key to be stored in the Vault KMS. - is one of the available [policies](#policies) based on what you want to accomplish. - The `type` is one of: - `sign`: for signing payloads, with the type `ecdsa-p256` - `encrypt` (for encrypt`chacha20-poly1305`). The `type` can't be changed after creation. You can create multiple endpoints, such as to have key management separate from key use. 512 MB is the minimum required disk space for the Vault KMS service. ### 2. Define the relationship To define the relationship, use the following configuration: ```yaml {location=".upsun/config.yaml"} applications: # The name of the app container. Must be unique within a project. : # Relationships enable access from this app to a given service. relationships: : service: endpoint: services: # The name of the service container. Must be unique within a project. : type: vault-kms: configuration: endpoints: : - policy: key: type: ``` You can define `` as you like, so long as it's unique between all defined services and matches in both the application and services configuration. The example above leverages [default endpoint](https://docs.upsun.com/create-apps/image-properties/relationships.md) configuration for relationships. That is, it uses default endpoints behind the scenes, providing a [relationship](https://docs.upsun.com/create-apps/image-properties/relationships.md) (the network address a service is accessible from) that is identical to the _name_ of that service. Depending on your needs, instead of default endpoint configuration, you can use [explicit endpoint configuration](https://docs.upsun.com/create-apps/image-properties/relationships.md). With the above definition, the application container (````) now has access to the service via the relationship ```` and its corresponding [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables). If you split the service into multiple endpoints, define multiple relationships. ### Example configuration ```yaml {location=".upsun/config.yaml"} applications: # The name of the app container. Must be unique within a project. myapp: relationships: vault_secret: "vault-kms:manage_keys" services: # The name of the service container. Must be unique within a project. vault-kms: type: vault-kms:1.12 configuration: endpoints: manage_keys: - policy: admin key: vault-sign type: sign - policy: sign key: vault-sign type: sign - policy: verify key: vault-sign type: sign ``` ## Multiple endpoints example ```yaml {location=".upsun/config.yaml"} applications: # The name of the app container. Must be unique within a project. myapp: relationships: vault_manage: service: vault-kms endpoint: management vault_sign: service: vault-kms endpoint: sign_and_verify services: # The name of the service container. Must be unique within a project. vault-kms: type: vault-kms:1.12 configuration: endpoints: management: - policy: admin key: admin-key type: sign sign_and_verify: - policy: sign key: signing-key type: sign - policy: verify key: signing-key type: sign ``` ## Use Vault KMS To connect your app to the Vault KMS, use a token that's defined in the [service environment variables](#relationship-reference). With this token for authentication, you can use any of the policies you [defined in your `.upsun/config.yaml` file](#1-configure-the-service). You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``. Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](https://docs.upsun.com/development/variables.md#service-environment-variables) directly rather than hard coding any values. The following examples use cURL as an example, which you could do in a hook or after accessing your app with SSH. Adapt the examples for your app's language. ### Get the token To make any calls to the Vault KMS, you need your token. Get it from the [service environment variables](#relationship-reference): ```bash echo ${_PASSWORD}" ``` `` is the relationship name you [defined in your `.upsun/config.yaml` file](#2-define-the-relationship). You can also store this as a variable: ```bash VAULT_TOKEN=${_PASSWORD} ``` A given token is valid for one year from its creation. ### Get the right URL The [service environment variable](#relationship-reference) also contains the information you need to construct a URL for contacting the Vault KMS: the `host` and `port`. Assign it to a variable as follows: ```bash VAULT_URL=${_HOST}:${_PORT} ``` `` is the name you [defined in your `.upsun/config.yaml` file](#2-define-the-relationship). ### Manage your keys Your key names are [defined in your `.upsun/config.yaml` file](#1-configure-the-service). You can manage them if you've set an [admin policy](#policies) for them. To get information on a key, such as its expiration date, run the following command: ```bash curl \ --header "X-Vault-Token: $VAULT_TOKEN" \ http://"$VAULT_URL"/v1/transit/keys/"$KEY_NAME" | jq . ``` `$KEY_NAME` is the name in your `.upsun/config.yaml` file. To rotate the version of your key, run the following command: ```bash curl \ --header "X-Vault-Token: $VAULT_TOKEN" \ http://"$VAULT_URL"/v1/transit/keys/"$KEY_NAME">/rotate \ --request POST ``` ### Sign and verify payloads If you've set [sign and verify policies](#policies), you can use your keys to sign and verify various payloads, such as a JSON Web Token (JWT) for authentication in your app. Note that all payloads (all plaintext data) must be base64-encoded. To sign a specific payload, run the following command: ```bash curl \ --header "X-Vault-Token: $VAULT_TOKEN" \ http://$VAULT_URL/v1/transit/sign/"$KEY_NAME"/sha2-512 \ --data "{\"input\": \"$(echo SECRET | base64)\"}" ``` The string at the end of the URL denotes the specific [hash algorithm used by the Vault KMS](https://www.vaultproject.io/api-docs/secret/transit#hash_algorithm). You get back a JSON object that includes the signature for the payload: ```json { "request_id": "a58b549f-1356-4028-d191-4c9cd585ca25", ... "data": { "key_version": 1, "signature": "vault-kms:v1:MEUCIAiN4UtXh..." }, ... } ``` You can then use `data.signature` to sign things such as a JWT. To verify a payload, run the following command: ```bash curl \ --header "X-Vault-Token: $VAULT_TOKEN" \ http://"$VAULT_URL"/v1/transit/verify/"$KEY_NAME"/sha2-512 \ --data " { \"input\": \"$(echo SECRET | base64)\", \"signature\": \"$SIGNATURE\" }" ``` You get back a JSON object that includes whether or not the signature is valid: ```json { "request_id": "5b624718-fd9d-37f6-8b95-b387379d2648", ... "data": { "valid": true }, ... } ``` A `true` value means the signature matches and a `false` value means it doesn't. ### Encrypt and decrypt data If you've set [encrypt and decrypt policies](#policies), you can use your keys to encrypt and decrypt any data you want. Note that all of plaintext data you work with must be base64-encoded. To sign a specific payload, run the following command: ```bash curl \ --header "X-Vault-Token: $VAULT_TOKEN" \ http://$VAULT_URL/v1/transit/encrypt/"$KEY_NAME" \ --data "{\"plaintext\": \"$(echo SECRET | base64)\"}" ``` You get back a JSON object that includes your encrypted data: ```json { "request_id": "690d634a-a4fb-bdd6-9947-e895578b79d5", ... "data": { "ciphertext": "vault-kms:v1:LEtOWSwh3N...", "key_version": 1 }, ... } ``` To decrypt data that you've already encrypted, run the following command: ```bash curl \ --header "X-Vault-Token: $VAULT_TOKEN" \ http://"$VAULT_URL"/v1/transit/decrypt/"$KEY_NAME" \ --data " { \"ciphertext\": \"$CIPHERTEXT\" }" ``` You get back a JSON object that your decrypted data base64-encoded: ```json { "request_id": "bbd411ca-6ed7-aa8b-8177-0f35055ce613", ... "data": { "plaintext": "U0VDUkVUCg==" }, ... } ``` To get the value un-encoded, add `| jq -r ".data.plaintext" | base64 -d` to the end of the `curl` command. #### Rewrap encrypted data If you have already encrypted data and you have [changed your key version](#manage-your-keys), you can rewrap the encrypted data with the new key. Assuming `$CIPHERTEXT` stores your encrypted data (`vault:v1:LEtOWSwh3N...`), run the following command: ```bash curl \ --header "X-Vault-Token: $VAULT_TOKEN" \ http://"$VAULT_URL"/v1/transit/rewrap/"$KEY_NAME" \ --data " { \"ciphertext\": \"$CIPHERTEXT\" }" ``` In the JSON object that's returned, you can notice that the `ciphertext` is different (and now includes the new key version as a prefix) as is the `key_version`: ```json { ... "data": { "ciphertext": "vault-kms:v2:ICRi0yAlH...", "key_version": 2 }, ... } ``` ## Policies | Policy | Endpoint | Capabilities | Purpose | | --------- | -------- | ------------ | ------- | | `admin` | `transit/keys/${KEY}` | `read` | Access to key properties and various functions performed on keys such as rotation and deletion | | | `transit/keys/${KEY}/*` | `read`, `create`, `update`, `delete` | | | `sign` | `transit/sign/${KEY}/${HASH_ALGORITHM}` | `read`, `update` | Signing payloads with an existing key | | `verify` | `transit/verify/${KEY}/${HASH_ALGORITHM}` | `read`, `update` | Verifying already signed payloads | | `encrypt` | `transit/encrypt/${KEY}` | `read`, `update` | Encrypting data with an existing key | | `decrypt` | `transit/decrypt/${KEY}` | `read`, `update` | Decrypting data with an existing key | | `rewrap` | `transit/rewrap/${KEY}` | `read`, `update` | Re-encrypting data with a new key version without revealing the secret | --- # Source: https://docs.upsun.com/administration/web.md # Source: https://docs.upsun.com/create-apps/web.md # Source: https://docs.upsun.com/create-apps/image-properties/web.md # web A web instance that defines how the web application is served. Optional in [single-runtime](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](https://docs.upsun.com/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. For **single-runtime images**, default values might vary based on the image [`type`](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#types), which defines the base container used to run the application. | Name | Type | Required | Description | |-------------|--------------------------------------------|-------------------------------|------------------------------------------------------| | `commands` | A [web commands dictionary](#web-commands) | See [`start`](#start) | 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](https://docs.upsun.com../web.md). ### Web commands | Name | Type | Required | Description | |--------------|----------|-------------------------------|-----------------------------------------------------------------------------------------------------| | [`pre_start`](#pre_start) | `string` | | Command run just prior to `start`, which can be useful when you need to run _per-instance_ actions. Non-blocking. | | [`start`](#start) | `string` | Typically, except for PHP; see [`start`](#start). | The command to launch your app. If it terminates, it's restarted immediately. | | [`post_start`](#post_start) | `string` | | Command runs **after** the `start` command and **before** adding the container to the router. Can be used to ensure app is active before routing traffic to it. | ### `pre_start` command {#pre_start} The `pre_start` command is **not blocking**, which means the `deploy` hook may start running **before** the `pre_start` command finishes. This can lead to unexpected behavior if `pre_start` performs setup tasks that `deploy` depends on. To avoid issues, make sure any critical initialization in `pre_start` can complete quickly or is safe to run concurrently with `deploy`. ### `start` command {#start} On all containers other than PHP, it's a best practice to include a `start` command. This command runs every time your app is restarted, regardless of whether new code is deployed. On PHP containers, `start` is optional and defaults to starting PHP-FPM (`/usr/bin/start-php-app`). You can set it 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 [Alternate start commands](https://docs.upsun.com/languages/php.md#alternate-start-commands) in the PHP topic. **Note**: Do not run a ``start`` process in the background by using ``&`` syntax. The Upsun supervisor interprets that syntax as the command terminating and starts another copy, creating a loop that continues until the container crashes. Run the command as usual and allow the Upsun supervisor to manage it. ### `post_start` command {#post_start} You can use the `post_start` command to ensure your app is fully active before traffic is routed to it. This command can perform checks or wait until your application starts listening on the expected port. For example, if your framework needs several seconds to initialize (for example, to build caches or establish database connections), `post_start` can help coordinate the handover to ensure that the app receives traffic only after it is initialized. #### Example: This example contains two web commands: - A `start` command that starts the application every time, whether or not new code is deployed. - A `post_start` command that repeatedly checks whether a service on `localhost` is responding. ```yaml {} applications: : type: "python:3.14" source: root: "/" web: commands: start: 'uwsgi --ini conf/server.ini' post_start: | date curl -sS --retry 20 --retry-delay 1 --retry-connrefused localhost -o /dev/null ``` .upsun/config.yaml ```yaml {} applications: : type: "composable:25.11" source: root: "/" stack: runtimes: [ "python@3.14" ] web: commands: start: 'uwsgi --ini conf/server.ini' post_start: | date curl -sS --retry 20 --retry-delay 1 --retry-connrefused localhost -o /dev/null ``` ### `upstream` {#upstream} ```yaml {} applications: myapp: type: 'python:3.14' source: root: "/" web: upstream: socket_family: tcp protocol: http ``` | 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](https://docs.upsun.com/create-apps/app-reference/composable-image.md#multiple-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](https://docs.upsun.com/create-apps/app-reference/composable-image.md#multiple-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: .upsun/config.yaml ```yaml {} applications: myapp: type: "composable:25.11" source: root: "/" stack: runtimes: [ "python@3.14" ] 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](https://docs.upsun.com/development/variables/use-variables.md#use-provided-variables) | | `unix` | The Unix socket file specified by the [`SOCKET` environment variable](https://docs.upsun.com/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` {#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 ](https://docs.upsun.com/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`` | ``string`` array 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](https://docs.upsun.com/create-apps/web/custom-headers.md)). 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 {} applications: myapp: type: 'python:3.14' source: root: "/" 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 ``` .upsun/config.yaml ```yaml {} applications: myapp: type: "composable:25.11" source: root: "/" stack: runtimes: [ "python@3.14" ] 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 {} applications: myapp: type: 'python:3.14' source: root: "/" web: locations: '/': passthru: true request_buffering: enabled: true max_request_size: 250m ``` .upsun/config.yaml ```yaml {} applications: myapp: type: "composable:25.11" source: root: "/" stack: runtimes: [ "python@3.14" ] web: locations: '/': passthru: true request_buffering: enabled: true max_request_size: 250m ``` --- # Source: https://docs.upsun.com/integrations/activity/webhooks.md # Webhooks Webhooks allow you to host a script yourself externally that receives the same payload as an activity script and responds to the same events, but can be hosted on your own server in your own language. ## Setup ```bash upsun integration:add --type=webhook --url= ``` The webhook URL receives a POST message for every activity that's triggered. The message contains complete information about the entire state of the project at that time. It's possible to set the integration to only send certain activity types, or only activities on certain branches. The CLI prompts you to specify which to include or exclude. Leave at the default values to get all events on all environments in a project. For testing purposes, you can generate a URL from a service such as [webhook.site](https://webhook.site/) and use the generated URL as ``. ## Webhook schema See the [activity script](https://docs.upsun.com/integrations/activity/reference.md) reference for a description of the webhook payload. ## Validate the integration To verify your integration is functioning properly, run the following [CLI command](https://docs.upsun.com/integrations/overview.md#validate-integrations): ```bash upsun integration:validate ``` --- # Source: https://docs.upsun.com/learn/overview/yaml/what-is-yaml.md # What YAML is [YAML](https://en.wikipedia.org/wiki/YAML) is a human-readable format for data serialization. This means it can be used for structured data, like what you can find in configuration files. Some basic rules about YAML files: - YAML files end in `.yaml`. Some other systems use the alternative `.yml` extension. - YAML is case-sensitive. - YAML is whitespace-sensitive and indentation defines the structure, but it doesn't accept tabs for indentation. - Empty lines are ignored. - Comments are preceded by an octothorpe `#`. ## Data types YAML represents data through three primitive data structures: - Scalars (strings/numbers/booleans) - Mappings (dictionaries/objects) - Sequences (arrays/lists) ### Scalars (strings/numbers/booleans) The most straightforward data structure involves defining key–value pairs where the values are strings or integers. So you could have a basic configuration for an app: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: "golang:1.18" source: root: /app hooks: build: ./build.sh ``` You can spot three key–value pairs: | Key | Value | | ------------------- |-------------------- | | `type` | "golang:1.18" | | `root` | root: /app | | `build ` | ./build.sh | You can define strings either with or without quotes, which can be single `'` or double `"`. Quotes let you escape characters (if double) and make sure the value is parsed as a string when you want it. For example, you might be representing version numbers and want to parse them as strings. If you use `version: 1.10`, it's parsed as an integer and so is treated the same as `1.1`. If you use `version: "1.10"`, it's parsed as a string and isn't treated as the same as `1.1`. ### Mappings (dictionaries/objects) In addition to basic scalar values, each key can also represent a set of other key–value pairs. So you can define entire dictionaries of pairs. The structure of the mapping is determined by the indentation. So children are indented more than parents and siblings have the same amount of indentation. The exact number of spaces in the indentation isn't important, just the level relative to the rest of the map. In contrast, when you define mappings, the order doesn't matter. So you could expand the configuration from before to add another mapping: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: "golang:1.18" web: commands: start: ./bin/app locations: '/': passthru: true allow: false ``` This creates a `web` dictionary that has two dictionaries within it: `commands` and `locations`, each with their own mappings: - `web` → `commands` → `start: ./bin/app` - `web` → `locations` → `'/'` → `passthru: true` and `allow: false` ### Sequences (arrays/lists) In addition to maps defining further key–value pairs, you can also use sequences to include lists of information. ```yaml {location=".upsun/config.yaml"} applications: myapp: web: locations: '/': index: - index.html - index.htm passthru: true allow: false ``` You can also define sequences using a flow syntax: ```yaml {location=".upsun/config.yaml"} applications: myapp: web: locations: '/': index: [index.html, index.htm] passthru: true allow: false ``` In either case, you get a list of values within `index`: `web` → `locations` → `'/'` → `index` → `index.html` and `index.htm` ## Define multi-line strings If you have a long string that spans multiple lines, use a pipe `|` to preserve line breaks. The new lines need to have at least the same indentation as the first (you can add more indentation that's then preserved). So you could add a multi-line string to a `build` key in the `hooks` map: ```yaml {location=".upsun/config.yaml"} applications: myapp: hooks: build: | set -x -e cp a.txt b.txt ``` And the resulting value preserves the line break. This lets you do things like enter small shell scripts within a YAML file. `hooks` → `build` → `set -x -e` and `cp a.txt b.txt` ## Reuse content YAML supports internal named references, known as anchors, which can be referenced using an alias. This allows you to reuse YAML blocks in multiple places within a single file. Define an anchor by adding `&` to the start of a value, where `` is a unique identifier. The anchor represents this entire value. Then refer to the anchor using `*`. The following example shows 4 different workers: ```yaml {location=".upsun/config.yaml"} applications: myapp: # ... workers: queue1: &runner commands: start: python queue-worker.py queue2: *runner queue3: <<: *runner ``` All of the workers above are identical to each other. Note that you need to place an alias with `<<:` at the same level as the other keys within that value. ## What's next - See what Upsun makes possible with [custom tags](https://docs.upsun.com/learn/overview/yaml/platform-yaml-tags.md). - Read everything that's possible with YAML in the [YAML specification](https://yaml.org/spec/1.2.2/). - See a [YAML file that explains YAML syntax](https://learnxinyminutes.com/docs/yaml/). --- # Source: https://docs.upsun.com/create-apps/workers.md # Source: https://docs.upsun.com/create-apps/image-properties/workers.md # workers Defines the list of worker names, which are alternate copies of the application to run as background processes. Optional in [single-runtime](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#primary-application-properties) and [composable](https://docs.upsun.com/create-apps/app-reference/composable-image.md#primary-application-properties) images. Workers require resource definition using `upsun resources:set`, same as application containers. For more information, see how to [manage resources](https://docs.upsun.com/manage-resources.md). Workers are exact copies of the code and compilation output as a `web` instance after a [`build` hook](https://docs.upsun.com/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. ```yaml {} applications: : type: 'python:3.14' source: root: "/" workers: queue: commands: start: | ./worker.sh ``` 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 [primary application properties](https://docs.upsun.com/create-apps/app-reference/composable-image.md#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: .upsun/config.yaml ```yaml {} applications: : type: "composable:25.11" source: root: "/" stack: runtimes: [ "python@3.14" ] workers: queue: commands: start: | ./worker.sh ``` --- # Source: https://docs.upsun.com/languages/php/xdebug.md # Using Xdebug p:last-child]:mb-0 [&>h3]:mt-0 rounded-lg" > ### Note You can now use composable image to install runtimes and tools in your application container. To find out more, see the [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.md) topic. [Xdebug](https://xdebug.org/) is a real-time debugger extension for PHP. While usually used for local development, it can also be helpful for debugging aberrant behavior on the server. As configured on Upsun, it avoids any runtime overhead for non-debug requests, even in production, and only allows connections via SSH tunnels to avoid any security issues. Note that Xdebug runs only on your app containers. So you can't use it for [worker containers](https://docs.upsun.com../../create-apps/workers.md). Also, note that if you use a [custom start command](https://docs.upsun.com/languages/php.md#alternate-start-commands), Xdebug is automatically disabled. ## Before you begin The following table shows the PHP versions where Xdebug is available: | 5.4 | 5.5 | 5.6 | 7.0 | 7.1 | 7.2 | 7.3 | 7.4 | 8.0 | 8.1 | 8.2 | 8.3 | 8.4 | 8.5 | | Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail Avail You also need: - The Upsun [CLI](https://docs.upsun.com../../administration/cli.md) - A Xdebug-compatible IDE installed on your machine. For setup instructions, consult your IDE's Xdebug documentation, such as that for [PHPStorm](https://www.jetbrains.com/help/phpstorm/configuring-xdebug.md). ## 1. Set up Xdebug Xdebug runs as a second PHP-FPM process used only for debugging requests, leaving the normal process unaffected. To enable Xdebug, add the following to your [app configuration](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md): ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'php:8.5' runtime: xdebug: idekey: ``` can be any arbitrary alphanumeric string. When that key is defined, Upsun starts a second PHP-FPM process on the container that's identically configured but also has Xdebug enabled. Only incoming requests that have an Xdebug cookie or query parameter set are forwarded to the debug PHP-FPM process. All other requests are directed to the normal PHP-FPM process and thus have no performance impact. If you have enabled the [router cache](https://docs.upsun.com../../define-routes/cache.md), you need to explicitly add the Xdebug cookie (`XDEBUG_SESSION`) to the cookie allowlist. Depending on the cookies already listed, the result should look similar to the following: ```yaml {location=".upsun/config.yaml"} applications: myapp: type: 'php:8.5' runtime: xdebug: idekey: routes: "https://{default}/": # ... cache: enabled: true cookies: ['/^SS?ESS/', 'XDEBUG_SESSION'] ``` Xdebug has several configuration options available. They can be set the same way as any other [PHP setting](https://docs.upsun.com/languages/php.md#php-settings). For a full list of available options, consult the [Xdebug documentation](https://xdebug.org/docs/). ## 2. Use Xdebug ### Open a tunnel To open an SSH tunnel to the server from a local checkout of your app, run the following [CLI command](https://docs.upsun.com../../administration/cli.md) : ```bash upsun environment:xdebug ``` That SSH tunnel allows your IDE and the server to communicate debug information securely. By default, Xdebug operates on port `9003`. Generally, it's best to configure your IDE to use that port. To use an alternate port, use the `--port` flag. To close the tunnel and terminate the debug connection, press Ctrl + C. ### Install an Xdebug helper While Xdebug can be triggered from the browser by adding a special query parameter, the preferred way is to use a browser plugin helper. Helpers are available for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/xdebug-helper-for-firefox/) and [Chrome](https://chrome.google.com/webstore/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc). Their respective plugin pages document how to trigger them when needed. ## 3. Configure your IDE Follow the instructions for your IDE, such as those for [PHPStorm](https://www.jetbrains.com/help/phpstorm/configuring-xdebug.md). The common steps for setup usually include: 1. Configuring the Xdebug debug port and making sure it's set to the expected value (`9003` as default or the value you chose with `--port` when opening the tunnel). 2. Making sure that external connections are allowed. 3. Adding a new server for your Upsun environment. The Host should be the hostname of the environment on Upsun you are debugging. The Port should always be `443` and the Debugger set to `Xdebug`. 4. Ensuring path mappings is enabled. This lets you define what remote paths on the server correspond to what path on your local machine. In the majority of cases you can just define [your app root](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md#root-directory) to map to `myapp`. 5. Listening for connections. 6. Starting debugging. While in listen mode, start the `upsun xdebug` tunnel. Use the Xdebug helper plugin for your browser to enable debugging. Set a break point in your app, then load a page in your browser. The request should pause at the break point and allow you to examine the running app. --- # Source: https://docs.upsun.com/learn/overview/yaml/yaml-structure.md # Upsun Fixed YAML structure In addition to the [basic functions you should be familiar with](https://docs.upsun.com/learn/overview/yaml/what-is-yaml.md), YAML structure is important. Upsun accepts a specific structure for YAML configuration files. ## YAML file location When you run the [`upsun project:init` command](https://docs.upsun.com/get-started/here/configure.md), a default ``config.yaml`` file is generated in the `.upsun` folder. It contains the minimum default configuration based on your detected local stack. This YAML file is located in your ``.upsun`` directory, at the root of your project source code, and is a good starting point before customization. ```bash . ├── .upsun | └── config.yaml └── ``` ## Top-level keys In the ``config.yaml`` file, there are three top-level YAML keys: - ``applications``: this section of the file contains all of your [app definitions](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md) **Note**: Note that ``applications`` is a **mandatory** top-level key to include in your ``config.yaml`` file. - ``routes``: this section of the file contains all of your [route definitions](https://docs.upsun.com/define-routes.md) (for each of your apps) - ``services``: this section of the file contains all of your [service definitions](https://docs.upsun.com/add-services.md) (for each of your apps) This looks like: ```yaml {location="apps"} applications: myapp: ... services: mariadb: type: mariadb:10.6 # All available versions are: 10.6, 10.5, 10.4, 10.3 routes: "https://{default}/": type: upstream upstream: "myapp:http" ``` Below these three top-level key sections, you can use any of the [available YAML tags](https://docs.upsun.com/learn/overview/yaml/platform-yaml-tags.md) you need. **Note**: Any YAML files located at the first level of your ``.upsun`` folder, at the root of your project source code, are taken in account. See [Rules on YAML files](#rules-on-yaml-files). ## Rules on YAML files The following rules apply to YAML files contained in the ``.upsun`` folder: - All the existing YAML files located at the first level of the ``.upsun`` folder are taken into account. - All the existing YAML files located at the first level of the ``.upsun`` folder must feature the [mandatory top-level keys](#top-level-keys), and must contain a [valid YAML configuration](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md). - All the YAML files in subdirectories of the ``.upsun`` folder need to be [manually imported](https://docs.upsun.com/learn/overview/yaml/platform-yaml-tags.md#include) and contain a [valid YAML configuration](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.md). **Warning**: When Upsun combines all the YAML files located at the first level of the ``.upsun`` folder, only the top-level keys (``applications``, ``services``, and ``routes``) are merged. So if you define an app named ``myapp`` in two different YAML files, Upsun only takes the second one into account. Example: .upsun/app.yaml ```yaml {} applications: myapp: type: nodejs:16 source: root: folder1 ... ``` .upsun/app-bis.yaml ```yaml {} applications: myapp: type: nodejs:20 build: flavor: none ... ``` Once Upsun has combined the two configuration files, the blended configuration will be the following: YAML config result ```yaml {} applications: myapp: type: nodejs:20 build: flavor: none ... ``` Note that ``source.root`` (and any other ``.upsun/app.yaml`` parameters) will not be included in the final configuration. --- # Source: https://docs.upsun.com/learn/overview/yaml.md # YAML [YAML](https://en.wikipedia.org/wiki/YAML) is a human-readable format for data serialization across languages. This means it's a good fit for human-edited configuration files, like those at Upsun. You can control nearly all aspects of your project's build and deploy pipeline with YAML files. Learn what YAML is or, if you're already familiar, what custom tags Upsun offers.