# ReadyMage

Magento 2 managed auto-scalable infrastructure hosting service.

## Supported Frontend Theme Options (Choose After Sign-Up)

### 🚀 Hyvä

Hyvä is a modern, high-performance frontend for Magento 2, built on Tailwind CSS and Alpine.js. It offers a **lightweight, fast, and developer-friendly** experience, significantly improving performance scores, developer productivity, and time to market.

* Reduced complexity and fast development cycles
* Great Lighthouse scores out-of-the-box
* Best choice for performance-focused Magento stores

Learn more about Hyvä: <https://hyva.io>

### 🧱 Luma (Magento Default Theme)

Luma is Magento's default theme and is fully supported for projects that prefer the classic experience or require compatibility with legacy customizations.

### 🧩 ScandiPWA (PWA Frontend)

ScandiPWA is a React-based PWA frontend for Magento 2. It's up to **3x faster** than traditional Magento storefronts and supports **server-side rendering (SSR)** for better SEO and social previews.

* Fully compatible with most Magento 2 features
* Improved conversions and SEO performance
* Built-in SSR with RendyJS for better indexing

Check the full feature list in the ScandiPWA User Manual:\
👉 <https://manual.scandipwa.com/>

## Magento 2 backend <a href="#magento-2-backend" id="magento-2-backend"></a>

All storefronts run on a **fully managed Magento 2 backend**. If you're migrating from another platform, our system includes **Cart2Cart integration** to simplify data migration.

More info on Magento 2: <https://magento.com>

## CI/CD tools and local environment built for ScandiPWA and Magento <a href="#ci-cd-tools-and-local-environment-built-for-scandipwa-and-magento" id="ci-cd-tools-and-local-environment-built-for-scandipwa-and-magento"></a>

Your cloud instance includes a **GitHub repository with 1-Click CI/CD pipelines** tailored for Magento and your selected frontend.

* Zero-downtime deploys
* Local development setup with Webpack Dev Server for SPWA, and Docker support for all themes
* Support for Development, Staging, and Pre-Live environments

## SSR and SEO Optimization (ScandiPWA Only)

ScandiPWA supports **RendyJS** for SSR, enabling search engines and social platforms to properly index and preview your PWA content.

## CDN, WebP image optimization, and DDoS protection by Cloudflare <a href="#cdn-and-ddos-protection-by-cloudflare" id="cdn-and-ddos-protection-by-cloudflare"></a>

* **CDN & Image Optimization**: WebP compression and CDN acceleration
* **DDoS Protection**: Powered by Cloudflare
* **Monitoring & Logs**: Visualized via Prometheus and Kibana
* **Database Management**: Accessible via secure SSH

## Managed Cloud Hosting optimized for PWA and Magento <a href="#managed-cloud-hosting-optimized-for-pwa-and-magento" id="managed-cloud-hosting-optimized-for-pwa-and-magento"></a>

Our cloud infrastructure is optimized for Magento 2 and all supported frontends:

* Built with **Kubernetes** for scalability and high availability
* Auto-scaling PHP, MySQL, Redis, Varnish, and ElasticSearch
* **Only pay for what you use** – smart autoscaling with resource limits
* Full access to performance metrics and logs

<figure><img src="/files/wCdbUCgec6FRl9cLGX88" alt=""><figcaption></figcaption></figure>


# User Portal Access

User Portal is ReadyMage environment management portal

Access to the [User Portal](https://portal.readymage.com/instances) is available once you have received an invitation to the project

You will receive a link to your email. Use it to set your password. Then log in to the [User Portal](https://portal.readymage.com/).

<figure><img src="/files/7XxynwaWEd6qFrstTRR8" alt=""><figcaption></figcaption></figure>


# Change Password

### Change the password for your ReadyMage account

<figure><img src="/files/1R5ynydHFc26WU7QBbQa" alt=""><figcaption></figcaption></figure>

1. Access the User Portal following these[ instructions](/user-portal/user-portal-access).
2. Click on the **Account** section in the header&#x20;
3. Open the **Security** tab in the side navigation
4. Fill in your current password, new password, and confirm new password fields.
5. Click on the **Change Password** button
6. "**Password changed successfully**" will be displayed


# Two-Factor Authentication

For each ReadyMage account, it is required to set up Two-Factor Authentication using the Authenticator app.

Two-Factor Authentication increases the security of your account by requesting to enter a code from your phone. Use the Authenticator app to get free verification codes, even when your phone is offline. Available for Android and iPhone.

### Set up Two-Facto Authentication

<figure><img src="/files/EnQXhh2bIPQXLgnii1VF" alt=""><figcaption></figcaption></figure>

1. Get the Authenticator App from the [Play Store](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2) or the [App Store](https://apps.apple.com/us/app/google-authenticator/id388497605).
2. Access the User Portal following these[ instructions](/user-portal/user-portal-access).
3. Upon your first login, you will automatically be prompted to **Set Up Two-Factor Authentication**.
4. Open your authenticator app and scan the QR code displayed on the screen.
5. Enter the 6-digit verification code generated by the authenticator app.
6. Click **Verify & Complete Setup**.
7. Once the setup is successful, a **"Two-factor authentication enabled"** confirmation message will be displayed.

<figure><img src="/files/cMqsok8nY6RV8duH8t4b" alt=""><figcaption></figcaption></figure>

8. Click **Go to Portal** to continue.


# Project List

The project list is presented as the home page for the User Portal. For each project on this page you will see:

* Your role in the project.
* How many environments project has.
* See and go to all storefronts in the project.

<figure><img src="/files/pRsTumpk6eYkybU6Zzlx" alt=""><figcaption></figcaption></figure>


# Project Settings

To access the **Project Settings** page, click the **Project Settings** icon in the project navigation.

<figure><img src="/files/uUsVCF8o1yuumV86Xf6m" alt=""><figcaption></figcaption></figure>

The Project Settings page is accessible to all the user roles, however, only the Owner and the Admins of the project can change its settings. It includes the following sections:

* [Project Details](/project-management/project-settings/project-details)
* [Instances](/project-management/project-settings/instances)
* [Members](/project-management/project-settings/members-and-roles)
* [Security](/project-management/project-settings/security)
* [Delete Project](/project-management/project-settings/delete-project)


# Project Details

The General Info tab will display the following data:

* **Project Name** - Human-readable project name. The Owner or Admin of the project can change it.
* **Project Id** - Project identifier in Portal database.

<figure><img src="/files/uOLTLmZzY20hJxvxzGMc" alt=""><figcaption></figcaption></figure>


# Git Management

The environment source code is hosted on GitHub. Here you can grant and remove access to the repo.

<figure><img src="/files/L31cYT2OxfIclBm8fO7N" alt=""><figcaption></figcaption></figure>

## Add Git User

Before you can access your GitHub repository you must add a GitHub user.

Owner, Admin and Developer member roles can add git users.

1. Click **+ Add User**.&#x20;

<figure><img src="/files/t03Nd5HqMsO0SCw7fVOI" alt="" width="563"><figcaption></figcaption></figure>

2. Enter the GitHub username.
3. Select the appropriate permission level.
4. Click **Add User**.&#x20;

<figure><img src="/files/l2wUhmRthjZU9uKASWei" alt=""><figcaption></figcaption></figure>

Note the git user permissions:

* **Read** can pull source code from repository
* **Write** can pull and push changes to repository
* **Triage** can pull source code from repository and manage pull requests and issues

[Learn more here](https://docs.github.com/en/organizations/managing-user-access-to-your-organizations-repositories/managing-repository-roles/repository-roles-for-an-organization#permissions-for-each-role).

## Change Git User permission

Owner, Admin and Developer member roles can change git user permission.

1. Click the permission dropdown

<figure><img src="/files/yoogRLtnVxDO66g2p7Hb" alt=""><figcaption></figcaption></figure>

2. Select the desired permission level.

<figure><img src="/files/mtDkEHZMQl56aGaFkm4i" alt=""><figcaption></figcaption></figure>

3. The permission is updated automatically upon selection.

## Delete User

Should you wish to remove users from your repository you can use the **Delete** button next to each of the usernames, to delete a specific user.

<figure><img src="/files/nlJyh24sOxlLTLuuTQOA" alt=""><figcaption></figcaption></figure>


# Instances

Access the **Instances** page under the **Project -> Settings.**

The **New Instance** button will open the instance page creation. Only accessible for Admins and the Owner of the project.

List of environments with actions:

* Delete an instance - this action might be disabled if it is the main instance or the instance is set as a *Live Instance*.
* Change instance branch - this action allows changing which branch is used for instance deployments. Note it it must be identical to the branch name on GitHub.
* Copy namespace
* Badges:
  * The branch badge contains information about the branch that the instance is linked to. It is also a link to that branch on GitHub.
  * The region badge identifies which region the instance belongs to.
  * The main instance badge indicates the main instance in the project.
  * A discoverable badge indicates if the instance can be discovered by Search Engine Bots. [Learn more here](/application-management/search-engine-bots-discovery).

<figure><img src="/files/NZvS43rng3d54jarpAYa" alt=""><figcaption></figcaption></figure>


# New instance

On the **New Instance** page, the Admins and the Owner of the project can create a new instance.

## 1. Step - Select Project

Choose one of the following options:

* **Existing Project** – Select a project that you are a member of to create an additional environment (instance) within that project.
* **New Project** – Create a new project and provision the first instance for it.
* **New Project for Another User** – Create a new project and assign ownership to another user by specifying their **Owner Email**. The specified user will become the project owner.

<figure><img src="/files/64hBE7Nyl2OI3xk2OQaO" alt=""><figcaption></figcaption></figure>

## 2. Step - Select instance template

{% hint style="warning" %}
Only applicable for the creation of the first instance.
{% endhint %}

<figure><img src="/files/VBLDYTvaZLbLqcWU0803" alt=""><figcaption></figcaption></figure>

You can select one of four templates available:

* **Magento Luma** - Latest Magento with Luma theme.
* **Hyva** - Latest Magento with Hyva theme.

  * To create an instance with Hyva Template, you will need to provide the **Hyva License Key** and the **Hyva Composer Repository in** [**Step 3**](#id-3.-step-configure-your-new-instance-settings)**.**

  <figure><img src="/files/4uuL2CLBK8PCv1hr5fJ6" alt=""><figcaption></figcaption></figure>
* **ScandiPWA** - Magento 2.4.7 with ScandiPWA 6.4.0.
* **No-code** - blank instance.

## 3. Step - Configure your new instance settings.

<figure><img src="/files/ePbFwQywqDEEcmFomZRT" alt=""><figcaption></figcaption></figure>

* **Instance Name** - A human-readable name for this instance.
* **Instance Tag** - You can use suggested prefixes or enter your own: `uat`, `stage-1`, `test-2` and e.t.c.
* **Magento Mode** - allows to set up Magento in `production` , `default` or `developer` mode. Refer to the [official Magento documentation](https://experienceleague.adobe.com/docs/commerce-operations/configuration-guide/setup/application-modes.html) to learn more.
* **Region** - a region your instance will be hosted in. Currently, available regions are:
  * Europe Ireland
  * Europe Stockholm
  * USA Ohio
  * Middle East UAE
  * Canada Central
  * Asia Pacific Sydney
* **Hyvä Credentials** *(Optional)* – This section is displayed only when the **Hyvä** template is selected. Enter the **Repository URL** and **License Key** to enable access to the Hyvä packages.

{% hint style="success" %}
We will verify if the provided **License Key** and **Composer Repository** are valid before proceeding.
{% endhint %}

## 4. Step - Create Instance

This is the final step before the environment is created. Ensure all provided details are correct, then click **Create Instance** to start the environment creation process.

<figure><img src="/files/DOkvebkiKNMMGX2HfkBB" alt=""><figcaption></figcaption></figure>

The instance creation process runs in the background, so you don't need to stay on this page. You can return at any time to monitor its progress.

<figure><img src="/files/mChBpiolQEIN1pgEv4eA" alt=""><figcaption></figcaption></figure>


# Members and roles

There are a few different user roles defined:

* **Owner** - has full control over the project.
* **Admin** - has full control over the project, but cannot create new Admins in the project.
* **Developer** - has access to all actions related to instances, but can't change project settings.
* **Guest** - has access to environments in the project but cannot invoke any actions.

<figure><img src="/files/SLQTg4tOE2HJjOooIIHo" alt=""><figcaption></figcaption></figure>

### Owner

The Owner of the project has access to the following actions:

* Can invite new members by email with one of the following permissions: Admin, Developer, or Guest.
* Can edit members' permissions.
* Can remove members from the project.

### Admin

The Admin role has full access to all actions in the portal related to the project, as well as:

* Can invite new members by email with one of the following permissions: Developer or Guest.
* Can edit members' permissions.
* Can remove members from the project.

New Admins can be invited only by the Owner of the project.

### Developer

The key difference in the Developer role compared to the Admin or Owner roles is that Developer cannot change the project settings, nor invite new members, however, is still able to manage all the environment-related information.

New Developers can be invited by the Owner or Admin of the project.

### Guest

A Guest user has access to environments in the project but cannot invoke any actions. A Guest user does not have access to environment-sensitive information, like usernames and passwords.

New Guests can be invited by the Owner or Admin of the project.


# Security

On the Security page Admin of the project has access to the following actions:

* Manage [Deletion Protection](/project-management/project-settings/security/deletion-protection).
* Manage [TFA Enforcement](/project-management/project-settings/security/tfa-enforcement).

<figure><img src="/files/WGk7mi96GOp131RPVTZH" alt=""><figcaption></figcaption></figure>


# Deletion Protection

Deletion Protection ensures that the project cannot be deleted from project settings, only through ReadyMage support.

When Deletion Protection is enabled, the [Delete Project](/project-management/project-settings/delete-project) button will be disabled but you will be able to request the deletion from the ReadyMage team.

<figure><img src="/files/2JtmJVen3BHQL2fEvEEg" alt=""><figcaption></figcaption></figure>


# TFA Enforcement

On the TFA Enforcement page, the Owner or Admin of the project can enable TFA Enforcement. This will ensure that only users with enabled Two-Factor Authentication will be able to access the project environments.

<figure><img src="/files/8XR9LsqbmZYea0pyldMl" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Before enabling the TFA Enforcement Owner or Admin of the project must set up Two-Factor Authentication in the account settings. Setup details can be found [here](/user-portal/two-factor-authentication).
{% endhint %}


# Delete Project

On the Delete Project page, the Admins and the Owner of the project are able to delete it.

{% hint style="info" %}
Deleting the project will **permanently delete all data** stored in the project plugins for all environments. This can't be undone.
{% endhint %}

<figure><img src="/files/WvRBwg9uJaJ1kP8On9MV" alt=""><figcaption></figcaption></figure>


# Magento Details

The **Magento Details** section can be found in **User Portal → Project → Selected Instance →  Overview.**

Here you will find your instance IP address, storefront and admin URLs, as well as the username and password to access the Magento admin.

{% hint style="warning" %}
Note that you must have permission access of an Admin or Developer to access Magento admin credentials.
{% endhint %}

<figure><img src="/files/nremKA0D4D5AZijqTvFy" alt=""><figcaption></figcaption></figure>

## IP Address

We have multiple clusters across regions of the world. Here is the list of their public IP addresses:

| Region           | IP Address    |
| ---------------- | ------------- |
| Europe Ireland   | 63.34.64.58   |
| Europe Stockhol  | 13.50.146.65  |
| USA Ohio         | 3.18.192.113  |
| Canada Central   | 35.182.89.153 |
| Middle East UAE  | 40.172.65.195 |
| Australia Sydney | 52.65.157.100 |

You can view the instance IP address by clicking on the **Region** name in the **Overview → Details** page.&#x20;

<figure><img src="/files/pyzS7NQ9La3FS6nKMEnj" alt=""><figcaption></figcaption></figure>


# Domain Management

If you'd like to change your domain, navigate to the **User Portal → Project → Selected Instance →  Configuration → Domains → Request Domain Change**.

{% hint style="info" %}
Domain change requires ReadyMage team assistance. Please request a domain change one week in advance.
{% endhint %}

<figure><img src="/files/8Y44JiqpzmMuAXeWZuPu" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/Aeq3G8XbtTO4PYWiUreB" alt=""><figcaption></figcaption></figure>


# Variables Management

On this page, you can add/edit/remove environment variables that are used by your application.

<figure><img src="/files/dErnNvmzCKxrWSk4tV05" alt=""><figcaption></figcaption></figure>

### Add Environment Variable

1. Click **Add Variable**

<figure><img src="/files/Yh0pja4iEUWbVNqb43bX" alt=""><figcaption></figcaption></figure>

2. Enter variable name (1), variable value (2) and click **Save** (3).

<figure><img src="/files/IRkaFI2cNSpfnN6vM4yo" alt=""><figcaption></figcaption></figure>

After the environment variable is added, redeployment will be required for changes to be applied.

<figure><img src="/files/praN6uz6mapAKQKe8k64" alt=""><figcaption></figcaption></figure>

### Edit Environment Variable

Click on "**Pencil" icon** to open the environment variable edit modal.

<figure><img src="/files/VA3LcggwgsVP2yRpWR1q" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/2ASuIODwu886J6m8egsd" alt=""><figcaption></figcaption></figure>

When finished editing the value, click **Save**.

<figure><img src="/files/IQBNKvPsFdJpF5LrTbOY" alt=""><figcaption></figcaption></figure>

After the environment variable is added, redeployment will be required for changes to be applied.

### Remove Environment Variable

Click on **Trash Icon**(1) near the variable you want to remove then click on **Delete** button (2).

<figure><img src="/files/GCvPffHz81HJzeSCirap" alt=""><figcaption></figcaption></figure>

In the opened modal, confirm that you want to delete a variable by clicking the **Yes, Delete** button.

<figure><img src="/files/uV6Nks3n14jI3U4odp5s" alt=""><figcaption></figcaption></figure>

If the variable is new and has not been deployed yet, it will be removed **immediately**.

If the variable was already deployed, you will see in **See Changes** that it will be removed **after** deployment.

<figure><img src="/files/X8jljghZ75TjLIzAlF4V" alt=""><figcaption></figcaption></figure>

## Raw Editor

<div><figure><img src="/files/0C5Eer4ESkYEPS0ai1Xc" alt=""><figcaption><p>Open <strong>Raw Editor modal</strong></p></figcaption></figure> <figure><img src="/files/p8gUs1XueesQX1UjRdPF" alt=""><figcaption><p>Raw Editor ENV view</p></figcaption></figure></div>

Inside the Raw Editor modal, you can copy all environment variables, add/edit/delete them in bulk. And view them in JSON.

<figure><img src="/files/wIkoKO5waCi0QahjuX1L" alt=""><figcaption></figcaption></figure>

## Hyva Credentials

The Variables Management page also includes **Hyva Credentials** modal.

<figure><img src="/files/7U8XlpqvtvhxJyAr8DZx" alt=""><figcaption></figcaption></figure>

Here you can enter the **Hyva License Key** and the **Hyva Composer Repository** directly. Portal will also perform a check to see if the provided license key has access to the Hyva theme.

<figure><img src="/files/ZcNkThfPDItZkJ3ZFsXt" alt=""><figcaption></figcaption></figure>

## Packagist

To install packages from Packagist, you need to provide **Composer Credentials** environment variable or have `auth.json` file in the repository. It is generally **recommended against** committing `auth.json` into the source code.

Instead, use `COMPOSER_AUTH` environment variable.

<div><figure><img src="/files/vnkvO2vSwxzlM3x5Qyf8" alt="Access Composer Auth modal"><figcaption><p>Access <strong>Composer Auth</strong> Modal</p></figcaption></figure> <figure><img src="/files/s6ZOK6o8c8zKzAohLXvY" alt="Composer Auth modal"><figcaption><p>Composer Auth modal</p></figcaption></figure></div>


# Logs & Monitoring

ReadyMage solution uses ELK Stack for log gathering and Kibana for log visualization. Both tools are automatically set up together with your instance.

### Access

Access information to the Kibana tool is available in the [User Portal](https://portal.readymage.com/).&#x20;

To access Kibana logs navigate to the **User Portal → Project → Selected Instance → Overview → Logs**.

<figure><img src="/files/SyNVdWkbvq82qzZVO4Ig" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Note that you must have permission access of an Owner, Admin, or Developer to see this page.
{% endhint %}

### Discover Page

Inside Kibana use the Discover page to view logs. There you will be able to select a specific time period and filter logs based on custom or saved filters.

{% hint style="info" %}
Please note that logs are kept for two weeks only.
{% endhint %}

![](/files/-MP4Ub5wsZx3t4ipirBC)

### Saved log filters

Kibana logs come with pre-configured filters for the most searched logs - app-updater, build, cron, exception, and system.

{% hint style="info" %}
App-updater logs show the logs of the deployment which occurs after the build.
{% endhint %}

<div align="left"><img src="/files/8UQa9OP90Lkhth8a337j" alt=""></div>

Learn more about Kibana from the [official guide](https://www.elastic.co/guide/en/kibana/7.6/index.html).


# Backups

ReadyMage creates backups for your database and media. Backups are available for download in the [User Portal](https://portal.readymage.com/).

{% hint style="warning" %}
Media backups for instances are performed every Monday at 04:00 UTC and stored securely for 2 weeks.

If you need to restore data from a backup, please get in touch with us at <admin@readymage.com> and include your instance name in the request.
{% endhint %}

### Downloading a backup

Access your backups by navigating to the **User Portal → Project → Selected Instance → Application Management  → Backups**.&#x20;

Within the backups tab, you can choose what database or media backup you wish to download.

<figure><img src="/files/2mGU0niEYxT8L7sRsHW4" alt=""><figcaption></figcaption></figure>

### Frequency, timing, and availability

All of the backups are set by default. Below you can see the time frame for each type of backup and for how long they will be available.

For example, a MySQL daily backup for July 1st will be automatically deleted after July 5th.

#### MySQL Database

| Frequency | Timing                                  | Availability |
| --------- | --------------------------------------- | ------------ |
| Daily     | 00:00 UTC                               | 4 days       |
| Weekly    | Sunday to Monday 00:00 UTC              | 14 days      |
| Monthly   | On the first day of the month 00:00 UTC | 93 days      |

#### Media

| Weekly | Monday 04:00 UTC | 14 days |
| ------ | ---------------- | ------- |

Media backup is made with `dar` utility ver. `2.7.3`. To unarchive a backup, you need the utility not lower than this version. \
\
If the standard software repositories of your operating system don't contain such a version you can download the binary from [here](https://dar.edrusb.org/dar.linux.free.fr/Releases/Dar_static/x86_64_GNU_Linux/dar_static_2.7.6_x86_64_GNU_Linux) for Linux and [here](https://dar.edrusb.org/dar.linux.free.fr/Releases/Windows64bits/dar64-2.7.6-win64.zip) for Windows.

Here is an example of a media backup unarchiving for Linux:

```
mkdir media-weekly
dar -x readymage-instance-media-weekly-20220101.1.dar -R media-weekly

ls media-weekly
config  media
```


# Backup process

#### AWS S3 Bucket (Build artifact / code base)

In Readymage, our workflow involves generating build artifacts, which encompass all user code, and subsequently transmitting these artifacts to an AWS S3 bucket as part of the successful code-build step, constituting the deployment phase.

AWS S3 is designed to provide high availability by replicating data across multiple Availability Zones (AZs) within a region. An Availability Zone is essentially a separate data center with its own power, cooling, and networking. This means that even if one data center within a region experiences issues, your data should still be accessible from other AZs within the same region.

#### Harbor (**Docker Images**)

Harbor is an open-source container image registry that allows to store, manage, and distribute Docker images. It provides a private and secure registry for container images, enhancing control over containerized applications. While Harbor is primarily used for managing container images, it plays a role in aspects related to disaster recovery.

**Image Storage and Distribution:** Harbor serves as a centralized repository for storing Docker images. In the context of disaster recovery, having container images stored in Harbor ensures that we have a reliable and accessible source for deploying applications, even in the event of a disaster affecting other parts of infrastructure.

<figure><img src="/files/NJ7JVNDJTImW4YTR5QKU" alt=""><figcaption></figcaption></figure>


# Disaster recovery process

Restoring an instance is a crucial undertaking that demands meticulous planning, thorough documentation, and effective communication.

It's important to acknowledge that not all incidents can be resolved by strictly adhering to predefined guides, as their nature may vary across instances.

Consequently, this guide serves as a brief overview of general steps, recognizing the need for adaptability and thoughtful consideration in addressing unique challenges that may arise during the recovery process.

1. **Assessment and Identification:**
   * Identify the nature and extent of the issue.
   * Assess the impact on users, data, and operations.
2. **Communication**
   * Reach out to <admin@readymage.com> for an assistance describing issue.
3. **Understanding scope of required recovery**
   * Identification of critical systems, prioritization of restoration steps, and roles and responsibilities for team members during a recovery scenario.
4. **Backup Verification:**
   * Verify the availability and integrity of recent backups.
   * Confirm that backups include necessary data, configurations, and settings.
5. **Recovery Plan Activation:**
   * Refer to the instance recovery plan and follow the documented steps.
   * Prioritize recovery tasks based on criticality.
6. **Data Restoration:**
   * Restore data from the most recent backup.
7. **Configuration and Settings:**
   * Reconfigure settings and configurations based on the documented standards.
   * Validate that security configurations are in place.
8. **Testing**
   * Conduct functional and performance tests to ensure the instance operates as expected.
   * Verify data integrity and consistency.


# Deployments

An instance deployment is automatically initiated when a code merge is made to its branch. The deployment utilizes a zero-downtime deployment pipeline specifically made for ScandiPWA and Magento 2.

You can also deploy changes made to your GitHub repository manually with a single click in the [User Portal](https://portal.readymage.com/): navigate to the **User Portal → Project → Selected Instance → Overview → Deployments** and click the *Start Deployment* button.

<figure><img src="/files/hunrLPxGYWtx2x6nLiaY" alt=""><figcaption></figcaption></figure>

You can switch on or off automatic deployments by toggling the "**Auto-Deploy on Push**" switcher. Deployments will happen automatically on the code commit to the repository branch connected to the instance.

* Navigate to **Overview → Deployments → Settings** to open the deployment settings.

<figure><img src="/files/Zj2qbhuttIempRH6MBP2" alt=""><figcaption></figcaption></figure>

* Toggle the **Auto-Deploy on Push** option to enable or disable automatic deployments.
* Optionally, enable **Email Notifications** to receive updates whenever the deployment status changes.&#x20;

<figure><img src="/files/tIfnWbkzs6wJ7ceuVpeE" alt=""><figcaption></figcaption></figure>

You can view the deployment history in the Deployments tab, with the information of date, type, and status.

<figure><img src="/files/6co4HnCbTjnJOxVTdOV0" alt=""><figcaption></figcaption></figure>

Deployment success and failure logs are available in the Logs Management tool - Kibana. To access Kibana follow the instructions in[ Log Management using Kibana](/application-management/log-management-using-kibana).


# Pipeline Deployments

ReadyMage solution comes with out-of-the-box pipeline deployment support. You can redeploy your instance with 1-click and the changes are deployed with zero downtime.

Zero downtime deployment is archived by a specifically designed pipeline deployment flow for Magento 2 and ScandiPWA development. Since the ReadyMage infrastructure is based on Kubernetes technology it allows creating a parallel servers during the deployment. When the deployment is processed successfully the switch to the new server is done and the previous one is removed, therefore, archiving zero downtime.

ReadyMage pipeline deployment are split in two distinctive phases.

## Build Phase

Build phase has two objectives:

1. Prepare code by installing dependencies and compiling it.
2. Packing up the code as artifact for the [deployment phase](#deployment-phase).

### Requirements

There is a single requirement for all the code bases that wish to be built by ReadyMage pipeline:

* `app/etc/config.php` file with the module list and with all available [`scopes`](https://devdocs.magento.com/guides/v2.4/config-guide/prod/config-reference-configphp.html#scopes)

<details>

<summary>Example</summary>

{% code title="config.php" %}

```php
<?php
return [
    'modules' => [
        'Magento_AdminAnalytics' => 1,
        'Magento_Store' => 1,
        'Magento_AdobeIms' => 1,
        'Magento_AdobeImsApi' => 1,
        'Magento_AdobeStockAdminUi' => 1,
        'Magento_MediaGallery' => 1,
        'Magento_AdobeStockAssetApi' => 1,
        'Magento_AdobeStockClient' => 1,
        'Magento_AdobeStockClientApi' => 1,
        'Magento_AdobeStockImage' => 1,
        'Magento_Directory' => 1,
        'Magento_AdobeStockImageApi' => 1,
        'Magento_AdvancedPricingImportExport' => 1,
        'Magento_Theme' => 1,
        'Magento_Amqp' => 1,
        'Magento_AmqpStore' => 1,
        'Magento_Config' => 1,
        'Magento_Backend' => 1,
        'Magento_Authorization' => 1,
        'Magento_Eav' => 1,
        'Magento_Variable' => 1,
        'Magento_Search' => 1,
        'Magento_Backup' => 1,
        'Magento_Customer' => 1,
        'Magento_AdminNotification' => 1,
        'Magento_BundleImportExport' => 1,
        'Magento_CacheInvalidate' => 1,
        'Magento_Indexer' => 1,
        'Magento_Cms' => 1,
        'Magento_Rule' => 1,
        'Magento_Security' => 1,
        'Magento_GraphQl' => 1,
        'Magento_EavGraphQl' => 1,
        'Magento_StoreGraphQl' => 1,
        'Magento_CatalogImportExport' => 1,
        'Magento_Catalog' => 1,
        'Magento_CatalogInventory' => 1,
        'Magento_CatalogPageBuilderAnalytics' => 1,
        'Magento_CatalogRule' => 1,
        'Magento_Msrp' => 1,
        'Magento_CatalogRuleGraphQl' => 1,
        'Magento_CatalogSearch' => 1,
        'Magento_CatalogUrlRewrite' => 1,
        'Magento_CatalogGraphQl' => 1,
        'Magento_MediaStorage' => 1,
        'Magento_Quote' => 1,
        'Magento_SalesSequence' => 1,
        'Magento_CheckoutAgreementsGraphQl' => 1,
        'Magento_MediaGalleryUi' => 1,
        'Magento_CmsGraphQl' => 1,
        'Magento_CmsPageBuilderAnalytics' => 1,
        'Magento_CmsUrlRewrite' => 1,
        'Magento_CmsUrlRewriteGraphQl' => 1,
        'Magento_CompareListGraphQl' => 1,
        'Magento_ComposerRootUpdatePlugin' => 1,
        'Magento_User' => 1,
        'Magento_Payment' => 1,
        'Magento_Sales' => 1,
        'Magento_QuoteGraphQl' => 1,
        'Magento_Checkout' => 1,
        'Magento_Contact' => 1,
        'Magento_Cookie' => 1,
        'Magento_Cron' => 1,
        'Magento_Csp' => 1,
        'Magento_Widget' => 1,
        'Magento_Robots' => 1,
        'Magento_Integration' => 1,
        'Magento_Downloadable' => 1,
        'Magento_CustomerGraphQl' => 1,
        'Magento_CustomerImportExport' => 1,
        'Magento_Deploy' => 1,
        'Magento_Developer' => 1,
        'Magento_Dhl' => 1,
        'Magento_Bundle' => 1,
        'Magento_DirectoryGraphQl' => 1,
        'Magento_DownloadableGraphQl' => 1,
        'Magento_CustomerDownloadableGraphQl' => 1,
        'Magento_ImportExport' => 1,
        'Magento_CatalogCustomerGraphQl' => 1,
        'Magento_BundleGraphQl' => 1,
        'Magento_AdvancedSearch' => 1,
        'Magento_Elasticsearch' => 1,
        'Magento_Elasticsearch6' => 1,
        'Magento_Email' => 1,
        'Magento_EncryptionKey' => 1,
        'Magento_Fedex' => 1,
        'Magento_GiftMessage' => 1,
        'Magento_GiftMessageGraphQl' => 1,
        'Magento_GoogleAdwords' => 1,
        'Magento_GoogleAnalytics' => 1,
        'Magento_Ui' => 1,
        'Magento_GoogleShoppingAds' => 1,
        'Magento_CatalogCmsGraphQl' => 1,
        'Magento_PageCache' => 1,
        'Magento_GroupedProduct' => 1,
        'Magento_GroupedImportExport' => 1,
        'Magento_GroupedCatalogInventory' => 1,
        'Magento_GroupedProductGraphQl' => 1,
        'Magento_DownloadableImportExport' => 1,
        'Magento_Captcha' => 1,
        'Magento_InstantPurchase' => 1,
        'Magento_Analytics' => 1,
        'Magento_Inventory' => 1,
        'Magento_InventoryAdminUi' => 1,
        'Magento_InventoryAdvancedCheckout' => 1,
        'Magento_InventoryApi' => 1,
        'Magento_InventoryBundleImportExport' => 1,
        'Magento_InventoryBundleProduct' => 1,
        'Magento_InventoryBundleProductAdminUi' => 1,
        'Magento_InventoryBundleProductIndexer' => 1,
        'Magento_InventoryCatalog' => 1,
        'Magento_InventorySales' => 1,
        'Magento_InventoryCatalogAdminUi' => 1,
        'Magento_InventoryCatalogApi' => 1,
        'Magento_InventoryCatalogFrontendUi' => 1,
        'Magento_InventoryCatalogSearch' => 1,
        'Magento_InventoryCatalogSearchBundleProduct' => 1,
        'Magento_InventoryCatalogSearchConfigurableProduct' => 1,
        'Magento_ConfigurableProduct' => 1,
        'Magento_ConfigurableProductGraphQl' => 1,
        'Magento_InventoryConfigurableProduct' => 1,
        'Magento_InventoryConfigurableProductIndexer' => 1,
        'Magento_InventoryConfiguration' => 1,
        'Magento_InventoryConfigurationApi' => 1,
        'Magento_InventoryDistanceBasedSourceSelection' => 1,
        'Magento_InventoryDistanceBasedSourceSelectionAdminUi' => 1,
        'Magento_InventoryDistanceBasedSourceSelectionApi' => 1,
        'Magento_InventoryElasticsearch' => 1,
        'Magento_InventoryExportStockApi' => 1,
        'Magento_InventoryIndexer' => 1,
        'Magento_InventorySalesApi' => 1,
        'Magento_InventoryGroupedProduct' => 1,
        'Magento_InventoryGroupedProductAdminUi' => 1,
        'Magento_InventoryGroupedProductIndexer' => 1,
        'Magento_InventoryImportExport' => 1,
        'Magento_InventoryInStorePickupApi' => 1,
        'Magento_InventoryInStorePickupAdminUi' => 1,
        'Magento_InventorySourceSelectionApi' => 1,
        'Magento_InventoryInStorePickup' => 1,
        'Magento_InventoryInStorePickupGraphQl' => 1,
        'Magento_Shipping' => 1,
        'Magento_InventoryInStorePickupShippingApi' => 1,
        'Magento_InventoryInStorePickupQuoteGraphQl' => 1,
        'Magento_InventoryInStorePickupSales' => 1,
        'Magento_InventoryInStorePickupSalesApi' => 1,
        'Magento_InventoryInStorePickupQuote' => 1,
        'Magento_InventoryInStorePickupShipping' => 1,
        'Magento_InventoryInStorePickupShippingAdminUi' => 1,
        'Magento_Multishipping' => 1,
        'Magento_Webapi' => 1,
        'Magento_InventoryCache' => 1,
        'Magento_InventoryLowQuantityNotification' => 1,
        'Magento_Reports' => 1,
        'Magento_InventoryLowQuantityNotificationApi' => 1,
        'Magento_InventoryMultiDimensionalIndexerApi' => 1,
        'Magento_InventoryProductAlert' => 1,
        'Magento_InventoryQuoteGraphQl' => 1,
        'Magento_InventoryRequisitionList' => 1,
        'Magento_InventoryReservations' => 1,
        'Magento_InventoryReservationCli' => 1,
        'Magento_InventoryReservationsApi' => 1,
        'Magento_InventoryExportStock' => 1,
        'Magento_InventorySalesAdminUi' => 1,
        'Magento_CatalogInventoryGraphQl' => 1,
        'Magento_InventorySalesFrontendUi' => 1,
        'Magento_InventorySetupFixtureGenerator' => 1,
        'Magento_InventoryShipping' => 1,
        'Magento_InventoryShippingAdminUi' => 1,
        'Magento_InventorySourceDeductionApi' => 1,
        'Magento_InventorySourceSelection' => 1,
        'Magento_InventoryInStorePickupFrontend' => 1,
        'Magento_InventorySwatchesFrontendUi' => 1,
        'Magento_InventoryVisualMerchandiser' => 1,
        'Magento_InventoryWishlist' => 1,
        'Magento_JwtFrameworkAdapter' => 1,
        'Magento_LayeredNavigation' => 1,
        'Magento_LoginAsCustomer' => 1,
        'Magento_LoginAsCustomerAdminUi' => 1,
        'Magento_LoginAsCustomerApi' => 1,
        'Magento_LoginAsCustomerAssistance' => 1,
        'Magento_LoginAsCustomerFrontendUi' => 1,
        'Magento_LoginAsCustomerGraphQl' => 1,
        'Magento_LoginAsCustomerLog' => 1,
        'Magento_LoginAsCustomerPageCache' => 1,
        'Magento_LoginAsCustomerQuote' => 1,
        'Magento_LoginAsCustomerSales' => 1,
        'Magento_Marketplace' => 1,
        'Magento_MediaContent' => 1,
        'Magento_MediaContentApi' => 1,
        'Magento_MediaContentCatalog' => 1,
        'Magento_MediaContentCms' => 1,
        'Magento_MediaContentSynchronization' => 1,
        'Magento_MediaContentSynchronizationApi' => 1,
        'Magento_MediaContentSynchronizationCatalog' => 1,
        'Magento_MediaContentSynchronizationCms' => 1,
        'Magento_AdobeStockAsset' => 1,
        'Magento_MediaGalleryApi' => 1,
        'Magento_MediaGalleryCatalog' => 1,
        'Magento_MediaGalleryCatalogIntegration' => 1,
        'Magento_MediaGalleryCatalogUi' => 1,
        'Magento_MediaGalleryCmsUi' => 1,
        'Magento_MediaGalleryIntegration' => 1,
        'Magento_MediaGalleryMetadata' => 1,
        'Magento_MediaGalleryMetadataApi' => 1,
        'Magento_MediaGalleryRenditions' => 1,
        'Magento_MediaGalleryRenditionsApi' => 1,
        'Magento_MediaGallerySynchronization' => 1,
        'Magento_MediaGallerySynchronizationApi' => 1,
        'Magento_MediaGallerySynchronizationMetadata' => 1,
        'Magento_AdobeStockImageAdminUi' => 1,
        'Magento_MediaGalleryUiApi' => 1,
        'Magento_CatalogWidget' => 1,
        'Magento_MessageQueue' => 1,
        'Magento_ConfigurableImportExport' => 1,
        'Magento_MsrpConfigurableProduct' => 1,
        'Magento_MsrpGroupedProduct' => 1,
        'Magento_InventoryInStorePickupMultishipping' => 1,
        'Magento_MysqlMq' => 1,
        'Magento_NewRelicReporting' => 1,
        'Magento_Newsletter' => 1,
        'Magento_NewsletterGraphQl' => 1,
        'Magento_OfflinePayments' => 1,
        'Magento_SalesRule' => 1,
        'Magento_Sitemap' => 1,
        'Magento_PageBuilder' => 1,
        'Magento_PageBuilderAnalytics' => 1,
        'Magento_GraphQlCache' => 1,
        'Magento_CardinalCommerce' => 1,
        'Magento_Vault' => 1,
        'Magento_Paypal' => 1,
        'Magento_PaypalGraphQl' => 1,
        'Magento_Persistent' => 1,
        'Magento_ProductAlert' => 1,
        'Magento_ProductVideo' => 1,
        'Magento_CheckoutAgreements' => 1,
        'Magento_QuoteAnalytics' => 1,
        'Magento_QuoteBundleOptions' => 1,
        'Magento_QuoteConfigurableOptions' => 1,
        'Magento_QuoteDownloadableLinks' => 1,
        'Magento_InventoryConfigurableProductAdminUi' => 1,
        'Magento_ReCaptchaAdminUi' => 1,
        'Magento_ReCaptchaCheckout' => 1,
        'Magento_ReCaptchaContact' => 1,
        'Magento_ReCaptchaCustomer' => 1,
        'Magento_ReCaptchaFrontendUi' => 1,
        'Magento_ReCaptchaMigration' => 1,
        'Magento_ReCaptchaNewsletter' => 1,
        'Magento_ReCaptchaPaypal' => 1,
        'Magento_ReCaptchaReview' => 1,
        'Magento_ReCaptchaSendFriend' => 1,
        'Magento_ReCaptchaStorePickup' => 1,
        'Magento_ReCaptchaUi' => 1,
        'Magento_ReCaptchaUser' => 1,
        'Magento_ReCaptchaValidation' => 1,
        'Magento_ReCaptchaValidationApi' => 1,
        'Magento_ReCaptchaVersion2Checkbox' => 1,
        'Magento_ReCaptchaVersion2Invisible' => 1,
        'Magento_ReCaptchaVersion3Invisible' => 1,
        'Magento_ReCaptchaWebapiApi' => 1,
        'Magento_ReCaptchaWebapiGraphQl' => 1,
        'Magento_ReCaptchaWebapiRest' => 1,
        'Magento_ReCaptchaWebapiUi' => 1,
        'Magento_RelatedProductGraphQl' => 1,
        'Magento_ReleaseNotification' => 1,
        'Magento_RemoteStorage' => 1,
        'Magento_InventoryLowQuantityNotificationAdminUi' => 1,
        'Magento_RequireJs' => 1,
        'Magento_Review' => 1,
        'Magento_ReviewAnalytics' => 1,
        'Magento_ReviewGraphQl' => 1,
        'Magento_AwsS3' => 1,
        'Magento_Rss' => 1,
        'Magento_PageBuilderAdminAnalytics' => 1,
        'Magento_CatalogRuleConfigurable' => 1,
        'Magento_SalesAnalytics' => 1,
        'Magento_SalesGraphQl' => 1,
        'Magento_SalesInventory' => 1,
        'Magento_OfflineShipping' => 1,
        'Magento_ConfigurableProductSales' => 1,
        'Magento_UrlRewrite' => 1,
        'Magento_Elasticsearch7' => 1,
        'Magento_CustomerAnalytics' => 1,
        'Magento_Securitytxt' => 1,
        'Magento_SendFriend' => 1,
        'Magento_SendFriendGraphQl' => 1,
        'Magento_InventoryInStorePickupSalesAdminUi' => 1,
        'Magento_AwsS3PageBuilder' => 1,
        'Magento_InventoryGraphQl' => 1,
        'Magento_UrlRewriteGraphQl' => 1,
        'Magento_Swagger' => 1,
        'Magento_SwaggerWebapi' => 1,
        'Magento_SwaggerWebapiAsync' => 1,
        'Magento_Swatches' => 1,
        'Magento_SwatchesGraphQl' => 1,
        'Magento_SwatchesLayeredNavigation' => 1,
        'Magento_Tax' => 1,
        'Magento_TaxGraphQl' => 1,
        'Magento_TaxImportExport' => 1,
        'Magento_AsynchronousOperations' => 1,
        'Magento_ThemeGraphQl' => 1,
        'Magento_Translation' => 1,
        'Magento_TwoFactorAuth' => 0,
        'Magento_GoogleOptimizer' => 1,
        'Magento_Ups' => 1,
        'Magento_SampleData' => 1,
        'Magento_CatalogUrlRewriteGraphQl' => 1,
        'Magento_CatalogAnalytics' => 1,
        'Magento_Usps' => 1,
        'Magento_InventoryConfigurableProductFrontendUi' => 1,
        'Magento_PaypalCaptcha' => 1,
        'Magento_VaultGraphQl' => 1,
        'Magento_Version' => 1,
        'Magento_InventoryInStorePickupWebapiExtension' => 1,
        'Magento_WebapiAsync' => 1,
        'Magento_WebapiSecurity' => 1,
        'Magento_Weee' => 1,
        'Magento_WeeeGraphQl' => 1,
        'Magento_CurrencySymbol' => 1,
        'Magento_Wishlist' => 1,
        'Magento_WishlistAnalytics' => 1,
        'Magento_WishlistGraphQl' => 1,
        'Amazon_Core' => 1,
        'Amazon_Login' => 1,
        'Amazon_Payment' => 1,
        'Dotdigitalgroup_Email' => 1,
        'Dotdigitalgroup_Chat' => 1,
        'Dotdigitalgroup_ChatGraphQl' => 1,
        'Dotdigitalgroup_EmailGraphQl' => 1,
        'Dotdigitalgroup_Sms' => 1,
        'Klarna_Core' => 1,
        'Klarna_Ordermanagement' => 1,
        'Klarna_Kp' => 1,
        'Klarna_Onsitemessaging' => 1,
        'Klarna_KpGraphQl' => 1,
        'PayPal_Braintree' => 1,
        'PayPal_BraintreeGraphQl' => 1,
        'ReadyMage_Logger' => 1,
        'ReadyMage_Maintenance' => 1,
        'ScandiPWA_Cache' => 1,
        'ScandiPWA_CatalogCustomerGraphQl' => 1,
        'ScandiPWA_CatalogGraphQl' => 1,
        'ScandiPWA_CmsGraphQl' => 1,
        'ScandiPWA_CompareGraphQl' => 1,
        'ScandiPWA_ContactGraphQl' => 1,
        'ScandiPWA_CustomerDownloadableGraphQl' => 1,
        'ScandiPWA_CustomerGraphQl' => 1,
        'ScandiPWA_Route717' => 1,
        'ScandiPWA_DirectoryGraphQl' => 1,
        'ScandiPWA_Installer' => 1,
        'ScandiPWA_KlarnaGraphQl' => 1,
        'ScandiPWA_Locale' => 1,
        'Scandiweb_Core' => 1,
        'ScandiPWA_Performance' => 1,
        'ScandiPWA_PersistedQuery' => 1,
        'ScandiPWA_ProductAlertsGraphQl' => 1,
        'ScandiPWA_QuoteGraphQl' => 1,
        'ScandiPWA_Customization' => 1,
        'ScandiPWA_SalesGraphQl' => 1,
        'ScandiPWA_MenuOrganizer' => 1,
        'ScandiPWA_ServiceWorker' => 1,
        'Scandiweb_Slider' => 1,
        'ScandiPWA_StoreGraphQL' => 1,
        'ScandiPWA_UrlrewriteGraphQl' => 1,
        'ScandiPWA_WishlistGraphQl' => 1,
        'ScandiPWA_SampleData' => 1,
        'ScandiPWA_SliderGraphQl' => 1,
        'Temando_ShippingRemover' => 1,
        'Vertex_Tax' => 1,
        'Vertex_AddressValidationApi' => 1,
        'Vertex_RequestLoggingApi' => 1,
        'Vertex_RequestLogging' => 1,
        'Vertex_AddressValidation' => 1,
        'Yotpo_Yotpo' => 1
    ],
    'scopes' => [
        'websites' => [
            'admin' => [
                'website_id' => '0',
                'code' => 'admin',
                'name' => 'Admin',
                'sort_order' => '0',
                'default_group_id' => '0',
                'is_default' => '0'
            ],
            'base' => [
                'website_id' => '1',
                'code' => 'base',
                'name' => 'Main Website',
                'sort_order' => '0',
                'default_group_id' => '1',
                'is_default' => '1'
            ]
        ],
        'groups' => [
            [
                'group_id' => '0',
                'website_id' => '0',
                'name' => 'Default',
                'root_category_id' => '0',
                'default_store_id' => '0',
                'code' => 'default'
            ],
            [
                'group_id' => '1',
                'website_id' => '1',
                'name' => 'Main Website Store',
                'root_category_id' => '2',
                'default_store_id' => '1',
                'code' => 'main_website_store'
            ]
        ],
        'stores' => [
            'admin' => [
                'store_id' => '0',
                'code' => 'admin',
                'website_id' => '0',
                'group_id' => '0',
                'name' => 'Admin',
                'sort_order' => '0',
                'is_active' => '1'
            ],
            'default' => [
                'store_id' => '1',
                'code' => 'default',
                'website_id' => '1',
                'group_id' => '1',
                'name' => 'Default Store View',
                'sort_order' => '0',
                'is_active' => '1'
            ]
        ]
    ]
];
```

{% endcode %}

</details>

### Logs

Build phase logs are found in the [log portal](/application-management/log-management-using-kibana) under **build** filter.

### Breakdown

<div align="center"><img src="/files/gg12m93k5L7CXKRsiEPs" alt="This is a rough approximation of typical deployment flow in ReadyMage."></div>

## Deployment Phase

Deployment phase has two objectives:

1. Run `app:config:import`, `setup:upgrade` to perform database schema and data upgrades if necessary based on the build phase artifact.
2. Swap live servers to the servers that contain the build artifact.

### Logs

Deployment phase logs are found in the [log portal](/application-management/log-management-using-kibana) under **app-updater** filter.

### Breakdown

![This is a rough approximation of typical deployment flow in ReadyMage.](/files/HFnkOx8XIpfyuAHbknct)


# Pipeline Configuration file

ReadyMage supports user defined configuration file that can inject various actions into different points of build/deploy pipeline or customize existing pipeline logic.

## Used terms

**Vanilla Magento theme** - a theme which uses Magento built in mechanisms of [theme server-side compilation](https://devdocs.magento.com/guides/v2.4/frontend-dev-guide/css-guide/css_quick_guide_mode.html). For example `Magento/Luma`.

## How to use

Add the `readymage.yaml` file to Magento 2 root folder. It's the folder which contains base Magento 2`composer.*` files.

```
├── 📁 app
├── 📄 composer.json
├── 📄 composer.lock
└── 📄 readymage.yaml
```

## Examples

<details>

<summary>Default</summary>

{% code title="readymage.yaml" %}

```yaml
schema_version: 1.0.0
environments:
- name: readymage-test
  build:
    themes:
      all: 
	area: all
	languages: [ 'en_US' ]
	scandipwa/theme:
     area: frontend
	playbook: scandipwa
	directory: scandipwa
	languages: [ 'en_US' ]
```

{% endcode %}

**Scenario**: You always want to generate static files for all available themes.

</details>

<details>

<summary>Build speed optimized</summary>

{% code title="readymage.yaml" %}

```yaml
schema_version: 1.0.0
environments:
- name: readymage-test
  build:
    themes:
      Magento/backend:
        area: adminhtml
        languages: [ 'en_US' ]
      scandipwa/theme:
        area: frontend
        playbook: scandipwa
        directory: scandipwa
        languages: [ 'en_US' ]
```

{% endcode %}

**Scenario**: You know which exact themes are used in the website and need static file generation, thus saving time on the build phase by not generating files for themes that are not going to be used.

</details>

<details>

<summary>Using post build hook</summary>

{% code title="readymage.yaml" %}

```yaml
schema_version: 1.0.0
environments:
- name: readymage-test
  build:
    hooks:
      post_build:
      - copy:
          app/etc/config.php: scandipwa/config-copy.php
          scandipwa/config-copy.php: scandipwa/config-copy2.php
          scandipwa/config-copy2.php: scandipwa/config-copy-move.php
      - move:
          scandipwa/config-copy-move.php: scandipwa/config-move.php
      - symlink:
          scandipwa/config-symlink.php: scandipwa/config-copy.php
          scandipwa/config-symlink-persistent.php: persistent:config-symlink-perst.php
```

{% endcode %}

**Scenario**: You need to execute some actions after automated build phase has completed.

</details>

<details>

<summary>Using post deploy hook</summary>

```yaml
schema_version: 1.0.0
environments:
- name: readymage-test
  build:
    ...
  deploy:
    hooks:
      post_deploy:
        - php:
            command: bin/magento indexer:reindex
        - curl:
            directory: /mnt/
            filename: <filename>
            url: <download-link>
```

**Scenario**: You need to execute some actions after deployment has completed.

{% hint style="info" %}
When using the `curl` command, only use the `/mnt/` directory or any sub-directory under it as the value for the key `directory`. Anything that doesn't fall under `/mnt/` will be lost.
{% endhint %}

</details>

<details>

<summary>Compiling with custom playbook</summary>

{% code title="readymage.yaml" %}

```yaml
schema_version: 1.0.0
playbooks:
  test-book:
  - npm:
      command: ci
  - npm:
      command: run build
      env_vars:
        BUILD_MODE: magento
environments:
- name: readymage-test
  build:
    themes:
      Magento/backend:
        area: adminhtml
        languages: [ 'en_US' ]
      scandipwa/theme:
        area: frontend
        playbook: test-book
        directory: scandipwa
        languages: [ 'en_US' ]
```

{% endcode %}

**Scenario**: You want to compile your custom theme during the build phase.

</details>

<details>

<summary>Compiling vanilla Magento 2 themes</summary>

{% code title="readymage.yaml" %}

```yaml
schema_version: 1.0.0
environments:
- name: readymage-test
  build:
    themes:
      Magento/luma:
        area: frontend
        languages: [ 'en_US', 'en_GB', 'lv_LV' ]
      Magento/blank:
        area: frontend
        languages: [ 'en_US', 'en_GB', 'lv_LV' ]
      Magento/backend:
        area: adminhtml
        languages: [ 'en_US' ]
```

{% endcode %}

**Scenario**: You want to compile default vanilla Magento 2 themes.

</details>

<details>

<summary>Compiling PWA Studio</summary>

{% code title="readymage.yaml" %}

```yaml
schema_version: 1.0.0
playbooks:
  pwastudio:
  - npm:
      command: ci
      env_vars:
        NODE_ENV: development
  - npm:
      command: run build
      env_vars:
        MAGENTO_BACKEND_URL: https://test.readymage.com
        MAGENTO_BACKEND_EDITION: CE
        CHECKOUT_BRAINTREE_TOKEN: sandbox_8yrzsvtm_s2bg8fs563crhqzk
environments:
- name: readymage-test
  build:
    themes:
      Magento/backend:
        area: adminhtml
        languages: [ 'en_US' ]
      Magento/Luma:
        playbook: pwastudio
        area: frontend
        directory: pwastudio
        languages: ['en_US']
```

{% endcode %}

**Scenario**: You want to compile custom PWA Studio based theme.

</details>

## Schema

By default, ReadyMage will attempt to validate configuration file before running its directives. If its invalid, the build will automatically fail with a relevant error about which parts of the schema are invalid or failed to be ran.

#### <mark style="color:red;">`schema_version`</mark>

Required. Specifies which schema version is used in the configuration file. Allowed values: `1.0.0`

#### <mark style="color:red;">`environments`</mark>

Optional. Array of environment specific configurations

{% hint style="info" %}
If there are no themes specified for the environment, all available Magento themes will be built for all areas, with the default language of `en_US` or, if specified, languages defined in `config.php`
{% endhint %}

* <mark style="color:red;">**`name`**</mark>

  Required. Environment full name.
* <mark style="color:red;">**`build`**</mark>

  Optional. Nested dictionary containing build specific configurations.

  * <mark style="color:red;">**`themes`**</mark>

    Optional. Dictionary of environment themes. Themes directive allows to specify which of themes should be built. This includes theme compilation and locale specific [static file generation](https://devdocs.magento.com/guides/v2.4/config-guide/cli/config-cli-subcommands-static-view.html#config-cli-subcommands-staticview.).

    * <mark style="color:red;">**`{theme}`**</mark>

      Theme ID `<Vendor>/<theme>` as defined in [registration.php](https://devdocs.magento.com/guides/v2.4/frontend-dev-guide/themes/theme-create.html#fedg_create_theme_reg). Use `all` to generate static files for all Magento themes.

      * <mark style="color:red;">**`area`**</mark>

        Optional. Allowed values: `all`, `frontend`, `adminhtml`. If not defined, will fallback to `all`
      * <mark style="color:red;">**`languages`**</mark>

        Optional. Allowed values: array of strings. If not defined, will fallback to locales specified in `config.php` or if none found - to `en_US`
      * <mark style="color:red;">**`playbook`**</mark>

        Optional. Specifies which of the playbooks should be called during theme compilation. Ignored if theme ID is set to `all`
      * <mark style="color:red;">**`directory`**</mark>

        Required if playbook field is set. Specifies in which directory the theme is located at. Ignored if theme ID is set to `all`&#x20;
  * <mark style="color:red;">**`hooks`**</mark> Optional. Hooks are a way to inject custom logic around automated actions (e.g. build). For example, if you need to swap `config.php` file for specific environment before the build. Allowed values: `pre_build`, `post_build.` To customize theme compilation and static content file generation logic, use playbook and theme directives instead of using the hooks.
    * <mark style="color:red;">**`pre_build`**</mark> This hook is run before automated build phase. Can contain only [actions](#actions). Any actions here will permanently disable build cache until all of the actions are removed. **It will result in permanently increased build times.**
    * <mark style="color:red;">**`post_build`**</mark> This hook is run after automated build phase. Can contain only [actions](#actions).&#x20;
* <mark style="color:red;">**`deploy`**</mark>\
  Optional. Nested dictionary containing deploy specific configurations.
  * <mark style="color:red;">**`hooks`**</mark>\
    Optional. Hooks in this context offer a way to execute the needed commands throughout the deployment.&#x20;
    * <mark style="color:red;">**`post_deploy`**</mark>\
      This hook runs after the deployment has completed successfully. Available commands are `php` and `curl` only.

#### <mark style="color:red;">**`playbooks`**</mark>

Optional. Dictionary of playbooks.

A playbook is set of actions that are called on the theme build/compilation step. It’s invoked during the build pipeline before automated `setup:static-content:deploy`. To customize static-content deployment, use themes directive.

Playbooks can only contain [actions](#actions). All the actions defined inside a playbook will be executed in sequentially manner.

<details>

<summary>Example</summary>

```yaml
...
playbooks:
  my-playbook:
  - npm:
      command: ci
      directory: some_directory
  - npm:
      command: build
      directory: some_directory
      env_vars:
        BUILD_MODE: magento
   - copy:
       app/etc/config.php: app/etc/config2.php
       app/etc/config2.php: app/etc/config3.php
...
```

</details>

Out of the box ReadyMage provides several playbooks, alongside with the possibility of defining fully custom playbooks.

#### `scandipwa`, `scandipwa_npm`

Curated, builtin playbook which is actively maintained and test against 3.x and higher ScandiPWA themes. The approximation of the curated playbook can be expressed using following [actions](#actions):

```yaml
playbooks:
  scandipwa_npm_aprox:
  - npm:
      command: ci
      directory: scandipwa
  - npm:
      command: build
      directory: scandipwa
      env_vars:
        BUILD_MODE: magento
```

#### `scandipwa_yarn`

Curated, builtin playbook which is actively maintained and test against 3.x and higher ScandiPWA themes. The approximation of the curated playbook can be expressed using following [actions](#actions):

```yaml
playbooks:
  scandipwa_yarn_aprox:
  - yarn:
      command: install --immutable --immutable-cache --check-cache
      directory: scandipwa
  - yarn:
      command: build
      directory: scandipwa
      env_vars:
        BUILD_MODE: magento
```

#### Custom

To create custom theme build/compilation logic which falls outside the curated playbooks, simply create a custom playbook where all of the necessary build actions can be defined. This can be accomplished by defining a set of actions grouped inside the playbook that will be responsible for theme compilation. The resulting playbook will be available on any environments themes playbook field.

{% hint style="info" %}
To build vanilla Magento themes, there is no need to specify playbook.
{% endhint %}

#### <mark style="color:red;">`actions`</mark>

Actions are generic, cherry-picked commands that are executed in pre-defined places inside the deployment pipeline. Actions can only be used inside [playbooks](#playbooks) or hooks.

* <mark style="color:red;">**`copy`**</mark>\
  Copies from source to destination. The path is relative to the Magento installation directory. Will overwrite file/directory if it exists at destination.
  * <mark style="color:red;">**`{source}: {destination}`**</mark>

<details>

<summary>Example</summary>

```yaml
...
- copy:
    app/etc/config.php: scandipwa/config.php
...
```

</details>

* <mark style="color:red;">**`move`**</mark>\
  Moves from source to destination. The path is relative to the Magento installation directory. Will overwrite the file/directory if it exists at destination.
  * <mark style="color:red;">**`{source}: {destination}`**</mark>

<details>

<summary>Example</summary>

```yaml
...
- move:
    app/etc/config.php: scandipwa/config.php
...
```

</details>

* #### <mark style="color:red;">`symlink`</mark>

  Creates symbolic link at the path pointing to the target. The path is relative to the Magento installation directory. The target is relative to the Magento installation directory, unless prefiexed with `persistent:` Will overwrite the file/directory if it exists at path.

  * <mark style="color:red;">**`{path}: {target}`**</mark>\
    Use `persistent:` prefix in target to set a symlink persistent and shared directory.

<details>

<summary>Example</summary>

```yaml
...
- symlink:
    app/test.xml: app/design/frontend/Ricards/test.xml
    app/test2.xml: persistent:test.xml
...
```

</details>

* #### <mark style="color:red;">`composer`</mark>

  Runs custom composer v1 or v2 commands. Use only if you have additional non-magento composer installations inside the project that have to be initialized after the main build.

  * <mark style="color:red;">**`command`**</mark> - Required.
  * <mark style="color:red;">**`version`**</mark> - Required. Allowed values: `1`, `2`
  * <mark style="color:red;">**`directory`**</mark> - Optional. If not defined, will fallback to theme directory.

{% hint style="warning" %}
Composer state should be **always** managed by `composer.json` and `composer.lock` files instead of configuration file actions!
{% endhint %}

* #### <mark style="color:red;">`npm`</mark>&#x20;
  * <mark style="color:red;">**`command`**</mark> - Required.
  * <mark style="color:red;">**`directory`**</mark> - Optional. If not defined, will fallback to theme directory.
  * <mark style="color:red;">**`env_vars`**</mark> - Optional. Nested field, contains all environmental variables that should be passed to the command

<details>

<summary>Example</summary>

```yaml
...
- npm:
    command: run build
    directory: scandipwa
    env_vars:
      BUILD_MODE: magento
...
```

</details>

* #### <mark style="color:red;">`yarn`</mark>&#x20;
  * <mark style="color:red;">**`command`**</mark> - Required.
  * <mark style="color:red;">**`directory`**</mark> - Optional. If not defined, will fallback to theme directory.
  * <mark style="color:red;">**`env_vars`**</mark> - Optional. Nested field, contains all environmental variables that should be passed to the command

<details>

<summary>Example</summary>

```yaml
...
- yarn:
    command: run build
    directory: scandipwa 
    env_vars: 
      BUILD_MODE: magento
...
```

</details>

* #### <mark style="color:red;">`php`</mark> (available on post\_deploy hooks only)&#x20;
  * <mark style="color:red;">**`command`**</mark> - Required.
  * <mark style="color:red;">**`directory`**</mark> - Optional. If not defined, will fallback to the root directory `/var/www/public/`.

<details>

<summary>Example</summary>

```yaml
...
- php:
    command: bin/magento indexer:reindex
...
```

</details>

#### <mark style="color:red;">`curl`</mark> (available on post\_deploy hooks only)&#x20;

* <mark style="color:red;">**`command`**</mark> - Required.
* <mark style="color:red;">**`directory`**</mark> - Required. Must specify an absolute path to the `/mnt/` directory.
* <mark style="color:red;">**`filename`**</mark> - Required. Must specify the name of the downloaded file.

<details>

<summary>Example</summary>

```yaml
...
- curl:
    directory: /mnt/
    filename: <filename>
    url: <download-link>
...
```

</details>

## Schema migrations

{% content-ref url="/pages/yhNhJHEtWy7ILJSTovKJ" %}
[Migration guide from 0.x.x to 1.0.0](/application-management/deploy-changes-to-your-instance/pipeline-configuration-file/migration-guide-from-0.x.x-to-1.0.0)
{% endcontent-ref %}


# Migration guide from 0.x.x to 1.0.0

## Migration

### 1. Update configuration file name

First, update configuration file name from `.readymage.yaml` → `readymage.yaml`

### 2. Update property names

Convert [camelCase](https://en.wikipedia.org/wiki/Camel_case) property names to [snake\_case](https://en.wikipedia.org/wiki/Camel_case).

For example:

* `schemaVersion` → `schema_version`
* `preBuild` → `pre_build`
* `postBuild` → `post_build`

### 3. Update hooks

Contents of `hooks` have been moved from array type to regular key-values

```yaml
hooks:
- preBuild: ...
- postBuild: ...
```

→

```yaml
hooks:
  pre_build: ...
  post_build: ...
```

### 3. Update actions

#### Copy

```yaml
...
- copy:
    name: Copy config
    source: app/etc/config-ca.php
    destination: app/etc/config.php
...
```

→

```yaml
...
- copy:
    app/etc/config-ca.php: app/etc/config.php
...
```

#### Move

```yaml
...
- move:
    name: Move config
    source: app/etc/config-ca.php
    destination: app/etc/config.php
...
```

→

```yaml
...
- move:
    app/etc/config-ca.php: app/etc/config.php
...
```

#### Symlink

```yaml
...
- symlink:
    name: Symlink to target inisde persistent directory
    path: satis/satis.json
    target: satis.json
    persistentTarget: true

- symlink:
    name: Symlink to target inside magento root directory
    path: package2.json
    target: scandipwa/package.json
...
```

→

```yaml
...
- symlink:
    satis/satis.json: persistent:satis.json
    package2.json: scandipwa/package.json
...
```

### Example migration

```yaml
schemaVersion: 0.4.0
environments:
- name: readymage-testinging-env-a
  build:
    hooks:
    - preBuild:
      - copy:
          name: Copy magento php config
          source: app/etc/config-ca.php
          destination: app/etc/config.php
- name: readymage-testinging-env-b
  build:
    hooks:
    - preBuild:
      - copy:
          name: Copy magento php config
          source: app/etc/config-aus.php
          destination: app/etc/config.php
      - copy:
          name: Copy package.json
          source: scandipwa/package-aus.json
          destination: scandipwa/package.json
      - copy:
          name: Copy package-lock.json
          source: scandipwa/package-lock-aus.json
          destination: scandipwa/package-lock.json
```

→

```yaml
schema_version: 1.0.0
environments:
- name: readymage-testinging-env-a
  build:
    hooks:
      pre_build:
      - copy:
	  app/etc/config-ca.php: app/etc/config.php
- name: readymage-testinging-env-b
  build:
    hooks:
      pre_build:
      - copy:
          app/etc/config-aus.php: app/etc/config.php
	  scandipwa/package-aus.json: scandipwa/package.json
          scandipwa/package-lock-aus.json: scandipwa/package-lock.json
```


# Deploy without build cache

Deploying without a build cache is a specialized approach required in certain scenarios where the deployment system encounters inconsistencies due to unawareness of specific changes. This is particularly useful when missing styles, uncompiled chunks, or absent installed modules arise.

{% hint style="info" %}
**Why was it needed?**

The necessity for deploying without build-cache arises when the deployment system lacks awareness of certain changes within the codebase, leading to discrepancies during the deployment process.
{% endhint %}

## How It Works

* **With build artifact:** \
  By default, when deploying with a build artifact, the system captures the commit ID (Hash) that was last triggered during the deployment. During the code build step, the deployment service compares the differences between the previous and latest commit hash using the following Git command:

  ```
  git --no-pager diff --name-status --stat ${previousSha} ${currentSha}
  ```

  Based on the changes and the locations of the modified files, the deployment functionality determines the necessary commands to be executed. This may include actions such as compiling static content or downloading packages. Once the code build is complete, the majority of the codebase is archived and sent to an S3 bucket, referred to as the "artifact."<br>
* **Without build artifact**: \
  If the option is chosen to perform deployment without an artifact, an EMPTY Tree SHA is utilized. In this scenario, the deployment system loads all content from the GitHub repository and performs the same checks. However, since an empty tree SHA is used, all files within the repository are considered, triggering all deployment actions.

***

{% hint style="info" %}
**Why can't we just do all deployments without building cache?**

Building without artifacts for all deployments will result in longer deployment times since it's not always necessary to install `vendor` or download packages (npm/yarn) etc.
{% endhint %}

***

## How to enable deployment without build cache

1. Navigate to **User Portal → Project → Selected Instance → Overview → Deployments**

<figure><img src="/files/6NIf8CwhI8ricNTlFOUl" alt=""><figcaption></figcaption></figure>

2. Click on the **Start Deployment** button
3. Check the **Deploy without build caches** check box

<div data-full-width="true"><figure><img src="/files/XOgmRSsOyBi5wuYW3tri" alt=""><figcaption></figcaption></figure></div>


# GitHub Management

{% hint style="warning" %}
This page has been moved to [Project Settings > Git Management](/project-management/project-settings/git-management).
{% endhint %}


# SSH Access

To use CLI commands and access the instance database you need to receive SSH access.

ReadyMage offers 2 methods of adding an SSH key to the environment:

## Using account SSH key integration (preferred way)

Using this method you will not need to copy-paste your key for each environment. It will be linked to your ReadyMage account.

### Add SSH key to your account

Navigate to **Account -> SSH Keys**.

<figure><img src="/files/lQXLWda3I4neVCh5lSVp" alt=""><figcaption></figcaption></figure>

Copy and paste the contents of your **public SSH key** into the text field and click **Save SSH Key**.

<figure><img src="/files/68gGUHMttuk4B7Dv0RB5" alt=""><figcaption></figcaption></figure>

After saving, the SSH key will be visible in the **Integrations -> SSH Keys.**

### Grant user access to SSH

Navigate to **User Portal → Project → Selected Instance → Application Management → SSH Access** tab. Click **Add User** and select User by email.

<figure><img src="/files/sMT5fYSmH25py7GLyF4E" alt=""><figcaption></figcaption></figure>

## Using SSH key

To do that, navigate to the **User Portal → Project → Selected Instance → Application Management → SSH Access** tab. Click **Add SSH Key**, fill in your SSH username, and add your SSH Public Key.

![](/files/9M6EWwF8cHdtQLTo7s0k)

## Connecting to the SSH server

To connect using the Terminal, copy the command by clicking on *Copy* and enter it in the terminal.

![](/files/2fGvokf3it1zedoWxDrE)

If you are connecting using a graphical interface you might have to add:

* Host by region:
  * USA Ohio: `ssh.ohio.us.i.readymage.com`
  * Canada Central: `ssh.central.ca.i.readymage.com`
  * Europe Ireland: `ssh.ireland.eu.i.readymage.com`
  * Europe Stockholm: `ssh.stockholm.eu.i.readymage.com`
  * Middle East UAE: `ssh.central.me.i.readymage.com`
  * Asia Pacific Sydney: `ssh.sydney.ap.i.readymage.com`
* Port - 22

You can remove users by pressing the *Delete* button next to their username.

More details on CLI, Utilities, and Tools can be found [here](/application-management/ssh-access/ssh-usage).<br>


# SSH Usage

Each environment can have an SSH container that allows a list of various actions. It doesn’t give direct access to any of the application/database containers.

### Utilities that you can use: <a href="#utilities-that-you-can-use" id="utilities-that-you-can-use"></a>

1. Magento cli — magento commands that will be executed on your application pods `magento CMD`
2. MySQL cli tools — provides access to your database: `mysql`\
   \
   `// Make dump`\
   mysqldump magento --single-transaction --no-tablespaces | gzip > dump.sql.gz
3. Redis cli — provides access to your redis. To connect: `redis-cli -h redis -p 6379`
4. Tools for copying:
   * rsync — use to sync data on local and ssh container. For example, to sync media folder: `// From local to SSH container`\
     `rsync -azP media/ your-user@ssh.readymage.com:/home/magento/media/` \
     \
     `// From SSH container to local`\
     `rsync -azP your-user@ssh.readymage.com:/home/magento/media/media/`
   * scp — the same purpose as rsync.

     **NB:** the only directory that’s allowed to copy data is /home/magento. Copy database backups and media there only.
5. Tools for compressing files:
   * gzip
   * tar
   * zcat
   * dar
6. Useful tools:
   * cat
   * clear
   * curl
   * du
   * find
   * gpg
   * grep
   * head
   * jq
   * pv
   * tail
   * tmux
   * wget
   * nano


# Database Access using Graphical Interface

You can access the database using a graphical interface that supports SSH connection.

### macOS <a href="#macos" id="macos"></a>

#### 1. Configure SSH Access <a href="#id-1.-configure-ssh-access" id="id-1.-configure-ssh-access"></a>

Follow [this guide](/application-management/ssh-access) to set up SSH access.

#### 2. Get database connection details <a href="#id-2.-get-database-connection-details" id="id-2.-get-database-connection-details"></a>

After making a successful SSH connection use this command:

`cat .my.cnf`

Note the following details

* host
* user
* password

#### 3. Setup Sequel Pro <a href="#id-3.-setup-sequel-pro" id="id-3.-setup-sequel-pro"></a>

Visit the [Sequel Pro official website](https://www.sequelpro.com/) to set it up.

#### 4. Configure Database Connection <a href="#id-4.-configure-database-connection" id="id-4.-configure-database-connection"></a>

![](/files/DdWcgvG0F0eMZ6jYCftq)

Enter the following details from the data you got in step 2:

* MySQL Host
* Username
* Password

Other details:

* SSH Host by region:
  * USA Ohio: `ssh.ohio.us.i.readymage.com`
  * Europe Ireland: `ssh.ireland.eu.i.readymage.com`
  * Europe Stockholm: `ssh.stockholm.eu.i.readymage.com`&#x20;
  * Canada Central: `ssh.central.ca.i.readymage.com`
  * Middle East UAE: `ssh.central.me.i.readymage.com`
  * Asia Pacific Sydney: `ssh.sydney.ap.i.readymage.com`
* SSH Port - 22
* SSH User: copy from User Portal following [this guide](/application-management/ssh-access)
* SSH Password: enter only if you have set a password for your SSH when generating it on your computer

**Press Connect to connect to your database.**

### Linux and Windows

#### **1. Configure SSH Access**

Follow [this guide](https://help.readymage.com/user-portal/ssh-access) to set up SSH access.

#### **2. Get database connection details**

After making a successful SSH connection use this command:

```
cat .my.cnf
```

Note the following details

* host
* user
* password

#### **3. Setup MySQL Workbench**

Download available [here](https://dev.mysql.com/downloads/workbench/). Setup instructions for [Linux](https://linuxhint.com/installing_mysql_workbench_ubuntu/) and [Windows](https://dev.mysql.com/doc/workbench/en/wb-installing-windows.html).

#### **4. Configure Database Connection**

Make sure to select **Standard TCP/IP over SSH** as the **Connection Method.**

<figure><img src="/files/bLSmx6nymI8iq339Eaqa" alt=""><figcaption></figcaption></figure>

**Enter the following details from the data you got in step 2:**

* MySQL Host
* Username
* Password

Other details:

* SSH Host by region (port included):
  * USA Ohio: `ssh.ohio.us.i.readymage.com:22`
  * Europe Ireland: `ssh.ireland.eu.i.readymage.com:22`
  * Europe Stockholm: `ssh.stockholm.eu.i.readymage.com:22`
  * Canada Central: `ssh.central.ca.i.readymage.com:22`
  * Middle East UAE: `ssh.central.me.i.readymage.com:22`
  * Asia Pacific Sydney: `ssh.sydney.ap.i.readymage.com:22`
* SSH User: copy from User Portal following [this guide​](/application-management/ssh-access)
* SSH Password: enter only if you have set a password for your SSH when generating it on your computer
* SSH Key File: choose your SSH private key file location.

After filling in the connection parameters click **Test Connection** and you should see the following window:&#x20;

<figure><img src="/files/HVZFRQ48SIzPNKz7DOzs" alt=""><figcaption></figcaption></figure>

Click **OK**, then **OK** to save your connection settings and your created connection will be available in the **MySQL Connections** list.<br>

<figure><img src="/files/VIwP6fANZRezkilfjHAQ" alt=""><figcaption></figcaption></figure>


# Troubleshooting

## Issues connecting with ReadyMage account

Make sure that you have added an SSH key to your account.

<figure><img src="/files/OUXwbQThDoF9XerCc00O" alt=""><figcaption></figcaption></figure>

If you see this red warning triangle, navigate to **Account -> Integrations** and add your SSH key using [our guide](/application-management/ssh-access).

## Issues connecting via SSH

1. Make sure that key that was added to SSH access is a valid **public** **key**.
2. When connecting via **OpenSSH 8.8+ client** ensure that the following configuration is added to the [SSH client configuration file](https://www.ssh.com/academy/ssh/config):&#x20;

   <pre data-line-numbers><code>Host *
   <strong>PubkeyAcceptedAlgorithms +ssh-rsa
   </strong></code></pre>

   Or inline the configuration option when connecting, for example:

   ```
   ssh -o 'PubkeyAcceptedKeyTypes +ssh-rsa' your-ssh-user@ssh.ireland.eu.i.readymage.com
   ```

## tmux

If running time-consuming commands via SSH the [tmux](https://github.com/tmux/tmux/wiki) terminal might come in handy to preserve your SSH session and even have multiple CLI windows.


# IP Whitelist

The whitelist can be managed in **User Portal → Project → Selected Instance -> Application Management -> IP Whitelist** section. You may add, remove, edit, and toggle individual whitelist items.

A maximum of 20 whitelist items can be added.

### Add IP

To add an IP, tap the button *Add IP* on the top right, then set the label, hosts, paths, and desired IPs.

![](/files/88dftZBho5cQMPeWPxhb)

### Enable the whitelist

Enabling whitelisting will restrict access to the specified hosts' paths. Access to them will be possible only from the IP addresses added to the whitelist. Those who will try to access the page using an IP address that is not on the list will see a 403 HTTP error page, meaning that access is restricted.

Once a whitelist item is added it will appear in the list. By default all the new items in the list are disabled. To enable the whitelist item, click on the *Enabled* toggle.

<figure><img src="/files/hwZrsKvhgrf15rg8duOS" alt=""><figcaption></figcaption></figure>


# Password Authentication

Password authentication will restrict access to your store frontend. Access to it will be possible only after entering valid password.

<figure><img src="/files/fw6R1D50hf6oeJiATrgx" alt=""><figcaption></figcaption></figure>

### Edit password

To change the password, enter a new password in the **Change Password** section and click **Save Password**.

<figure><img src="/files/96JrTZ2tuUrz7dOlGqHN" alt=""><figcaption></figcaption></figure>

### Adding password to non-browser requests

For non-browser requests, alongside your request, send a cookie `readymagepass` with same value as the password.&#x20;

For example:

#### Curl

```
curl --location --request GET 'https://yourstore.readymage.com/' --header 'Cookie: readymagepass=your_password
```

###


# Database & Media

This feature allows you to replace your instance database/media with database/media from another instance. It is useful for setting up testing environments.&#x20;

{% hint style="info" %}
Note that your current database/media on this instance will be removed and the database/media from the selected instance will be fully imported.
{% endhint %}

To access, navigate to the **User Portal → Project → Selected Instance → Application Management → Database & Media**.

![](/files/DsOn6YSOzqiitTa5Zotw)

{% hint style="warning" %}
Be aware that the encryption key will be moved with the database as well. This can affect the security of the source instance.
{% endhint %}

If database schema and data migration versions differ from those that are defined in the code, your Magento 2 instance will experience downtime until those versions are synced.

After the database is replaced, you need to manually replace the base URLs in the destination instance database because they will have the values of the source instance database.


# Search Engine Bots Discovery

By default, this setting will **block** Search Engine Bots from crawling and indexing your website.

Crawling & indexing your website by Search Engine Bots should be done only on production instances so we recommend leaving this setting in a **prevented** state for all other instances.

## Block Search Engine Bots from discovering your website

To prevent Search Engine Bots from discovering your website you must navigate to **Portal > Selected Project > Selected Environment > Application Management > Search Engine Bots Discovery** tab and click **Block Search Engine Bots**.

<figure><img src="/files/DeElTmX3pJaTpodEHgZ2" alt=""><figcaption><p>Search Engine Discovery not allowed</p></figcaption></figure>

Confirm that you want to prevent Search Engine Bots Discovery.

<figure><img src="/files/1f7HJA1ArjFiEUOIzMS2" alt=""><figcaption><p>Allow Search Engine Discovery prompt</p></figcaption></figure>

Now **Search Engine Bots Discovery** setting tab will have an updated description.

<figure><img src="/files/2GQxW9Kgk6jojjHZFMeN" alt=""><figcaption></figcaption></figure>

In the [Deployments](/application-management/deploy-changes-to-your-instance) tab, you will be required to run the next deployment without a cache. Automatic deployment will also happen without a cache.

<figure><img src="/files/NewwaScYjfuQqTlpszd8" alt=""><figcaption></figcaption></figure>

After successful deployment, the **Search Engine Bots** will be blocked from crawling, discovering and indexing your website.

## Allow Search Engine Bots to discover your website

To allow Search Engines to crawl, discover, and index your website you must navigate to **Portal > Selected Project > Selected Environment > Application Management > Search Engine Bots Discovery** tab and click **Allow Search Engine Bots**.

<figure><img src="/files/lqOIuf5ptdhfhCais8rA" alt=""><figcaption></figcaption></figure>

Confirm that you want to allow Search Engine Bots Discovery.

<figure><img src="/files/LSbKVeldY64L7jmrsz5d" alt=""><figcaption></figcaption></figure>

Now **Search Engine Bots Discovery** setting tab will have an updated description.

<figure><img src="/files/dK1xoSpTxQ26FTQfyosD" alt=""><figcaption></figcaption></figure>

In the [Deployments](/application-management/deploy-changes-to-your-instance) tab, you will be required to run the next deployment without a cache. Automatic deployment will also happen without a cache.

<figure><img src="/files/5FRyVIdpQ7KAkHu3Ul0q" alt=""><figcaption></figcaption></figure>

After successful deployment, navigate to **Magento Admin Panel > Content > Design > Configuration > Default Website > Search Engine Robots** and confirm that **Default Robots** is set to **INDEX, FOLLOW** and **Custom instructions for robots.txt** are either **empty** or contain correct instructions for Search Engine Bots.

<figure><img src="/files/EJqozpbYI0uCTfgrywqX" alt=""><figcaption></figcaption></figure>

Click **Save Configuration** and flush the invalidated cache type! That is it!


# Maintenance Page

On this page, you will learn to control Maintenance Page settings for your application

{% content-ref url="/pages/O1Zwu4PVpU9fuD6CIKir" %}
[Website Access During Maintenance](/application-management/maintenance-page/website-access-during-maintenance)
{% endcontent-ref %}

{% content-ref url="/pages/fSHR0sfQ7fRKnZISm2zy" %}
[ReadyMage Maintenance Page](/application-management/maintenance-page/readymage-maintenance-page)
{% endcontent-ref %}


# Website Access During Maintenance

Readymage maintenance module only replaces the default Magento 2 maintenance page template with Readymage's version, while retaining accessibility to other Magento CLI commands.

{% hint style="warning" %}
You must already have SSH access to the instance. Refer to the documentation for SSH access instructions: [Readymage SSH Access Documentation](https://help.readymage.com/application-management/ssh-access).
{% endhint %}

### To add or remove exempted IP addresses

You can manage the list of exempted IP addresses by utilizing the `[--ip=]` option in the preceding commands or by following the method below:

```bash
bin/magento maintenance:allow-ips <ip address> .. <ip address> [--none]
```

The `<ip address> .. <ip address>` syntax is an optional space-delimited list of IP addresses to exempt.

The `--none` option clears the list.


# ReadyMage Maintenance Page

ReadyMage replaces the default Magento 2 maintenance page with our custom Maintenance Page

{% tabs %}
{% tab title="ReadyMage custom Maintenance Page" %}

<figure><img src="/files/f2tC5mF3qhrg0UPJ3zqA" alt=""><figcaption><p>ReadyMage maintenance page</p></figcaption></figure>
{% endtab %}

{% tab title="Default Maintenance Page" %}

<figure><img src="/files/C29VsWRh3w149CSGxrBs" alt=""><figcaption><p>Default Magento 2 maintenance page</p></figcaption></figure>
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="ReadyMage Maintenance Page on mobile" %}

<figure><img src="/files/EFvKpxlQTDpcuMgRNQLF" alt="" width="375"><figcaption><p>ReadyMage Maintenance Page on Samsung S24</p></figcaption></figure>
{% endtab %}

{% tab title="Default Maintenance Page on mobile" %}

<figure><img src="/files/aw774skryTXxCw5RXAUW" alt="" width="375"><figcaption></figcaption></figure>
{% endtab %}
{% endtabs %}

If you want to have your own maintenance page displayed instead, please get in touch with customer support.


# Server-Side Rendering

Server-side rendering allows the content of your PWA store to be available for the search engine and social network bots.

SSR (Server-Side Rendering) provides the content of your PWA store to the search engine and social network bots for the best indexing and display.

ReadyMage instances come with a **RendyJS** module available. You can request to connect to it through the User Portal.

{% hint style="info" %}
If connected, you will be billed based on your usage automatically through your regular monthly invoice.
{% endhint %}

<figure><img src="/files/Rmscjj03Wsx7mjMlmLMx" alt=""><figcaption></figcaption></figure>

### Connecting to the ReadyMage account

1. Navigate to **User Portal → Project → Selected Instance → Service Management → Server-Side Rendering**.
2. Click **Connect**.
3. RendyJS will be activated within 2-3 working days.

{% hint style="info" %}
Note: A charge for RendyJS will be added to your monthly bill.
{% endhint %}

### Disconnecting your RendyJS account

1. Navigate to User Portal → Instances → Service Management → Server-Side Rendering.
2. Click **Disconnect**.
3. RendyJS will be deactivated within 2-3 working days.


# SFTP

SFTP (SSH File Transfer Protocol) works by using a secure shell data stream. It establishes a secure connection and then provides a higher level of protection for data while transferring it.

## SFTP Access

### Using account SSH key integration (preferred way)

Using this method you will not need to copy-paste your key for each environment. It will be linked to your ReadyMage account.

#### Add SSH Key to your account

Navigate to **Account -> Integrations**.

<figure><img src="/files/uZAOSaTsmYSGiX5Kl1TM" alt=""><figcaption></figcaption></figure>

Click **Add Key**.

<figure><img src="/files/pjSKFmfIm00aFXPK7Fm1" alt=""><figcaption></figcaption></figure>

Enter your SSH Public Key and click **Save**.

<figure><img src="/files/eIQz5UEfgT6hdwOqova5" alt=""><figcaption></figcaption></figure>

After saving, the SSH key will be partially visible in the integrations.

<figure><img src="/files/cKbpu6sf376a8FADMLlk" alt=""><figcaption></figcaption></figure>

#### Grant user access to SFTP

Navigate to **User Portal → Project → Selected Instance → Service Management → SFTP** tab. Click **Add User** and select User by email.

<figure><img src="/files/z0PJKKxKHqQkRIdlwHp4" alt=""><figcaption></figcaption></figure>

### Using SSH key

Navigate to the **User Portal → Project → Selected Instance → Application Management → SFTP** tab. Click **Add SFTP Key**, fill in your SSH username, and add your SSH Public Key or leave it empty to get a **one-time** generated password.

<figure><img src="/files/GID5FQIovUiE6XwmExB5" alt=""><figcaption></figcaption></figure>

## Directory mapping

Following directories are available on the SFTP server and mapped to appropriate directories in Magento 2 root:

* `/import` -> `<magento2_root>/var/import`
* `/export` -> `<magento2_root>/var/export`
* `/media` -> `<magento2_root>/pub/media`

## Connect to SFTP server

Connection details are available in the SFTP tab in the Service Management section.

{% hint style="warning" %}
SFTP does not grant access to Magento 2 and ScandiPWA source files. Code changes and extension installation require [local setup](https://help.readymage.com/project-development/code-customization-and-local-setup).
{% endhint %}

### Connect using FileZilla

To connect to the SFTP server you can use a free cross-platform client like [FileZilla](https://filezilla-project.org/).

1. Open FileZilla.
2. Go to Edit > Settings > Connection > SFTP
3. Add your private SSH key using Add key file button.
4. Enter Host, Username, and Port in Quickconnect fields.
5. Press Quickconnect.


# NewRelic

Your instance comes with the **NewRelic** module already pre-installed. In order to activate it, you must [create a NewRelic account](https://newrelic.com/signup) and configure the NewRelic license key in the User Portal.

You can get your account NewRelic key by following the instructions here - <https://docs.newrelic.com/docs/accounts/install-new-relic/account-setup/license-key>

{% hint style="danger" %}
**Important!**

For the application name in NewRelic, use the namespace of your instance but without "readymage-" prefix. E.g., if your namespace is "readymage-mystore-yud-1631089038", use the "mystore-yud-1631089038" application name in NewRelic
{% endhint %}

Once you have your license key you have to go to the **User Portal → Project → Selected Instance → Service Management → NewRelic** tab and configure it there.&#x20;

To disconnect NewRelic, remove the key and press the *Connect* button.

<figure><img src="/files/VYGZCck8RoWVDeiRJqDK" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Enable NewRelic Distributed Tracing to track requests across the microservices, more information can be found [here](https://docs.newrelic.com/docs/distributed-tracing/concepts/introduction-distributed-tracing/).
{% endhint %}

{% hint style="danger" %}
Enabling Distributed Tracing functionality generates a lot of traffic which may leads to extra billing costs.
{% endhint %}

## Single Page App Monitoring

ScandiPWA is a SPA (Single Page Application). To make the most of NewRelic and be able to have metrics about page load times you must enable Single Page App monitoring.

![](/files/-MN3x0P8aFGNoyjcWr0F)

Learn more on how to set up and use Single Page App monitoring in [official NewRelic documentation](https://docs.newrelic.com/docs/browser/single-page-app-monitoring/get-started/introduction-single-page-app-monitoring).


# Packagist Modules

{% hint style="danger" %}
Packagist Module functionality has been replaced by the [Variables Management page](/application-management/variables-management#packagist) functionality.
{% endhint %}

{% content-ref url="/pages/aX8eLSVpfCDo6gmNrS6H" %}
[Variables Management](/application-management/variables-management)
{% endcontent-ref %}


# Cloudflare

Using Cloudflare is not obligatory when launching a project on Readymage or any other hosting provider, but we strongly advise considering its inclusion due to the numerous benefits it offers. In essence, Cloudflare enhances speed, security, and protection against DDoS attacks and robots, as well as provides valuable traffic insights.

To delve further into Cloudflare's features:

* As a Content Delivery Network (CDN), all requests are routed through Cloudflare. With a vast network of servers located closer to end users, it can cache responses and deliver them faster.
* Cloudflare optimizes images by converting them into smaller, more modern formats.
* It possesses the ability to identify and block DDoS attacks.
* Cloudflare includes rate-limiting capabilities, which can be advantageous in preventing data exfiltration from APIs.
* It offers insights regarding traffic, such as the country, network provider, user agent, and other metadata. These insights aid in making informed blocking decisions and gaining a better understanding of incoming traffic.
* Cloudflare incorporates a web application firewall (WAF) that blocks malicious requests.

Follow the [appropriate instructions](/project-development/connect-cdn-and-webp-optimization) depending on where your domain is hosted to configure Cloudflare and ReadyMage instance connection.&#x20;

Access the Cloudflare setting through the **User Portal → Project → Selected Instance → Configuration → Cloudflare**.&#x20;

<figure><img src="/files/F5HDWOkCil4cmeo7eZ9o" alt=""><figcaption></figcaption></figure>

#### Cloudflare Cache Purging Functionality

**Purge Cache**

* Use **Purge** button to clear the Cloudflare cache for specific URLs, specific hostname, or the entire cache ("Purge Everything").

<figure><img src="/files/WKIFFqcZ5aZO1O3kh99P" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
The domains need to be managed by ReadyMage Cloudflare account <admin@readymage.com>, if not then the Project Owner would need to provide Cloudflare API Token and Zone ID to be able to use the functionality as discussed below
{% endhint %}

**Cloudflare Credentials:**

* To configure Cloudflare settings, click **Configure** next to the desired domain.

<figure><img src="/files/XfdXWdJyhta7ZvIMK9uG" alt=""><figcaption></figcaption></figure>

In case of hosting domains which are not managed by us, the Project Owner would need to provide Cloudflare credentials as described in the below Cloudflare developer guides:

* [API Token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) - Select **Cache Purge** permission
* [Zone ID](https://developers.cloudflare.com/fundamentals/account/find-account-and-zone-ids/#copy-your-zone-id)

<figure><img src="/files/RHTINcitHJW2rWl6zCjP" alt=""><figcaption></figcaption></figure>

#### Exclude Magento admin from Cloudflare

If you are running long processes in Magento admin, it is recommended that you set up a separate domain for Magento admin and disable Cloudflare to avoid operation timeouts. Find detailed instructions [here](/project-development/connect-cdn-and-webp-optimization#exclude-magento-admin-from-cloudflare).


# Autoscale

ReadyMage autoscale applies to the Magento **Admin Panel** and **Front End**.&#x20;

Your store's resource load is automatically monitored and if additional resources are required, additional server pod replicas are created. Once the load decreases, these additionally created server pod replicas are removed.&#x20;

Access the *Autoscale* setting through the **User Portal → Project → Selected Instance → Infrastructure Management → Autoscale**. Then, enable or disable the switch.

<figure><img src="/files/DojJ5iNNXkOWHiTkSWkG" alt=""><figcaption></figcaption></figure>

Autoscaling is enabled by default for your first instance, and disabled for each of the subsequent instances you create in your account.

{% hint style="info" %}
**Note**: Autoscaling does not apply to stateful services, such as MySQL.&#x20;

Therefore, when your store has a planned **marketing campaign**, please inform <hello@readymage.com> in advance and provide the **estimated traffic**, so these resources can be checked and manually adequate if necessary.\
After the campaign is over, the resources should be reduced back.
{% endhint %}

For more information, refer to [Autoscaling](/faq/autoscaling).


# Sleep Mode

Use the sleep mode to save costs for instances when they are not needed. This is especially useful for development and testing instances.

Access the Sleep Mode setting through **User Portal → Project → Selected Instance → Operations → Sleep Mode**.

<figure><img src="/files/5IGfXIEVuztrgQrdYuin" alt=""><figcaption></figcaption></figure>

Press the **Put to sleep** button to have your instance sleep.

<figure><img src="/files/6XefS0IDTZpd2Z7VjKrW" alt=""><figcaption></figcaption></figure>

### Inactivity-based sleep mode

If turned on the instance will be put in low resource consumption mode after 2 hours of inactivity. Opening the front-end or admin panel will wake up the instance in 1-3 minutes. If turned off, the instance will always be active.

<figure><img src="/files/wAYJKP3Im8ZO2C8pxTNj" alt=""><figcaption></figcaption></figure>

### Scheduled sleep mode

Allows you to configure specific time intervals for each weekday when the instance should be put to sleep. During the specified time periods, your instance **won't be available**.

Specify your timezone, choose the intervals, and enable the switch.

Leave from 00:00 to 00:00 if you don't want to activate sleep mode for a specific day.

<figure><img src="/files/OCmia1LjctD90egi95MM" alt=""><figcaption></figcaption></figure>


# Manage Services

The Manage Services tab offers a control over the individual services of the instance.&#x20;

To access it, navigate to **User Portal → Project → Selected Instance → Configuration → Services.**

The following actions can be done to each service individually:

* Start
* Stop
* Restart

<figure><img src="/files/4eTvqxRIVdBsVWu6nlHG" alt=""><figcaption></figcaption></figure>

### Cron Jobs Graceful Termination Management

Manage Services tab offers control over cron jobs to allow for *Graceful Termination*. Graceful Termination allows the currently scheduled, running jobs to execute successfully while stopping the scheduling of new jobs. This comes in handy if the running jobs are critical and their execution should be resumed while the need to stop future cron jobs is present as well.

It's important to note that to able to use the Graceful Termination feature, the SSH service needs to be running.


# Historical Resource Usage

The historical resource usage graphs provide transparency regarding resource usage for environments. This can help to track down events and bottlenecks in applications/services.

The metrics can be found in **User Portal → Project → Selected Instance → Infrastructure Management → Historical Resource Usage.**

<figure><img src="/files/M5Lw3hMfusoywChPN07Q" alt=""><figcaption></figcaption></figure>

The precision is different based on the selected period:

* 30 mins period will show data with 1-minute precision
* 24 hours - 5-minute precision
* 7 days - 30-minute precision
* 30 days - 90-minute precision

{% hint style="warning" %}
Due to technical limitations, displayed metric accuracy for 30 days is currently lower than other time ranges.

If you need more accurate metrics for the selected time range don't hesitate to get in touch with our support team.
{% endhint %}


# Node.js version

{% hint style="info" %}
We are using **Node 20** with **NPM 10** as the default Node version. If you need a different Node and NPM version, update your code repository according to this documentation.
{% endhint %}

ReadyMage provides support for running all LTS releases of Node.js, starting with Node 14: **Node 14** with **NPM 6**, **Node 16** with **NPM 8**, **Node 18** with **NPM 10**, **Node 20** with **NPM 10,** and **Node 22** with **NPM 10**.

Version mapping looks like this:

| Node version | NPM version | Yarn version |
| ------------ | ----------- | ------------ |
| 14           | 6           | 1            |
| 16           | 8           | 1            |
| 18           | 10          | 1            |
| 20           | 10          | 1            |
| 22           | 10          | 1            |

You can select the **Node** and **NPM** versions according to your Magento theme installation and build requirements using one of the following methods:

## package.json

By adjusting the **package.json** file **engines.node** field, you can specify the Node version that is required to be used for your theme dependency installation and command execution.

{% code title="package.json" %}

```json
{
    "name": "theme-name",
    "version": "0.0.1",
    "dependencies": {
        // Insert your dependencies here
    },
    "scripts": {
        // Insert your scripts here
    },
    "engines": {
        "node": "^20.0.0"  // Supports any version of Node 20.x.x
        "node": ">=16.0.0 <=18.0.0"  // Supports Node versions from 16.x.x to 18.0.0
        // The range will prioritize the lowest available version within the specified range
    }
}
```

{% endcode %}

General documentation for the **engines** field is available [here](https://docs.npmjs.com/cli/v10/configuring-npm/package-json#engines).

## .node-version

{% hint style="warning" %}
We don't recommend using this method of selecting the Node.js version unless you know what you are doing.
{% endhint %}

{% code title="example .node-version" %}

```
v22.3.0
```

{% endcode %}

The `.node-version` file should be located in the same directory as `package.json`.

`.node-version` file syntax allows you to specify the exact version that you need.

```
v22.3.0  // Functional, but non-LTS releases are not recommended.
v22.3    // Functional.
22       // Functional.
20       // Recommended and fully functional.
```

The advantage of this approach is that you can install any version you want. Not just versions from a provided list. Using a non-LTS version is not recommended.

## Priority

Node version defined in `.node-version` has a higher priority than the one defined in `package.json` file `engines.node` field.


# Store access

Magento 2 admin panel and ScandiPWA frontend access information.

{% hint style="info" %}
It is highly advised to change your Admin Panel user password. The User Portal will NOT reflect your changed password. Also, if you migrate a database that has a different admin password, it will not be reflected in the User Portal - Magento Details.
{% endhint %}

1. Log into your User Portal account following these [instructions](/user-portal/user-portal-access).
2. Navigate to **Project → Selected Instance →  Overview.**
3. Open the **Details** tab in the Overview section.
4. You will find your Store URL which leads to your website frontend and Admin Panel URL as well as the User and Password which gives you access to Magento Admin Panel.

<figure><img src="/files/MCdUAzppurKAKOnI0sOU" alt=""><figcaption></figcaption></figure>

Learn available customization options for your website that can be done through Admin Panel [here](https://manual.scandipwa.com/).

To make customizations on the source code level, follow these instructions:

{% content-ref url="/pages/-MVHFGHdeRMq\_K7FMnhU" %}
[Code customization and local setup](/project-development/code-customization-and-local-setup)
{% endcontent-ref %}

To install extensions follow these instructions:

{% content-ref url="/pages/-MVHFNuDs9HMqYZWZW9I" %}
[Extension installation](/project-development/extension-installation)
{% endcontent-ref %}


# Creating a Production Environment

ReadyMage provides complete setup of infrastructure with Magento 2 and ScandiPWA installed and configured in 15 minutes.

## Environment

In ReadyMage we use the term "Environment" to refer to an infrastructure instance where the website with all its services is deployed and used for its intended purposes.

ReadyMage accounts can have one or multiple environments and each of them can be used for different purposes. You start out with a single environment and can create additional ones on demand.

The most common is to have 3 environments - production, staging, and development.

* A production environment is used to host the version of the website for commercial daily operations.
* A staging environment is used to test changes made for the website before deploying them to the production environment.
* A development environment is used to test individual change to ensure that it works after it has been developed locally.

## How to Create a Production Environment

The production environment is created by default on account creation by making a subscription -  <https://readymage.com/subscribe/>

In 15 minutes after subscribing, you will receive an email with Magento access information and instructions on how to access the User Portal.

{% hint style="info" %}
Existing ScandiPWA projects can be fully migrated to ReadyMage for free.
{% endhint %}

## Infrastructure

{% hint style="info" %}
Environments by default are created with resource configuration listed [here](https://readymage.com/subscribe/). You can request a custom resource configuration by writing to <hello@readymage.com>.
{% endhint %}

The infrastructure consists of a dedicated server for each of these individual services:

![ReadyMage Environment Infrastructure Topology](/files/-MVMN4xKOu_Wvkv4T-nF)

Magento 2 and the Frontend will be already set up in your environment. The production environment source code will be available through the GitHub project and it will be on the `production` branch.

Learn how to make code customizations, local setup, and deployments by following [the instructions](/project-development/code-customization-and-local-setup).

## Additional Environments

You can create additional environments for staging and development by following the instructions [here](/project-development/additional-environments).


# Additional Environments

Create a *development* and *staging* environment for your project to test and demo changes before releasing them in production.

You can select your instance in the User Portal by using the instance drop-down.&#x20;

<figure><img src="/files/RWIxsyLQWg6qyxvK4rSU" alt=""><figcaption></figcaption></figure>

### Important to know!

1. Additional environments are created using the default resource allocation. If you would like to set different resources please contact <hello@readymage.com>.
2. The source code will be managed through the same repository that your production environment is managed. Each environment has its own branch within the GitHub project.
3. The additional environment branches will contain a copy of the current master branch code.
4. Media and Database are NOT copied to additional instances from the production environment automatically. A default database and media will be set initially, which may result in your website not working at first due to database data/media and source code inconsistencies. You need to migrate the database and media to an additional environment following these [instructions](/project-development/database-and-media-migration).
5. Auth.json is copied over to additional environments from the production environment on creation.

### Create your additional environment

You can create additional environments, such as Staging and Development environments, through the User Portal.&#x20;

{% hint style="warning" %}
Note that you must be an Owner or Admin to create environments.
{% endhint %}

<figure><img src="/files/Gqjh7aeWYjA7Ku26XWd4" alt=""><figcaption></figcaption></figure>

1. Navigate to Project Configuration page - [Project Settings](https://app.gitbook.com/o/-MJEF8d2zq5zB16UWyvQ/s/-MKew-XtJKAPabdeTxXg/~/edit/~/changes/442/project-management/project-settings)
2. Click the ***New Instance*** button.
3. Select the **Project** where you want to create the new instance.
4. Under **Existing Project**, select the project name and click **Next**.&#x20;

<figure><img src="/files/wM4qJITNkXbWsEWz1e6L" alt=""><figcaption></figcaption></figure>

5. Template is automatically inherited from the main instance. Click **Next** to continue.
6. Enter the **Instance Name** and **Instance Tag**, then select the desired **Magento Mode**.
7. Select the region where the instance will be deployed.

<figure><img src="/files/M0ZfukMvgbiGu5Fz4Xo7" alt=""><figcaption></figcaption></figure>

8. Click **Next** to proceed to the **Review** step.
9. Carefully review the instance configuration, then click **Create Instance** to start the provisioning process.

<figure><img src="/files/b5zAdRrGs3T8DIDcEqWq" alt=""><figcaption></figcaption></figure>

10. The new instance will be ready in approximately **15 minutes**. You can monitor the provisioning progress from the instance overview page.

{% hint style="info" %}
An additional instance is created using the production instance source code. Database and media are the default so you will need to migrate yours from the production environment to replicate it.
{% endhint %}

During instance creation you will see instance creation progress.

<figure><img src="/files/JGm1vjxkqMjJlvrNhWLr" alt=""><figcaption></figcaption></figure>

This progress will refresh automatically and after the instance is created you will be redirected to the [Magento Details](/application-management/access-details) of that instance.


# ScandiPWA, PWA Studio, Hyva, or Luma

When you sign up, you receive access to a store with Magento 2 + ScandiPWA.

If you'd like to switch to PWA Studio, Hyva, or Luma, here’s a step-by-step:

1. Do the local setup normally with your ScandiPWA store.
2. Change the code to PWA Studio, Hyva or Luma following [this guide](/project-development/code-customization-and-local-setup).
3. Configure `readymage.yaml` file to PWA Studio (or other) following [this guide](/application-management/deploy-changes-to-your-instance/pipeline-configuration-file).
4. For PWA Studio or Luma, add <https://github.com/magento/magento2-upward-connector> as it’s done in Magento 2 Cloud: <https://developer.adobe.com/commerce/pwa-studio/tutorials/production-deployment/adobe-commerce/#add-required-adobe-commerce-extensions>
5. Deploy these changes to your GitHub.


# Project Migration to ReadyMage

If you intend on migrating your ScandiPWA project to ReadyMage, we invite you to follow this **checklist**:

{% embed url="<https://docs.google.com/spreadsheets/d/1Bh0mSbnGyCeqNTO6sNM87DlbBdKhsccK3-dh6EVY1Hs/edit?usp=sharing>" %}

The same checklist can be used if you intend on migrating a project running on PWA Studio, Hyva or Luma. In this case, some additional steps are required:

{% content-ref url="/pages/0Fcxy3SP8Py8aoWDVCrH" %}
[ScandiPWA, PWA Studio, Hyva, or Luma](/project-development/scandipwa-pwa-studio-hyva-or-luma)
{% endcontent-ref %}


# SSH Access for Magento CLI, database and media

Run Magento CLI commands, create database and media dumps or replace database or media.

## Generating your SSH Key and Getting Public Key

### Linux

{% hint style="info" %}
**xclip** must be installed to generate SSH keys on Linux. Check if you have it installed by running the following command in the terminal:

`where xclip`
{% endhint %}

For version >= Ubuntu 20.04

`which clip`

If the output is nothing then you don't have it installed. Install it by entering the following command in the terminal:\
`sudo apt install xclip`

1. Generate the SSH key by entering the following command in the Terminal window:\
   `ssh-keygen -t rsa`
2. When you execute this command, the ssh-keygen utility prompts you to indicate where to store the key.
3. Type in a passphrase. You can also hit the ENTER key to accept the default (no passphrase).
4. After you confirm the passphrase the system generates the key pair.
5. Your private key is saved to the *id\_rsa* file in the .ssh directory. Do not share it with anyone.
6. Your public key is saved to the *id\_rsa.pub* file. You can copy it by running this: `xsel -b < ~/.ssh/id_rsa.pub`

### Mac

1. Generate the SSH key by entering the following command in the Terminal window:\
   `ssh-keygen -t rsa`
2. When you execute this command, the ssh-keygen utility prompts you to indicate where to store the key.
3. Type in a passphrase. You can also hit the ENTER key to accept the default (no passphrase).
4. After you confirm the passphrase the system generates the key pair.
5. Your private key is saved to the id\_rsa file in the .ssh directory. Do not share it with anyone.
6. Your public key is saved to the id\_rsa.pub file. You can copy it by running this: `pbcopy < ~/.ssh/id_rsa.pub`

### Windows

Follow these [instructions](https://phoenixnap.com/kb/generate-ssh-key-windows-10).

## Add SSH User

{% hint style="danger" %}
**SSH access doesn't allow you to make code-level changes including enabling or disabling extensions.** Perform code changes by following instructions [here](/project-development/code-customization-and-local-setup) and enable/disable extensions by following instructions [here](/project-development/extension-installation).
{% endhint %}

1. Log into your User Portal account by following [these instructions](https://help.readymage.com/user-portal/user-portal-access). &#x20;
2. In the instance drop-down, select the instance for which you would like to create SSH access.&#x20;
3. If you plan to use a single SSH key for multiple instances, [follow this guide](https://help.readymage.com/application-management/ssh-access#using-account-ssh-key-integration-preferred-way).
4. To add SSH access for a single instance, [follow this guide](https://help.readymage.com/application-management/ssh-access#using-ssh-key).<br>

## Remove SSH User

1. Log into your User Portal account by following [these instructions](https://help.readymage.com/user-portal/user-portal-access).&#x20;
2. In the instance drop-down, select the instance from which you would like to remove SSH access.
3. Open the `SSH Access` section.&#x20;
4. Click the red delete button next to the username to remove access.

## Connect to SSH using terminal

{% hint style="info" %}
If you are not using Terminal to connect to SSH then you might require to enter:\
Host: *ssh.ireland.eu.i.readymage.com* (EU Ireland region)\
&#x20;         *ssh.stockholm.eu.i.readymage.com* (EU Stockholm region)\
&#x20;         *ssh.ohio.us.i.readymage.com* (USA Ohio region)\
&#x20;         *ssh.central.ca.i.readymage.com* (Canada Central region)\
&#x20;         *ssh.central.me.i.readymage.com* (Middle East UAE region)\
&#x20;         *ssh.sydney.ap.i.readymage.com* (Asia Pacific Sydney region)\
Port: *22*
{% endhint %}

1. Log into your User Portal account by following the instructions [here](/user-portal/user-portal-access).
2. Select the instance you would like to SSH connect to.
3. Open the SSH Access tab under the Application Management section.
4. Press copy next to your Username to copy the command.
5. Paste the command into Terminal and hit enter.

## SSH Usage

{% hint style="danger" %}
**SSH access doesn't allow you to make code-level changes including enabling or disabling extensions.** Perform code changes by following instructions [here](/project-development/code-customization-and-local-setup) and enable/disable extensions by following instructions [here](/project-development/extension-installation).
{% endhint %}

### Magento CLI

The list of Magento CLI commands can be found [here](https://devdocs.magento.com/guides/v2.4/reference/cli/magento.html).

### MySQL CLI

Instructions to create a database dump, download the database dump locally, and replace the database on your instance can be found [here](/project-development/database-and-media-migration).

### Media management

Instructions to create download media locally or replace media on your instance can be found [here](/project-development/database-and-media-migration).

### Additional tools

File compressing tools:

* gzip
* tar
* unzip
* zcat
* zip
* dar

Other useful tools:

* curl
* git
* grep
* head
* jq
* ping
* pv
* tail
* tmux
* wget


# Code customization and local setup

You have full access to project source code through GitHub.

## Access your GitHub repository

{% hint style="warning" %}
Code changes can only be done by making commits to your GitHub repository. It is not possible to make code changes through SSH or SFTP.
{% endhint %}

{% hint style="info" %}
All your environment source code is managed in a single GitHub repository.  Each environment has its own branch.
{% endhint %}

1. Log into your User Portal account by following the instructions [here](/user-portal/user-portal-access).
2. Select the instance you would like to know access details for in the instance drop-down.
3. Open the [GitHub Management](/application-management/github-repository-and-user-management) tab in the Application Management section.
4. Here you will find the URL to your project GitHub repository and the branch name where the source code for the selected instance is managed.

{% hint style="info" %}
Only GitHub users added to the [GitHub Management](/application-management/github-repository-and-user-management) tab can access, clone, and make changes to the repository. You can select the access level of the user - Write, Read, or Triage.
{% endhint %}

1. Add a user by clicking Add User button in the GitHub Management tab in the Application Management section.
2. Enter the existing Git username and a select role that will control the access level of the user:<br>

   **Write**: Recommended for contributors who actively push code changes to your project\
   **Read**: Recommended for non-code contributors who want to view or discuss your project

   **Triage**: Recommended for contributors who need to proactively manage issues and pull requests without writing access\
   \
   If you plan to make code changes select the Write role.<br>
3. Click Add User.

## Set up Git locally

{% hint style="info" %}
You must have Git set up locally to perform the local setup.
{% endhint %}

1. Go to the directory where you will perform the local setup.
2. Run the following commands:\
   `git init`

   `git config user.name “YOUR-GITHUB-USERNAME”`

   `git config user.email “YOUR-EMAIL-ADDRESS”`

   `ssh-keygen -t rsa -C "YOUR-EMAIL-ADDRESS"`
3. Enter the file name in which to save the generated key.
4. Copy the content from the generated file with .pub type and save it in your GitHub profile following [these instructions](https://docs.github.com/en/github/authenticating-to-github/adding-a-new-ssh-key-to-your-github-account).

## Local setup

Local setup is supported by Linux and Mac operating systems.

{% hint style="warning" %}
**Important!** You must use your project GitHub repository when following the instructions.
{% endhint %}

### Installing prerequisites

1. Make sure that you have Node.js with a version higher or equal to 12.20 installed on your local development machine. You can check it by running this command from the terminal: `node -v`
2. Install the following [prerequisites](https://docs.create-magento-app.com/getting-started/prerequisites).

### Cloning repository

1. Clone project from your ReadyMage GitHub repository, for example:\
   `git clone git@github.com:scandipwacloud/readymage-help-demo-1119750197.git`\
   \
   **IMPORTANT!** Make sure to clone the repository to an empty directory path.

### How to set ScandiPWA locally

1. Open a terminal and navigate to cloned repository folde&#x72;**: `cd scandipwa`**
2. Run command `npm install`  and wait for this process to finish.
3. Run command `BUILD_MODE=magento npm run start`. Wait for this process to finish.

### Setting up Magento 2 locally and connecting it with ScandiPWA

1. Open a new terminal window and navigate to the cloned repository folder.
2. Run command `npm install` Wait for this process to finish.
3. Run command `npm i @scandipwa/magento-scripts@latest` Wait for this process to finish.
4. Run command `npm run start`
5. Run commands:\
   `npm run cli`\
   `magento in:rei`\
   `magento c:c`

You should now have URLs given in the terminal using which you can access Frontend and Admin Panel.

Import environment database and media in your local setup by following these instructions:

{% content-ref url="/pages/-MVHFaqQlaXr6gJWLn3o" %}
[Database and media migration](/project-development/database-and-media-migration)
{% endcontent-ref %}

### **Known Issues and Solutions**

**fileinfo extension not available.**\
Follow this [guide](https://docs.create-magento-app.com/usage-guide/configuring-php#installing-php-extensions) to install the missing extension.

Add fileinfo to you cma.js file like this:

```
configuration: {
  extensions: {
    fileinfo: {}
  }
}
```

Run `npm start` command.

## Making code changes

{% hint style="info" %}
Code changes can only be done by making commits to your GitHub repository. It is not possible to make code changes through SSH or SFTP.
{% endhint %}

{% hint style="warning" %}
Git must be installed on your local machine and you must have a Git account created. Follow these [instructions](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) to install Git.
{% endhint %}

1. Once the local setup is done you can make changes to your project files. Learn more on how to develop the ScandiPWA theme [here](https://docs.scandipwa.com/).
2. Before making changes make sure to switch to the specific environment branch you want to make changes to by running the following commands.\
   \
   Switch to your environment branch (replace `master` with branch name you want to make changes to):\
   `git checkout master`\
   Pull the latest code from the GitHub repository:\
   `git pull`
3. When you are happy with your changes locally you must push them to your environment branch using the following instructions:

To add all changes to your commit:

```
git add .
```

To add specific files to your commit you need to specify a path to it, for example,

```
git add app/etc/config.php
```

Commit your changes (replace Commit Message description for your changes):

```
git commit -m "Commit Message"
```

Push your changes to GitHub:

```
git push
```

4\. After you push your changes to GitHub they will be deployed automatically to your environment. Automatic deployments can be disabled and manual deployments can be used instead if you don't want to deploy on every code push. Follow the instructions [here](/project-development/code-customization-and-local-setup#deployments) to do it.\
5\. If you see a blank page on your frontend after deployment run the Magento cache clear command through SSH:

```
bin/magento c:c
```

{% content-ref url="/pages/-MVHFBi3IpTnJ3seuJjd" %}
[SSH Access for Magento CLI, database and media](/project-development/ssh-access-for-magento-cli-database-and-media)
{% endcontent-ref %}

Follow these instructions to install extensions:

{% content-ref url="/pages/-MVHFNuDs9HMqYZWZW9I" %}
[Extension installation](/project-development/extension-installation)
{% endcontent-ref %}

## Deployments

ReadyMage provides 2 ways to deploy code changes to your environment - automatic and manual.

### **Automatic deployments**

Automatic deployments are enabled by default. Code changes are deployed automatically to your environment on every push GitHub. You can disable or enable deployments by following these instructions:

1. Log into your User Portal account following these [instructions](/user-portal/user-portal-access).
2. Select the instance you would like to know access details for in the instance drop-down.
3. Open the Deployments tab in the Application Management section.
4. Use the Automatic Deployments toggle to enable or disable them.

### Manual deployments

If you have disabled automatic deployments only way to deploy code changes is by initiating manual deployment.

1. Log into your User Portal account following these [instructions](/user-portal/user-portal-access).
2. Select the instance you would like to know access details for in the instance drop-down.
3. Open the Deployments tab in the Application Management section.
4. Click the Start Deployment button.
5. You can check your deployment status in the Deployments tab.


# Extension installation

## Installation instructions

{% hint style="info" %}
Front-end extensions require to be ScandiPWA theme compatible to work on ReadyMage. Admin Panel extensions will work out of the box if the Magento version is supported.
{% endhint %}

Extensions have to first be installed on the project locally and then pushed to your GitHub repository to be available on the environment. Project local setup instructions:

{% content-ref url="/pages/-MVHFGHdeRMq\_K7FMnhU" %}
[Code customization and local setup](/project-development/code-customization-and-local-setup)
{% endcontent-ref %}

Once the local setup is done you can follow extension installation instructions [here](https://docs.scandipwa.com/developing-with-scandi/extensions/installing-an-extension).

When you have installed the extension locally [push the code to your GitHub repository and redeploy your instance](https://docs.scandipwa.com/stack/extensions/installing-an-extension).

## ScandiPWA Extension Marketplace

Find extensions with ScandiPWA compability on [ScandiPWA Marketplace](https://marketplace.scandipwa.com/).


# Add translations (switch locale)

## Step-by-step guide

{% hint style="info" %}
Local setup is required to add translations.
{% endhint %}

{% content-ref url="/pages/-MVHFGHdeRMq\_K7FMnhU" %}
[Code customization and local setup](/project-development/code-customization-and-local-setup)
{% endcontent-ref %}

1. Ensure that you are running `"@scandipwa/scandipwa": "x.x.x"`. You can check within `scandipwa/package.json` file. &#x20;
2. Set up the project locally by following these [instructions](https://help.readymage.com/faq/know-how-for-developers#how-can-i-set-up-the-project-locally-and-start-the-development).
3. Navigate to `scandipwa` folder within your source code folder.
4. Run command from the terminal `npm i @scandipwa/webpack-i18n-runtime`
5. Remove hardcoded locale from `app/etc/config.php` file by deleting the following lines of code:\
   `'general' => [`

   &#x20;   `'locale' => [`

   &#x20;        `'code' => 'en_US'`

   &#x20;    `]`

   `],`
6. Open `scandipwa/package.json` file.
7. Add the locales you wish to have and `@scandipwa/webpack-i18n-runtime` extension, for example: \
   `"scandipwa": {`

   &#x20;       `"type": "theme",`

   &#x20;       `"locales": {`

   &#x20;           `"en_US": true,`

   &#x20;           `"fr_FR": true`

   &#x20;       `},`

   &#x20;       `"parentTheme": "@scandipwa/scandipwa",`

   &#x20;       `"extensions": {`

   &#x20;           `"@scandipwa/webpack-i18n-runtime": true`

   &#x20;       `}`

   &#x20;   `},`
8. Navigate to scandipwa folder and build your ScandiPWA theme to create added translation files by running the following command: `BUILD_MODE=magento npm run start`
9. Add your translations within generated locale file which is located in scandipwa/i18n folder.
10. Navigate to the repository root folder and run: `npm run start`
11. In Magento admin go to Stores > Configuration > General > General > Locale Options.
12. Switch to your store's scope and change the Locale to the one you created.
13. Clear cache by going to System > Tools > Cache Management and pressing Flush Cache Storage and Flush Magento Cache.
14. Open Frontend to ensure that translations are active.
15. Push all the changes to your repository.
16. Once the changes are deployed, enable access instance using SSH following these [instructions](/application-management/ssh-access).
17. Run the following command to enable developer mode: `magento deploy:mode:set developer`
18. Change the locale for the store view through your instance admin panel.
19. Clear cache by going to System > Tools > Cache Management and pressing Flush Cache Storage and Flush Magento Cache.
20. Run the following commands from your SSH:\
    `magento in:rei`\
    `magento c:c`\
    `magento deploy:mode:set production`


# Existing ScandiPWA Project Code Migration

## Steps to migrate ScandiPWA version 4+ projects

1. Ensure that your existing project `scandipwa` theme folder is named **scandipwa**.
2. Clone the instance repository following the instruction [here](/project-development/code-customization-and-local-setup#cloning-repository).
3. Replace the following folders/files in the cloned repository root folder from your project:\
   `app/etc/config.php`\
   `app/code`\
   `scandipwa`\
   `composer.json`\
   `composer.lock`\
   `package.json`
4. Add scopes configuration to  app/etc/config.php file following [Magento reference example](https://devdocs.magento.com/guides/v2.4/config-guide/prod/config-reference-configphp.html).
5. Perform [local setup](/project-development/code-customization-and-local-setup#local-setup).
6. [Push the code changes](/project-development/code-customization-and-local-setup#making-code-changes) to ReadyMage.
7. Perform database migration.
8. Perform media migration.

## Migrating earlier ScandiPWA version projects

Contact [ReadyMage support](https://help.readymage.com/faq/general#how-can-i-contact-customer-support).


# Database and media migration

## Migrate ReadyMage database to your local setup

1. Setup SSH access following these [instructions](/project-development/ssh-access-for-magento-cli-database-and-media).
2. Connect to SSH through your terminal.
3. Run the following commands to create a database dump zip file on the ReadyMage server: `mysqldump magento --single-transaction --no-tablespaces | zip dump.sql.gz -`
4. Exit SSH by running command `exit`
5. Navigate to the directory where you want to download the database dump on your local machine, for example, Desktop: `cd desktop`
6. Run commands `scp {SSH USER}:/home/magento/dump.sql.gz .`\
   Make sure to replace {SSH USER} part with your ReadyMage SSH username, for example,&#x20;

   `scp store-pwruv-shj-1611224333-user@prod.ssh.us.i.readymage.com:/home/magento/dump.sql.gz .`
7. Unarchive the dump locally.
8. Rename the unarchived file to `dump.sql`
9. Make sure that your local Magento application is running and run the following command to import database dump (./dump.sql should be replaced with the path your dump file)\
   `npm run import-db ./dump.sql`\
   If the import-db command doesn't exist, check known issues below.
10. Navigate to your project repository using terminal and run the following commands:\
    `npm run stop`\
    `npm run start`\
    `npm run cli`\
    `magento indexer:reindex`\
    `magento cache:clean`
11. Create a new admin user to be used on your local setup by running this command `magento admin:user:create`

### Know Issues

**Import-db not available**

If the import-db command is not available add the following line to the package.json file located in the root folder of the cloned repository:

```
"import-db": "magento-scripts import-db"
```

Your package.json file scripts variable should have the import-db add&#x20;

```
"scripts": {
        "import-db": "magento-scripts import-db",
        "start": "magento-scripts start",
        "stop": "magento-scripts stop",
        "cli": "magento-scripts cli",
        "logs": "magento-scripts logs",
        "link": "magento-scripts link",
        "status": "magento-scripts status",
        "exec": "magento-scripts exec"
    },
```

## Migrate local database to ReadyMage

1. Navigate to your project repository using terminal and run the following command: `npm run status`
2. Copy the name of the MySQL container, for example,  `readymage-mystore-pwruv-shj-1611224333-master_mysql`
3. Create database dump by running the following command: `docker exec {MYSQL CONTAINER NAME} mysqldump magento --single-transaction --no-tablespaces -u magento -pmagento --result-file=/tmp/dump.sql`

   Replace {MYSQL CONTAINER NAME} by the container name you copied in step 2.
4. Download the dump to your Desktop by running the following command:\
   `docker cp {MYSQL CONTAINER NAME}:/tmp/dump.sql ~/Desktop/dump.sql`
5. Before importing the database dump to your ReadyMage instance open the database dump and change all the mentions of  `utf8mb4_general_ci` to `utf8mb4_0900_ai_ci`
6. Setup SSH access following these [instructions](/application-management/ssh-access). You don't have to connect to it.
7. Move your database to the ReadyMage server by running the following command from your terminal:  `scp {LOCAL PATH TO YOUR DUMP} {SSH USER}:/home/magento/dump.sql`\
   Replace `{LOCAL PATH TO YOUR DUMP}` with the path to your database dump and `{SSH USER}` with your SSH username, for example,&#x20;

   `scp ~/Desktop/dump.sql store-pwruv-shj-1611224333-user@prod.ssh.us.i.readymage.com:/home/magento/dump.sql`
8. Drop the database `DROP DATABASE magento; CREATE DATABASE magento;`
9. Connect to SSH and run the following command: `mysql magento < dump.sql`
10. Connect to mysql by running `mysql` command in terminal.
11. Run the following commands (replace **{STORE URL}** with your instance store URL):\
    `use magento`

    `UPDATE core_config_data SET value="elasticsearch" where path="catalog/search/elasticsearch7_server_hostname";`&#x20;
12. `UPDATE core_config_data SET value="9200" where path="catalog/search/elasticsearch7_server_port";`

    `UPDATE core_config_data SET value="2" where path="system/full_page_cache/caching_application";`

    `UPDATE core_config_data SET value="http://{STORE URL}/" where path="web/unsecure/base_url";`

    `UPDATE core_config_data SET value="https://{STORE URL}/" where path="web/secure/base_url";`

    `UPDATE core_config_data SET value="1" where path="web/secure/use_in_frontend";`

    `UPDATE core_config_data SET value="1" where path="web/secure/use_in_adminhtml";`\
    `UPDATE core_config_data SET value="{STORE URL}" where path="web/cookie/cookie_domain";`

    `exit`<br>
13. Access SSH and run the following commands:\
    `magento indexer:reindex`\
    `magento cache:clean`

### Known Issues

* **Error: Catalog Search index exception: Could not ping search engine: No alive nodes found in your cluster**\
  Update elasticsearch port to 9200 in your instance database core config table. Follow instructions [here](<https://devdocs.magento.com/guides/v2.4/config-guide/elasticsearch/configure-magento.html >).

* **Error: ERROR 1227 (42000) at line XX: Access denied; you need (at least one of) the SUPER or SET\_USER\_ID privilege(s) for this operation** \
  Please check the reported line. If `DEFINER` is specified, please remove it.

  <div data-gb-custom-block data-tag="hint" data-style="info" class="hint hint-info"><p>To remove it from the entire SQL dump file (<code>DATA-DUMP.sql</code>), you can use the following <code>sed</code> command:<br><code>sed 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' DATA-DUMP.sql > DATA-DUMP--cleared.sql</code></p></div>

## Migrate ReadyMage media to your local setup

1. Setup SSH access following these [instructions](/application-management/ssh-access).
2. Run command to download Media Content to your desktop (change the \~/Desktop/media path to your path where you want to dump the media):  `rsync -azh --partial --append {SSH USER}:/home/magento/media/ ~/media`\
   Replace `{SSH USER}` with your SSH username, for example, \
   `rsync -azP store-pwruv-shj-1611224333-user@prod.ssh.us.i.readymage.com:/home/magento/media/ ./Desktop/`
3. Move downloaded media content to your repository `pub/media` folder.
4. Navigate to the repository in the terminal and run the following commands:\
   `npm run cli`\
   `magento indexer:reindex`\
   `magento cache:clean`

## Migrate local media to ReadyMage

1. Setup SSH access following these [instructions](/application-management/ssh-access).
2. Navigate to your repository `pub` folder in terminal and run the command: `rsync -azP media/ {SSH USER}:/home/magento/media/`

   Replace `{SSH USER}` with your SSH username, for example, \
   `rsync -azh --partial --append --chmod=Du=rwx,Dg=rwx,Do=rx,Fu=rw,Fg=rw,Fo=r media/ store-pwruv-shj-1611224333-user@prod.ssh.us.i.readymage.com:/home/magento/media/`
3. Connect to SSH and run the following commands:\
   `magento indexer:reindex`\
   `magento cache:clean`
4. Restart Varnish from `Infrastructure Management > Manage Services`.


# Redirect setup

## Setup 301 redirects

301 redirects are set up using [default Magento 2 URL rewrite features](https://docs.magento.com/user-guide/marketing/url-rewrite.html).

## Setup server-side redirects

Server-side redirects are possible to set up on ReadyMage. In order to set them up contact the ReadyMage support team at <admin@readymage.com>.

&#x20;


# Connect CDN and WebP optimization

Connect CDN for free and get unlimited WebP image optimization for 20$ per month. WebP compression helps to make your store faster reducing image size up to 50%. Visit <https://www.cloudflare.com/> for more details.

{% hint style="info" %}
Throughout the guide replace "yourdomain.com" with the domain you are connecting to Cloudflare.
{% endhint %}

## Setup for a domain hosted on Cloudflare

1. Open a [Cloudflare](https://www.cloudflare.com/) account and attach billing information
2. [Migrate DNS records to Cloudflare ](https://support.cloudflare.com/hc/en-us/articles/200168856-Importing-and-exporting-DNS-records)if the domain is not already there.
3. [Switch NS records](https://support.cloudflare.com/hc/en-us/articles/205195708-Changing-your-domain-nameservers-to-Cloudflare) in the register if the domain is not already there.
4. Point [www.yourdomain.com](http://www.yourdomain.com) CNAME (proxy -> Yes) to
   * `lb.ireland.eu.i.readymage.com` (for instance created in EU Ireland region)&#x20;
   * `lb.ohio.us.i.readymage.com` (for instance created in US Ohio region),&#x20;
   * `lb.stockholm.eu.i.readymage.com` (for instance created in Stockholm region),&#x20;
   * `lb.central.ca.i.readymage.com` (for instance created in Canada Central region),&#x20;
   * `lb.central.me.i.readymage.com` (for instance created in Middle East UAE region),&#x20;
   * `lb.sydney.ap.i.readymage.com` (for instance created in Asia Pacific Sydney region)
5. Point yourdomain.com CNAME (proxy -> Yes) to&#x20;
   * `lb.ireland.eu.i.readymage.com` (for instance created in EU Ireland region)
   * `lb.ohio.us.i.readymage.com` (for instance created in US Ohio region),&#x20;
   * `lb.stockholm.eu.i.readymage.com` (for instance created in Stockholm region),&#x20;
   * `lb.central.ca.i.readymage.com` (for instance created in Canada Central region),
   * `lb.central.me.i.readymage.com` (for instance created in Middle East UAE region),&#x20;
   * `lb.sydney.ap.i.readymage.com` (for instance created in Asia Pacific Sydney region)
6. Adjust Cloudflare settings according to recommended settings.

## Setup for a domain hosted outside of Cloudflare

Cloudflare setup if you host your domain outside of Cloudflare and can't migrate NS records:

1. Open a [Cloudflare](https://www.cloudflare.com/) account and attach billing information
2. Purchase Cloudflare Business Plan for 200$ for the specific domain.
3. Contact Cloudflare support asking to switch the account using TXT (CNAME) validation method. Cloudflare performs the switch within hours.
4. Cloudflare support will provide you with the DNS record that you need to add.
5. Add the provided DNS record to your existing DNS hosting panel and wait for Cloudflare activation.
6. In Cloudflare point [www.yourdomain.com](http://www.yourdomain.com) CNAME (proxy -> Yes) to
   * `lb.ireland.eu.i.readymage.com` (for instance created in EU Ireland region)&#x20;
   * `lb.ohio.us.i.readymage.com` (for instance created in US Ohio region),&#x20;
   * `lb.stockholm.eu.i.readymage.com` (for instance created in Stockholm region),&#x20;
   * `lb.central.ca.i.readymage.com` (for instance created in Canada Central region),&#x20;
   * `lb.central.me.i.readymage.com` (for instance created in Middle East UAE region),&#x20;
   * `lb.sydney.ap.i.readymage.com` (for instance created in Asia Pacific Sydney region)
7. In Cloudflare, point yourdomain.com CNAME (proxy -> Yes) to&#x20;
   * `lb.ireland.eu.i.readymage.com` (for instance created in EU Ireland region)
   * `lb.ohio.us.i.readymage.com` (for instance created in US Ohio region),&#x20;
   * `lb.stockholm.eu.i.readymage.com` (for instance created in Stockholm region),&#x20;
   * `lb.central.ca.i.readymage.com` (for instance created in Canada Central region),
   * `lb.central.me.i.readymage.com` (for instance created in Middle East UAE region),&#x20;
   * `lb.sydney.ap.i.readymage.com` (for instance created in Asia Pacific Sydney region)
8. In existing DNS hosting panel point: [www.yourdomain.com](http://www.yourdomain.com) CNAME [www.yourdomain.com.cdn.cloudflare.net](http://www.yourdomain.com.cdn.cloudflare.net)
9. In existing DNS hosting panel point: yourdomain.com CNAME yourdomain.com.cdn.cloudflare.net
10. Adjust Cloudflare settings according to recommended settings:

## Recommended Cloudflare settings

### SSL/TLS

#### Edge Certificates

* Always Use HTTPS → On
* HSTS
  * Enable HSTS → On
  * Max Age Header → 6 months
  * Apply HSTS policy to subdomains → Off
  * Preload → On
  * No-Sniff Header → On
* Minimum TLS Version → TLS 1.2
* Opportunistic Encryption → On
* TLS 1.3 → On
* Automatic HTTPS Rewrites → On

### Security

#### WAF → Managed rules

* Managed rules → On
* Cloudflare Managed Ruleset
  * Cloudflare Magento → On
  * Cloudflare Php → On

#### Bots → Configure Super Bot Fight Mode

* JavaScript Detections → Off (if you leave it "on", the performance will decrease slightly, but it will be possible to detect robots more accurately)

#### Settings

* Browser Integrity Check → On
* Privacy Pass Support → On

### Speed

#### Optimization

* Polish → Lossy + webP
* Auto Minify → JavaScript, CSS, HTML
* Brotli → On
* Early Hints → On
* Enhanced HTTP/2 Prioritization → On
* Mirage → On
* Rocket Loader → Off (You can try to enable it for sites that are not single-page applications \[SPA], for example, for ScandiPWA which is a SPA site it should be disabled)

### Caching

#### Configuration

* Crawler Hints → On

#### Cache Rules → Create Rule

If incoming requests match: `Custom filter expression`

When incoming requests match

* Field: `URI Path`, Operator: `Starts with`, Value: `/static`
* Field: `URI Path`, Operator: `Starts with`, Value: `/media`

﻿Cache eligibility - `Eligible for cache.`

#### Edge TTL

* Ignore cache-control header and use this TTL
  * Input time-to-live (TTL) - `1 year`
* Status code TTL
  * Scope: `Range`, From - To: `300` `403`, Duration: `2 hours`
  * Scope: `Single code`, Status code: `404`, Duration: `No cache`
  * Scope: `Range`, From: `405` `509`, Duration: `2 hours`

#### Browser TTL

* Override orign and use this TTL
  * Input time-to-live (TTL) - `2 hours`

### Network

* HTTP/2 → On
* HTTP/2 to Origin → On
* HTTP/3 (with QUIC) → On

## Exclude Magento admin from Cloudflare

In order to avoid Cloudflare becoming a bottleneck for long backend operations, you can exclude it from Cloudflare.

{% hint style="info" %}
Replace admin.yourdomain.com with your Magento 2 admin URL.
{% endhint %}

1. Set up a separate domain for your Magento 2 admin that differs from your Magento 2 front-end domain.
2. Point admin.yourdomain.com CNAME (proxy -> No) to&#x20;
   * `lb.ireland.eu.i.readymage.com` (for instance created in EU Ireland region)
   * `lb.ohio.us.i.readymage.com` (for instance created in US Ohio region),&#x20;
   * `lb.stockholm.eu.i.readymage.com` (for instance created in Stockholm region),&#x20;
   * `lb.central.ca.i.readymage.com` (for instance created in Canada Central region),
   * `lb.central.me.i.readymage.com` (for instance created in Middle East UAE region),&#x20;
   * `lb.sydney.ap.i.readymage.com` (for instance created in Asia Pacific Sydney region)


# Email setup

{% hint style="warning" %}
While your instance is under the `readymage.com` domain and you're using Magento 2's default email-sending functionality via `sendmail`, you’ll need to configure your store’s email address using a temporary subdomain of `readymage.com`. For example, you can use `info@YOUR-STORE.readymage.com`.
{% endhint %}

## Using ReadyMage SES

To use a different domain's email address with default Magento 2 email sending functionality, a domain switch is required on your instance. ReadyMage team will provide the required SES (Simple Email Service) DNS records that have to be added to your domain management panel. Follow [these instructions](/project-development/change-domain) to switch the domain.

## Using 3rd party SMTP

Alternatively, to default Magento 2 email sending functionality, you can integrate 3rd party email solutions for Magento 2.


# Changing the Domain & Multi-Store Set up

## Schedule domain switch

{% hint style="info" %}
Domain change requires ReadyMage admin assistance. Please contact <admin@readymage.com> one week in advance and we will schedule a domain change.
{% endhint %}

1. Access the User Portal following these[ instructions](/user-portal/user-portal-access).
2. Select the instance you want to change the domain for from the instance drop-down.&#x20;
3. Go to the [Domain Management](/application-management/domain-management) tab in the Application Management section.
4. Click Change domain and enter the domain you would like to switch to, for example, mystore.com
5. You will get contacted via email by the ReadyMage team to schedule the domain switch.

### SES Records for email

During the domain switch required DNS records can be set to enable the default Magento 2 SMTP email solution with your domain email addresses. Once the domain switch is requested ReadyMage team will clarify if the default Magento 2 SMTP email solution will be used and provide the required DNS records for it.

## Multi-Store Set up

With ReadyMage it is also possible to have multiple stores on a single instance.

1. Set up multiple stores in Magento admin following [Magento Guide](https://devdocs.magento.com/guides/v2.4/config-guide/multi-site/ms_websites.html).&#x20;
2. Send a support request to ReadyMage or write directly to <admin@readymage.com> that you wish to set up multiple domains for your stores. The ReadyMage team will assist you with further configuration.


# Internal service addresses

{% hint style="info" %}
These addresses are only valid from the inside of your application.
{% endhint %}

| Service       | Address              |
| ------------- | -------------------- |
| Nginx         | `nginx:80`           |
| Varnish       | `varnish:80`         |
| Elasticsearch | `elasticsearch:9200` |
| Redis         | `redis:6379`         |
| MySQL         | `mysql:3306`         |


# Kibana filters and useful CLI commands

## Service logs available in Kibana and their filter queries

### Cron

```
*.container.name : "cron"
```

### ElasticSearch

```
*.container.name : "elasticsearch"
```

### Application

```
*.container.name : "app-fe"
*.container.name : "app-be"
```

### Redis

```
*.container.name : "redis"
```

### Nginx

```
*.container.name : "nginx"
```

If you see that your logs are duplicated, then keep in mind that nginx has many server blocks in its configuration, so one or more of the same internal requests may be added to the external request, and each of them will be logged. If you want to filter only external requests without showing duplicates, then use the following query:

```
*.container.name : nginx and server_port: 80
```

### MySQL

```
*.container.name : "mysql"
```

## Deployment and build logs in Kibana

### Build logs

{% hint style="info" %}
Build logs are only recorded in Kibana if the build failed.
{% endhint %}

```
*.container.name : "build"
```

### Deployment logs

```
*.container.name : "app-updater"
```

### system.log in Kibana

```
(*.container.name : "app" or *.container.name : "cron") and (message : "main.ERROR" or message: "main.NOTICE" or message: "main.INFO" or message: "main.DEBUG") 
```

### exception.log in Kibana

```
(*.container.name.keyword : "app" or *.container.name : "cron") and message: "main.CRITICAL" 
```

### cron.log in Kibana

```
*.container.name.keyword : "cron"
```

## Create database dump

1. Grant SSH access via the User Portal following [the instructions](/application-management/ssh-access).
2. Connect to the environment using created SSH access.
3. Create a database dump on the server:

   ```
   mysqldump magento --single-transaction --no-tablespaces | zip dump.sql.gz -
   ```
4. Exit SSH.
5. Copy the database dump locally:

   ```
   scp {ssh_user}@ssh.readymage.com:/home/magento/dump.sql.gz .
   ```

## Replace the database with a database dump

1. Grant SSH access via the User Portal following [the instructions](/application-management/ssh-access).
2. Place database dump on the server by running:

   ```
   scp {local_path_to_db} {ssh_user}@ssh.readymage.com:/home/magento/dump.sql
   ```
3. Connect to the environment using created SSH access.
4. Replace the database with your dump file:

   ```
   mysql magento < dump.sql
   ```

## Copy media data from local to SSH container

{% hint style="info" %}
You can only copy media to `/home/magento` directory.
{% endhint %}

```
rsync -azP media/ your-user@ssh.readymage.com:/home/magento/media/
```

## Copy media data from SSH container to local

```
rsync -azP your-user@ssh.readymage.com:/home/magento/media/
```

## Connect to MySQL database

1. Grant SSH access via the User Portal following [the instructions](/application-management/ssh-access).
2. Connect to the environment using created SSH access.
3. Connect to MySQL database:

   ```
   SSH - "mysql"
   ```

## View Magento reports stored in var/reports

Use the following command when connected to SSH to list all available reports:

```
ls -l var/report/
```

Use the following command when connected to SSH to view the specific report:

```
cat var/report/{report_name}
```

## Resolve stuck deployment

Identify the problem by checking deployment and build logs and try redeploying the instance following the instructions [here](/application-management/deploy-changes-to-your-instance).

## Reindex commands

1. Grant SSH access via the User Portal following [the instructions](/application-management/ssh-access).
2. Connect to the environment using created SSH access.
3. Check reindexing status:

   ```
   php bin/magento indexer:info
   php bin/magento indexer:status
   ```
4. Perform reindex

   ```
   php bin/magento indexer:reindex
   ```
5. Reset reindex

   ```
   php bin/magento indexer:reset
   ```

## Files that are copied to ReadyMage during deployment

* `src/composer.json`
* `src/composer.lock`
* `src/app/`
* `src/pub/.well-known`
* `src/pub/google*.html`

## Content Security Policy control

Content security policies are controlled on Magento 2 application level.

## Clear cache

### Via Magento admin

System > Tools > Cache Management > Flush Cache Storage and Flush Magento Cache.

### SSH

```
php bin/magento c:f
```

### Cloudflare

Dashboard > Settings > Purge Cache

## Resolve "The default website isn't defined"

ReadyMage requires having store views, stores, and website defined in the config.php file

## The folder structure on the Magento server

Magento files are stored in `/var/www/shared/public` and can be checked through SSH access.

## Applying patches

Magento patches must be placed in `src/patches`

There should be no `composer.patches.json` file. The indication of patches should be via "extra: patches" in `composer.json`.


# Persistent directories

Certain directories require persistent storage to ensure data integrity and availability across system restarts or scaling events. These persistent directories serve as essential components for storing application data, logs, media files, and maintenance flags.

To facilitate data persistence and maintain consistency across deployments, symbolic links (symlinks) are utilized to connect application directories to their corresponding persistent storage locations. These symlinks ensure that essential data is stored in designated directories on the underlying filesystem.

#### Symlinks Configuration

The following symlinks are established within the application's directory structure to map to persistent storage locations:

**Media Files**:

`/var/www/public/pub/media` -> `/mnt/media`&#x20;

`/home/magento/media` or (`~/media` ) -> `/mnt/media`

**Debug Logs**:&#x20;

`/var/www/public/var/debug` -> `/mnt/var/debug`

**Exported Data**:&#x20;

`/var/www/public/var/export` -> `/mnt/export`

**Imported Data**:&#x20;

`/var/www/public/var/import` -> `/mnt/import`

**Log Files**:&#x20;

`/var/www/public/var/log` -> `/mnt/var/log`

**Error Reports**:

`/var/www/public/var/report` -> `/mnt/var/report`

#### Special Maintenance Flags

In addition to the persistent directories, the applications can utilize special maintenance flags for managing system maintenance operations. These flags are stored in the following locations:

**Maintenance Flag**:

&#x20;`/var/www/public/var/.maintenance.flag` -> `/mnt/var/.maintenance.flag`

**Maintenance IP Whitelist**:&#x20;

`/var/www/public/var/.maintenance.ip` -> `/mnt/var/.maintenance.ip`

For detailed information on maintenance flags and their usage, refer to this [reference](https://experienceleague.adobe.com/en/docs/commerce-operations/installation-guide/tutorials/maintenance-mode).


# General

## **How can I contact customer support?**

We provide a support form for any issue or request regarding your Cloud project.

<figure><img src="/files/5myAhaxDKY8fKqjPVk2F" alt=""><figcaption></figcaption></figure>

In order to contact support, a Support Ticket must be submitted. Support Ticket submission happens through [User Portal](https://portal.readymage.com/). Navigate to the **User Portal → Support** and simply fill in the required fields and press submit.

<figure><img src="/files/3k64ZsFJGIqIvFLIuB6i" alt=""><figcaption></figcaption></figure>

After submission Support will reach out to you directly via email to address your ticket.

## Can I use Setup Wizard to install new extensions to my store on ReadyMage?

To ensure the security of the application, the changes to its code base are allowed only via code repository in GitHub, meaning that all extensions need to be set up locally first and then committed to the repository. After that these will be built and deployed to the cloud, altering DB tables, if required by the extension install files.

## What is the rate for custom infrastructure requests, consultancy, or code audits?

This is a project-specific service provided based on an hourly pay-as-you-go model, prices can be consulted by contacting us through <hello@readymage.com>. Note, we do not provide application support or customization services.

## Do you offer support in the migration of my store from another hosting?

Yes, our team can provide on-demand support in moving your Magento 2 + ScandiPWA site to the ReadyMage cloud. Please, contact us through email at <hello@readymage.com>.

## Can I host Magento 1 sites on ReadyMage?

Generally, ReadyMage does not provide support for Magento 1 website hosting.&#x20;

But experienced partner MigrateMyStore can help you migrate your existing Magento 1 store to Magento 2 and ScandiPWA. Visit [www.migratemystore.com](https://migratemystore.com/) for a cost calculator and quote.

## What is your backup policy?

### Frequency, timing, and availability

#### MySQL Database

| Frequency | Timing                                  | Availability |
| --------- | --------------------------------------- | ------------ |
| Daily     | 00:00 UTC                               | 6 days       |
| Weekly    | Sunday to Monday 00:00 UTC              | 14 days      |
| Monthly   | On the first day of the month 00:00 UTC | 93 days      |

#### Media

| Weekly | Monday 04:00 UTC | 14 days |
| ------ | ---------------- | ------- |

#### How to request a database or media restore

Download the backup by following the instructions [here](/application-management/backups). You can perform database or media restore yourself via SSH or request restore through support and it will be done in the next 24 hours.

## Which version of Magento 2 and ScandiPWA will I have?

After the new account creation in ReadyMage, you will have an instance with the latest version of ScandiPWA and the corresponding Magento 2 version. You can find the Magento 2 version in the [ScandiPWA and Magento 2 version mapping table](https://manual.scandipwa.com/pwa/magento-version-mapping).&#x20;

The latest version of ScandiPWA is served by ReadyMage in 5 days after the latest ScandiPWA version is released. You can find more information about the ScandiPWA releases [here](https://github.com/scandipwa/scandipwa/releases).&#x20;


# Autoscaling

ReadyMage autoscaling explained with case study

ReadyMage hosting is created on Kubernetes which allows it to provide autoscaling features for its customers.&#x20;

In ReadyMage, your resources of infrastructure components - MySQL, Front-end, Back-end, Varnish, ElasticSearch, are stored on pods. Pods, in turn, run on nodes, which are virtual AWS servers.&#x20;

{% hint style="info" %}
Pods are the smallest, most basic deployable objects in Kubernetes. A Pod represents a single instance of a running process in your cluster.
{% endhint %}

![](https://lh3.googleusercontent.com/VCEcDzt41mTkOSDyauQR3PRAALNUq-694CnuAwYevxAzckK1IBdtoWaDNebIjkaIG2c2ukNpMgYn5KCk3nFrCilO9Syf7ZX844HPqLtFOlQqNS0qCNXn968CjwTXKsP01DSKhRhd)

### Why is autoscaling needed?&#x20;

Imagine you have a production instance with the server resources set to handle only normal traffic. And once the sales period starts and the traffic increases, ideally, we want the website to still handle it and not have downtime. But at the same time, we want to keep default resources low so we do not need to pay for the resources that are not used. This is a case where autoscaling helps. <br>

If we now consider the ReadyMage infrastructure, in other words, it would sound like that: we do not want to keep resource limits of one pod bigger than needed on a regular basis but we want the server to still handle the high load by assigning more resources automatically. <br>

### Real-life case study

On June 21st, [beautyworksonline](https://beautyworksonline.com/), hosted on ReadyMage, received more traffic than usual due to the unexpected promotion.&#x20;

After a big blog post by a popular blogger, beautyworksonline received x3 more traffic than usual having around 350 concurrent users on the website.&#x20;

![Front-end pod replicas and CPU consumption for beautyworksonline on 21.06](https://lh3.googleusercontent.com/80zZyofxBf17uMULY53qcg6OgLGHMsibs44_i_0yn4FgN5Cdg-4r31QyohbVS16euCl02jHoeRNf5WuSNAXTn3weTnrll75ssrC4a3ZS39qeP6NQZEmw1tqHdDbkkXbzaQnFIwwD)

At 8:00 PM, when the traffic went up, ReadyMage infrastructure was creating pods one by one until the total CPU amount could handle the incoming traffic.&#x20;

Once it got normalized back after 1:00 AM, the unused pods were scaled down.

### How does it work?

ReadyMage provides the ability of horizontal autoscaling for **front-end** and **back-end** pods.

Horizontal scaling allows you to automatically increase or decrease the number of running pods as your application’s usage changes.<br>

![ CPU Usage utilization in front-end pod](https://lh5.googleusercontent.com/wAarcb2JPHQnhrJSQi_qRBeEYpAfH-wzhS5STHxkvuqcCnjBUoAfXv2-UQ9gFFXtm9EDY8OiPvh47gOY8CtJwmskhcU2AHyuvA3eaVnJQfI66YEQ6MprPWrAHTWvriXhEJPby0e6)

As your consumed resources hit the HPA (Horizontal Pod Autoscaling) limit, the green line on the graph above, our infrastructure creates a new replica of a pod for the same infrastructure component and distributes the traffic equally between all pods.

HPA limit is calculated programmatically based on the requested resource amount that is set for the pod, the yellow line on the graph above. In ReadyMage, the HPA is 75% of this limit. It is less than the limit for safety purposes, if the replica pod requires more time to get up, your current pod will still have some available resources while waiting for it.

In the example of the CPU consumption above, the total limit is 0.8 CPU and the HPA is 0.6 CPU. At 1:05 AM, the resources required to hit the HPA limit, and a new replica of the same pod was created. <br>

![Number of pods running ](https://lh3.googleusercontent.com/oj6kRKkND0Zez9X3ISf0mQzz1wpdNJUW9-Vq5YoH5vuXuNJ3NOZIO8YPWe41XEybE1wGKQGwF-RH8SE9g6OdiBtc8KPKZkE01CP0_ITWOMeCr2loJ7IrAJl1bARMOUGjTZvEa0R7)

For scaling down, each 5 min the traffic is checked for front-end and back-end pods, and if the total consumed CPU can be handled by fewer pods, we scale down the allocated resources by killing unused pods. So when the traffic is back to normal, the resources are returned back to the default state and you do not need to pay more than needed.

Referring to the same example, at 1:10 AM the additional pod was killed, and the resources were allocated back to normal.

{% hint style="success" %}
For scaling up there is no stabilization window. When the metrics indicate that the target should be scaled up the target is scaled up immediately.&#x20;
{% endhint %}


# Billing

How can I manage my billing and subscription details?

To access and manage your billing and subscription details, navigate to the **User Portal → Account Menu (top-right corner) → Billing → Click "Access portal"** &#x20;

Enter your email and one-time password, which will be sent to your registered email.

<figure><img src="/files/7dM9D4WgViawCfGO14nC" alt=""><figcaption><p>Billing in Account Menu</p></figcaption></figure>

<div align="center"><img src="/files/RAYEJgEXFGeo2m4GtXHK" alt="&#x22;Access Portal&#x22; Button"></div>

## What will I be charged on a monthly basis?

There is a minimum charge of $215 / month that includes the resources necessary to run a small shop efficiently, handling a load of back-end catalog and order management operations as well as a front-end load of up to 600 users per hour and up to 1,500 daily unique accesses in a store with a catalog carrying a few thousands SKUs.

## My store can not handle the above load on the minimum package, why?

This can happen for various reasons, for example:

* Your catalog size is considered “medium” or “big” based on [Magento 2 standards](https://devdocs.magento.com/guides/v2.4/config-guide/cli/config-cli-subcommands-perf-data.html).
* The quality of code, DB queries, or extensions create an inefficient load for PHP and DB to process customer requests. You can [check logs](/application-management/log-management-using-kibana) in order to identify the root cause.
* Caching is set up inefficiently or is broken, so instead of serving cached content without almost any costs, your store invokes expensive computing resources of PHP and MySQL to serve the content to your visitors.

Our team can help with the code audit and optimization recommendations that your dev team or technical partner can implement. Please reach out to us through support.

## What are the resources and services corresponding to the minimum monthly fee of $215?

These are the following computing, storage, bandwidth, and service resources:

* Managed services for hosting and CI/CD of ScandiPWA (or your choice of FE) and Magento 2
* 3.75 CPUs, 6.5 GB of RAM, 30 GB database, 10GB elasticsearch, 5GB Redis, and 20 GB application storage volume in AWS
* GitHub repository
* Automated Pipeline Deployment
* Connected ELK stack
* Setup NewRelic
* Daily DB backup
* 24/7 alerts
* On-demand support for custom infrastructure queries
* FREE setup of CDN, WebP, and SSR integration
* Free setup of SFTP server
* Up 20 000 user session handling

## What are the additional charges to the monthly managed hosting fee?

Additional charges are subject to whether your project is using additional services such as CDN, WebP image conversion, and Server Side Rendering (SSR). These are recommended to run on any store and are connected on-demand after registration.

Sample pricing is:

* CDN - from FREE Cloudflare tier to $20 / month per domain
* WebP - included in $20 / month of Cloudflare

## When I set up an additional UAT or Prelive instance, how is it charged?

The charge is calculated based on the consumed resources by these additional instances. The cost will be reduced if the instance is not regularly used since [it will be put in low-consumption mode](/infrastructure-management/sleep-mode) after 24 hours of inactivity.&#x20;

{% hint style="info" %}
Caution! Your Dev or UAT instances can become very costly if you run stress tests there or perform frequent full reindexes on large catalog sizes.
{% endhint %}

## Can I cap my budget per month?

Yes, you can. You may disable the [autoscaling in the User Portal](/infrastructure-management/autoscale). If autoscaling is disabled, no matter what load you produce on the back-end or front-end, the instances will not scale themselves, thus not incurring any extra costs even for a short period of time.&#x20;

## Can I configure different resource limits and set my monthly limit, for example, to $400?

Yes, you can turn off autoscaling, but increase static sizes for each of the services, setting them to a target budget or maximum resource limits.

## Can I look into the possible reasons why my consumption became higher if I do not see increased traffic in Google Analytics?

Yes, you can request setting up Grafana with performance and load dashboards as well as contracting NewRelic and inserting your license key as NewRelic is already pre-configured on all the instances. These tools will show the reasons for the load and you are also welcome to contact our on-demand support, who can prepare a report for you along with any practical actions to address it.

## How can I transfer my subscription to another person?

There can various reasons you might want to change ownership of the ReadyMage instance:

* the instance will be managed by a different person;
* you are an agency that has developed a project for a client and now you want to transfer it;
* another person will be managing payments for the instance;
* and etc.

If billing information doesn't change then to transfer the subscription create a support ticket through User Portal.

If you would like to fully transfer the subscription including the billing information, contact <hello@readymage.com>.

## Can I cancel the ReadyMage service at any time?

Yes, you can log in to the User Portal and cancel it anytime. You will be charged for the actual consumption till the cancellation, all your assets, including code, media, database, etc will be archived for a period of 24 hours subject to a recovery service, and then permanently deleted.


# User Portal Options

## I see an option to put my instance to “sleep mode”, what does it mean?

This is a cost-saving option for non-production instances. We will minimize its resources to a minimum of $1 / day, while in sleep. It will recover automatically within 1 to 3 minutes if the website or admin panel is opened. Sleep mode can be turned on or off. If it is turned on the instance will automatically go into sleep mode after 24 hours of inactivity.

Refer to the [Sleep mode documentation](/infrastructure-management/sleep-mode) to learn more.

## I see an option to create a new instance, what does it mean?

When you sign up, you get your first production instance running in production mode, but usually, you want to have an extra one for UAT purposes or as a DEV server for your agency or team. Such a setup ensures that you can test the features on a similar infrastructure before accepting them to be deployed on the production server.

## What do the options “production mode” and “default mode” mean, when creating instances?

Magento has optimized caching and indexing in production mode to ensure better performance, so this is the setting you want to keep for production instances or when testing for production.

Default mode runs without production mode optimization.

There is also developer mode that is only used for local setups and is not offered on the ReadyMage cloud instances.

## I see I can change CPU, RAM, and media volume size for my project in the owner's panel, why should I do it?

While there is autoscaling in place, some stores may need to have a minimum size of the server being larger for example due to a large number of SKUs, stores, or attributes as well as bad coding practices. Even though these are simple sliders, we recommend using these settings by a person experienced in server-side resourcing or by on-demand consulting with our support team, who will recommend you the best setup based on your catalog size, code quality, and traffic.

## I see the Composer Authentification field, why do I need it?

You may need it if you run Magento Commerce edition to access a private repository or to access any private package repository, where you store your code. Configuring Composer Authentication allows code from these private repositories to your instance.


# Services connected to ReadyMage

## I need to see logs of Magento, ElasticSearch, and other services to debug, where can I find them?

Yes, your project comes with a connected ELK stack and in your project's User Portal, you can find the access to Kibana application that updates logs in real-time with the possibility to search particular records or narrow down the search by a service e.g. Magento or Varnish logs.

## I need to set up UAT and Pre-live environments as well, how can I do it?

Yes, you can also do it with 1-click in the User Portal naming your new instance that will be cloned from the master branch and choosing to run it in production or default Magento mode.

## How can I connect to DB to manage it in WorkBench or a similar tool?

Please, add the public key of the user in the User Portal to connect.

## I need to run Magento CLI commands e.g. reindex, how can I do that?

Please, add the public key of the user to run the commands in the User Portal.

## I want to set up a CDN for my site, how can I do it?

There are different CDN providers we support with FREE set up such as Fastly and Cloudflare. Cloudflare offers FREE unlimited CDN or $20 per domain that includes unlimited DDoS attack mitigation and WebP image optimization, which is the most cost-efficient solution by now. Fastly on the other hand offers Varnish cache at the edge, where we store GraphQL responses and WebP optimization as well, but at a higher fee. Please, make your CDN provider choice and we will be happy to assist with FREE setup. Simply contact us through a support request.

## I want to set up WebP for my site, how can I do it?

WebP is usually provided by one of the CDN providers such as Cloudflare. We will set up Cloudflare FREE for you once you make a support request.

## I know that PWA sites need Server Side Rendering to ensure fast indexation by search engines, do you provide that?

Yes, we connect out of the box Server-Side Rendering (SSR) service, and its fee, based on the number of pages indexed, is added to your monthly resource consumption bill.

## Why don't you use CloudFront instead of Cloudflare?

CloudFront only provides CDN and you pay $0.085 per gigabyte. You would require to set up AWS Lambda for WebP optimization and AWS WAF for DDoS protection at an additional cost.

On the other hand with Cloudflare, you get unlimited CDN, WebP optimization, and DDoS protection out of the box for a fixed cost of $20.

## Why don't you use AWS ElastiCache?

We can setup AWS ElastiCache if required at an extra cost.

Since ReadyMage only does Magento 2 e-commerce solution infrastructure, we use Redis as per Magento's recommendation and only for isolated Magento purposes allowing us to configure it for optimal performance.

## What Database are you using? Why not AWS Aurora?

You can’t export data from AWS Aurora due to it having the proprietary SQL format of AWS.

ReadyMage is using the same database as Magento Cloud - MySQL database.&#x20;

In terms of backups, ReadyMage has a daily, weekly, and monthly snapshots system in place ensuring high data security.

## Do you use Terraform?

We are using Terraform only to create Nodes. Infrastructure provisioning is fully done by Kubernetes manifests.

## Can MariaDB data be migrated to ReadyMage?

Since both MariaDB and MySQL databases provide the same set of underlying tools, it is very easy to copy data from MariaDB to MySQL. Using out of the box commands the records would get migrated into MySQL from the provided MariaDB database dump.


# Hosting, managing resources and autoscaling

## Where does ReadyMage host their cloud?

We host it in Amazon Web Services (AWS) data centers located in Europe (Ireland, Stockholm), USA (Ohio), Canada (Central), Asia Pacific (Sydney), Middle East (UAE) on high-performance CPU-intensive compute instances under Kubernetes management.

## If you host in AWS and I have an existing account, can I link my instances to it?

In order to ensure efficiency across multiple projects, all of them share the same core configuration that is linked to our account, so by default, you cannot link your account to ReadyMage services.

## I want to connect some of the services that are not provided out of the box by ReadyMage e.g. Aurora DB or AWS Cloudfront, can I?

Yes, you can, it usually takes a few hours. Reach out to the support team to schedule this setup and agree on the billing.

## Is my Magento 2 and ScandiPWA placed on a single instance in your cloud?

We have an enterprise-level solution for provisioning infrastructure: each service is placed on a separate dedicated instance that has an optimised configuration and mix of CPU and RAM resources to run this particular service for PWA and Magento 2 type of loads.

## If you have distributed deployment instead of a single instance, how many isolated ones are there?

These applications and services are placed on isolated instances - Magento front-end, Magento back-end, Magento cron jobs, MySQL DB, Redis, Varnish, ElasticSearch, and Nginx.

## What are some of the benefits of distributed deployment?

1. Allows to configure each service for its particular loads, thus saving costs and providing better performance;
2. Keeps all other services stable and performing in case one of the services is overloaded;
3. Simplifies debugging as instead of “server is down”, we immediately see which of the services is down e.g. Varnish, ElasticSearch, and can start fixing it right away;
4. Enables horizontal auto-scaling as now your Magento front-end instances can be doubled, quadrupled, or even multiplied by the factor of 50 or 100 depending on the load it handles with other services running on their original setups;
5. Cost optimisation by figuring out which of the particular services needs an increase of resources rather than assigning more resources to all.

## If I need an extra feature e.g. VPN tunnel, can you configure such?

Yes, we can. We provide infrastructure support and maintenance. Please, reach out to our support and we will provide an estimate for this.

## If I would like to verify my Magento site is secure what can I do?

ReadyMage understands the need to make sure their websites are up-to-date with latest security standards and Magento patches. Therefore, you are free to do the following activities:

1. Stress-testing your application in a way that does not cause excessive network load on ReadyMage infrastructure or any other tenants;
2. Perform vulnerability scanning for your application;
3. Verify your environment isolation within environments you are the owner of (for example, by testing network communication between production and non-production environment).

Nevertheless, we recommend getting in touch with us before you perform such activities at <hello@readymage.com>.

We do not allow to perform the following kind of actions:

1. DoS (denial-of-service) kind of attacks that generate excessive traffic transfer and load on ReadyMage infrastructure;
2. Execute penetration testing of ReadyMage infrastructure and components;
3. Perform any kind of tests that could negatively impact other tenants.

## How does auto-scaling work for my store?

Auto-scaling scripts check the load on your store every 15 seconds and if it surpasses a certain threshold of CPU and RAM usage then it triggers a procedure of duplicating this particular server instance. It takes less than 60 seconds to create a new service, so in case you will experience a double load on your Magento store that is happening over 1 to 2 minutes, the system will manage to adapt and provide double capacity. If the load continues to increase, additional instances will be spun up.

\
If resource consumption decreases, the additionally created instances will be destroyed, thus optimising the costs.

## Autoscaling is cool, but can I change the default value for my DB instance or PHP as my store carries a larger catalog with millions of SKUs?

Contact the support and we will help you set up the most efficient configuration based on your specific requirements.

## I need a bespoke build for my store with triple redundancy, multi-regions, master-slave DB, and other enterprise features, can you build it for me?

In order to provide reliable and cost-efficient service, we focus on the current set up and do not revise the core of it. We can, however, recommend you a few of our partners, who have related experience in such setups. Please send us an email at <hello@readymage.com>


# Security


# Source Code Management

## Do I have full access to the code that is deployed to ReadyMage Cloud?

Yes, you have full access to the code of deployed applications and can manage it in your GitHub repository by adding GitHub username(s) in your User Portal after registration.

## Can I add multiple people managing the repository with the source code?

Yes, you can add multiple users to manage your repository. It is made for you to manage your teams on a project-by-project basis.

## Can I revoke the access to the repository or an invite that I made?

Yes, you can revoke pending or an accepted invites by revoking particular user access to your project GitHub repository in the User Portal or through GitHub.

## Where should I commit the code to trigger deployment?

In order to trigger the deployment you have to commit the code to the project branch associated with the instance you want to deploy on. You start out with a single instance and its code is managed on the master branch in GitHub.

## I have multiple environments set up, where is their source code?

When you set up an additional environment(s) e.g. pre-live or UAT, we create a new branch in your repository that is cloned from the master branch. We give it a name based on the environment name that you have chosen, dash, and 3 random letters e.g. UAT environment will have something like `UAT-asd`.

## Can we follow gitflow or feature-branch workflow in the repository you have created?

Yes, you can! You can follow conventional version control and collaboration approaches supported by GitHub.

## Can I use GitHub actions to check my code on commits in your repository?

Yes, you can use Github actions - <https://github.com/features/actions>

## When I delete an environment, will the branch with its source code be deleted as well?

No, the branch with the source code will stay in the repository, but the associated infrastructure that was provisioned for this environment will be deleted. There is no cost associated with keeping the source code in the repository after deletion.

## When I cancel the ReadyMage service, is my repository deleted?

We don't delete the repository in case you decide to restore the service.

## What happens if I delete all the code from the master?

Your ReadyMage project repository can't be deleted with the access level provided to added users.

## Are there some folders that are restricted to commit to?

You can check what is being ignored on the commit within the .gitignore file. You can modify the .gitignore file to suit your project needs. It is available in your GitHub repository. Keep in mind that ReadyMage only deploys composer.\* files and app directory from /src.

## Can I commit an application e.g. on Laravel into my GitHub repository to have it deployed to the ReadyMage cloud?

Committing different apps will cause a build and deploy error. We have dedicated solutions for hosting other eCommerce applications, e.g. Akeneo PIM. Please, contact our support for more details.


# ScandiPWA and Magento Versions, Commerce Edition and Upgrades

## I see your solution comes with the latest Magento 2 and ScandiPWA. What if the project that I want to deploy is working on previous Magento 2 and ScandiPWA versions?

Yes, we provide the latest by default, but once you get access to the GitHub repository with their code you simply commit your project there and there will be an automatic build that will take your project’s code and deploy it to the infrastructure. This means that you can have any ScandiPWA version hosted on ReadyMage.

## I want to run a particular version of Magento 2 with ScandiPWA on it, which ones do you support?

ScandiPWA supports the latest Magento version which currently is Magento 2.4.3. Newly signed-up accounts on ReadyMage always get the latest version of Magento 2 and ScandiPWA. Of course, you can install ScandiPWA on any Magento 2.x.x version afterward but keep in mind that there might be some issues.

## I have a Magento Commerce license, but I do not use Magento Commerce Cloud, can I host my site on ReadyMage?

Yes, absolutely, we host several Magento Commerce + ScandiPWA customers. The only difference is that you will provide an authentication file in your User Portal to read from the private Magento Commerce repository. All other processes and setups of CDN, WebP, and SSR are the same.

## I have been your customer for several months now. How do Magento and ScandiPWA upgrades work? Is it included in your managed services?

If you are running a previous version, you need to have a developer or an Agency Partner who will help you to upgrade, as this is a manual process. Please send us a message to <hello@readymage.com> and we will advise companies skilled in Magento and PWA with experience in the ReadyMage cloud.

## I want to upgrade my version, can I pay your support to do it?

Though we do have paid support, it only covers infrastructure-related things e.g. setting up VPN tunnels or providing code audit for the purposes of hosting code optimization. We don't cover the application-related issues that need to be covered by your development team or technical solution partner.


# Supported software versions

{% hint style="info" %}
All of the software dependencies have been tested and verified to be stable and working with all the listed Magento 2 versions.
{% endhint %}

| Software          | Version                                                                                                                                                                                                                                                          |
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Magento 2**     | <p>2.2.10<br>2.3.3<br>2.3.4<br>2.3.5 (and p1)<br>2.3.6<br>2.3.7 (and p3, p4)<br>2.4.0<br>2.4.1<br>2.4.2<br>2.4.3 (and p1, p3)<br>2.4.4 (and p2, p3, p5, p17)<br>2.4.5<br>2.4.6 (and p3, p14)</p><p>2.4.7-beta1<br>2.4.7- (and p9)<br>2.4.8 (and p4)<br>2.4.9</p> |
| **PHP**           | <p>7.2</p><p>7.3</p><p>7.4<br>8.1<br>8.2<br>8.3<br>8.4<br>8.5</p>                                                                                                                                                                                                |
| **MySQL**         | <p>5.7<br>8.0</p>                                                                                                                                                                                                                                                |
| **MariaDB**       | <p>10.4<br>10.5<br>10.6<br>11.4</p>                                                                                                                                                                                                                              |
| **Elasticsearch** | <p>5.6<br>7.6<br>7.17</p>                                                                                                                                                                                                                                        |
| **OpenSearch**    | <p>1.3<br>2.5<br>2.12<br>2.19<br>3.0<br>3.1</p>                                                                                                                                                                                                                  |
| **Varnish**       | <p>6.5<br>7<br>7.2<br>7.5<br>7.7</p>                                                                                                                                                                                                                             |
| **Valkey**        | 8.1                                                                                                                                                                                                                                                              |
| **Redis**         | <p>6.2<br>7.0<br>7.2</p>                                                                                                                                                                                                                                         |
| **Nginx**         | 1.21                                                                                                                                                                                                                                                             |


