# AWS Deployment

Amazon AWS is perfect for Enterprise customers who wish to have a robust platform with high availability. It is used and trusted by some of the largest companies in the world to serve as their cloud infrastructure. Below is a diagram showing the architecture of an AWS Deployment.

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FvPlJilovQMDGTLhgpB5D%2FForm_io%20Environment%20Diagram%20AWS_bg.png?alt=media\&token=6bbe543f-307c-4d41-a37e-d8bc4b168245)

## Prerequisites

This procedure assumes the user has an account with [**Amazon AWS**](https://aws.amazon.com/).&#x20;

## DB Requirements

Form.io requires MongoDB or a MongoDB-compatible DB. Before deployment, create a database to store all the Forms and Submissions within the Form.io deployment. This document describes what to configure on each respective service:

* [MongoDB Atlas](#mongodb-atlas)
* [AWS DocumentDB](#documentdb)

### MongoDB Atlas

Before deployment, create an account at [MongoDB.com/atlas](https://www.mongodb.com/atlas). Follow the steps provided by MongoDB to create the cluster while observing the guidelines described below.

#### Performance

When configuring the performance of the cluster, it may be necessary to review the **advanced settings**. The particular settings selected may depend on the planned deployment. The following baseline standard may be used when determining the application's needs:

1. For production environments, the **dedicated** tier may be required.
2. Consider enabling **multi-region** replication to create additional instances for greater availability.
3. Choose a sufficient **cluster tier** based on the expected usage.\
   **M10** is typically sufficient for development.\
   **M20** is the recommended baseline for production.

#### Security

When configuring the security settings in MongDB Atlas after clicking **Create Cluster**, refer to the following guidelines:

1. Record the **username** and **password** for use in the connection string later.
2. Configure **VPC peering** with the appropriate details.
   1. The configuration window will require the **AWS ID** and **VPC** **ID** from the deployment's AWS Account.&#x20;
   2. Enter the **VPC CIDR** as found in Amazon's AWS Dashboard at **Networking > VPC.**
3. Record the **Peering Connection ID** provided by MongoDB Atlas.
4. From the AWS Dashboard, complete the peering configuration from the **Networking > VPC > Peering Connections** menu.

If the deployment requires additional security that would mandate a private endpoint, refer to the [MongoDB Documentation](https://www.mongodb.com/docs/atlas/security-cluster-private-endpoint/) regarding connecting cloud services to a private endpoint.

#### Connection String

From the MongoDB Atlas **Project Overview**, open the **Connect Menu** and generate a **legacy (standard**) **connection string**. It will appear similar to the following:

{% code overflow="wrap" %}

```
mongodb://formio:<db_password>@<node1>,<node2>,<node3>/<dbName>?replicaSet=<replicaSetName>&ssl=true&authSource=admin&retryWrites=true&w=majority&appName=<appName>
```

{% endcode %}

Note the following placeholders:

* **\<node1>...** : These will correspond to the individual instances of the DB.
* **\<replicaSetName>**:  The atlas-generated replica set name.
* **\<appName>:** Typically *formio*.
* **\<dbName>:** Typically *formio* (added by us).

Supplying the required info creates a connection string similar to the following, using the example password *badPassword*:

{% code overflow="wrap" %}

```
mongodb://formio:badPassword@formio-shard-00-00.qa5hm.mongodb.net:27017,formio-shard-00-01.qa5hm.mongodb.net:27017,formio-shard-00-02.qa5hm.mongodb.net:27017/formio?replicaSet=atlas-6fxuzs-shard-0&ssl=true&authSource=admin&retryWrites=true&w=majority&appName=formio
```

{% endcode %}

**Note that the database name `formio` is added so that the Form.io deployment will initialize with this database instead of the default `test` database.**&#x20;

Also observe that `?ssl=true` indicates a database connection over SSL,  `&retryWrites=true` indicates retryWrites is supported, and uses the `admin` database rather than IAM to authenticate.&#x20;

Record this connection string for later.

### DocumentDB

[**DocumentDB**](https://aws.amazon.com/documentdb/) is an AWS managed NoSQL database that can store projects, forms, and submissions.

From the AWS Console, navigate to the **Amazon DocumentDB** service. Launch a new DocumentDB service, following the AWS process.&#x20;

#### Performance

Configure the instance according to the following parameters:

1. **Cluster Identifier**:  Keep default or type a unique name.
2. **Engine Version**: 5.x and below.&#x20;
3. **Instance Class:** &#x20;
   * Production environment:  At least **db.r5.large**&#x20;
   * Development environment: At least **db.t3.medium**
4. **Number of Instances:**
   * Production Environment: At least 2
   * Development Environment: At least 1

#### Authentication

Provide a **Master username** and a secure password for the cluster. These will be required later.

#### Connection String

Now that the DocumentDB cluster is created, click on the cluster link, and copy the application connection string. It should look like the following:

{% code overflow="wrap" %}

```
mongodb://formio:<insertYourPassword>@docdb-2024-08-23-12-49-44.cluster-chnyabcd6feh.us-east-1.docdb.amazonaws.com:27017/?tls=true&tlsCAFile=global-bundle.pem&replicaSet=rs0&readPreference=secondaryPreferred&retryWrites=false
```

{% endcode %}

This connection string must be converted to a standard connection string.  To do so:

1. Remove everything after the “:27017/”, and then append the database name to the end, for example, "**formio".** It should look like:

{% code overflow="wrap" %}

```
 mongodb://formio:<insertYourPassword>@docdb-2019-02-05-03-07-17.cluster-chnyabcd6feh.us-east-1.docdb.amazonaws.com:27017/formio
```

{% endcode %}

2. Replace `<insertYourPassword>` with the Master Password previously entered in the Authentication field. This example uses "*badpassword*":

{% code overflow="wrap" %}

```
mongodb://formio:badpassword@docdb-2019-02-05-03-07-17.cluster-otsyrtio9xoe.us-east-1.docdb.amazonaws.com:27017/formio
```

{% endcode %}

3. Add `?tls=true&retryWrites=false&authSource=admin` to the end of the URL. This indicates a database connection over SSL, disables retryWrites since DocumentDB does not support it, and uses the `admin`database rather than IAM to authenticate (see [here](https://docs.aws.amazon.com/documentdb/latest/developerguide/security-iam.html) for more information on IAM authentication):

```
mongodb://formio:badpassword@docdb-2019-02-05-03-07-17.cluster-otsyrtio9xoe.us-east-1.docdb.amazonaws.com:27017/formio?tls=true&retryWrites=false&authSource=admin
```

Record this connection string for use later.

Navigate to the newly created cluster's dashboard. At the bottom of the page, take note of the **Security Group Name** that the cluster was added to. It will be used later to ensure that the Form.io Enterprise Server can communicate with the database.

## Cloud File Storage Using S3

Before setting up Form.io API and PDF servers, set up an S3 Bucket which will contain the uploaded PDFs used by the PDF server.

### Create a bucket

1. From the AWS Console, navigate to the **AWS S3** service.
2. Create a new S3 Bucket, following the AWS process.
3. Give the bucket a unique name and record it for later use.

### Create a User

Create an **IAM** role with admin rights to this S3 bucket. From the AWS dashboard, navigate to the **IAM** service and use the **Create User** wizard. Create a descriptive named use (such as *pdf-server*), noting the following essential settings:

1. In the **Set Permissions** page for the new user, select **Attach existing policies directly**, and then select **Create Policy**.
2. Ensure that within the **Service** menu's **Specify Permissions** page, the **Select a Service** option is set for **S3**.
3. In the Actions section, select **All S3 actions** to give this IAM role access to all of the read, write, and update actions available via the S3 service.

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MPHoF2HwOA0s5HV_AIB%2F-MX8mM6a0fjUBdd3gtpH%2F-MX8mRWQszT5LHnHkhIH%2Fpolicy-actions.jpg?alt=media\&token=337f7731-9416-4a9f-9dee-59d88c90e2f5)

4. In the Resources dropdown, click the **Add ARN** link next to the bucket section. Enter the bucket name specified in the previous section. Click **Add ARNs.**
5. In the object resource section, click **Add ARN** and then provide the bucket name. Next, click on the **Any** checkbox for the object section. Then click the **Add ARNs** button.

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FKN3Kdd6sj6sS4oRLpxid%2Fobject_arn_console.png?alt=media\&token=d1b59a45-9f76-4c19-b74b-3577135f6964)

9. For the remaining Resources, click on each one and enable **Any in this account** for all of them. It should look like the following:

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FZyKp9Ynq0V5uoHok5oLV%2FIAM%20Management%20Console%202022-01-20%2010-33-07.png?alt=media\&token=93419a73-500f-4c20-86ad-0c46efd7e0b7)

10. Click the **Next** button to view the Review and Create page. Name the policy "*pdf-server-s3"* and click on the **Create policy** button.

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MPHoF2HwOA0s5HV_AIB%2F-MX8munkSoKcS9sF-8hJ%2F-MX8myr_LsaOCQqj7JHq%2Fs3-policy.jpg?alt=media\&token=8c9a455e-33b9-49f5-abc6-6c0eab19a943)

### Attach the policy

Now that a policy has been created, it must be attached to the IAM role. From AWS dashboard, clicking the **Refresh** icon, and then searching for the newly created policy  (*pdf-server-s3*) in the search bar.

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MPHoF2HwOA0s5HV_AIB%2F-MX8n0N6IT9NiWF--hbE%2F-MX8n3ruvLOKwg3F9kJ1%2Fuser-policy.jpg?alt=media\&token=f98061fd-22a4-432d-9e83-30393d95e37b)

1. Click **Next** in the IAM wizard to view the **Review and Create** page. Select **Create User** to return to the list of Users.
2. From the newly created user, navigate to **Security Credentials.**
3. Click **Create Access Key**, then. select **Third-party Service.** Enter a description for its use.
4. Write down the access key ID and the secret key in a secure location, both will be used to configure environment variables later.

Following these steps, the S3 bucket should be configured to allow file storage for the deployment. Next, proceed to the Elastic Beanstalk deployment!

## Generate Deployment Package

Once the infrastructure is in place, generate the deployment packages. Refer to the process described in the Readme in the [Form.io Github Deploy repo](https://github.com/formio/deploy/).

Following the procedure will result in running a command similar to the following:

{% code overflow="wrap" %}

```
formio-deploy package compose/aws/multicontainer.zip --license=YOURLICENSE
```

{% endcode %}

This will generate a new ZIP file within the deployments folder for `compose/aws/multicontainer.zip` as well as place the deployment in the `deployments/current` folder. This .zip file will be used next to deploy to AWS Elastic Beanstalk.

{% hint style="warning" %}
**IMPORTANT NOTE**: This **multicontainer.zip** file uses a default MongoDB connection string for AWS DocumentD&#x42;**.** Pay attention to the following steps when using MongoDB Atlas, any other external database provider, or an internal MongoDB Community Edition database.
{% endhint %}

To configure the deployment package for use with an alternative DB:

1. Extract `docker-compose.yml` from the multicontainer.zip.
2. In a text editor, locate the MongoDB connection string. It defaults to&#x20;

   ```dockercompose
   MONGO: mongodb://mongo:27017/formio
   ```
3. Change the parameter to the connection string configured previously. It may look like the following:

```
mongodb://formio:badPassword@formio-shard-00-00.qa5hm.mongodb.net:27017,formio-shard-00-01.qa5hm.mongodb.net:27017,formio-shard-00-02.qa5hm.mongodb.net:27017/?replicaSet=atlas-6fxuzs-shard-0&ssl=true&authSource=admin&retryWrites=true&w=majority&appName=formio
```

4. Save the file.

## Elastic Beanstalk

Now that the database and S3 have been configured, this deployment will use **AWS** **Elastic Beanstalk** to manage the Docker deployments.&#x20;

### Create Role

Before proceeding, configure an EC2 instance profile so the underlying instances can interact with Elastic Beanstalk. Return to the **IAM Dashboard** and select **Roles** from the menu, then click **Create Role**. Use the following steps to create the appropriate role:

1. Set the **Trusted Entity Type** to **AWS Service** and **EC2** for the Use Case, then click **Next**.
2. Filter the Permissions Policies by the string "*ElasticBeanstalk*" and select each of the following:

* AWSElasticBeanstalkWebTier
* AWSElasticBeanstalkWorkerTier
* AWSElasticBeanstalkMulticontainerDocker

6. Click **Next**, then give the role a meaningful name (e.g *aws-elasticbeanstalk-ec2-role*). This role will be the EC2 Instance Profile role for the Elastic Beanstalk deployment.
7. Click **Create Role** to complete the process.

### Elastic Beanstalk Deployment

Next, proceed with the Elastic Beanstalk Deployment.

#### Environment

To begin, open the **Elastic Beanstalk Dashboard** and click either **Create Application** or **Create New Environment**.&#x20;

1. Select **Web Server Environment** and provide a meaningful Application Name.
2. Select **Docker** as the managed platform:

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FJn8idguxqHa2xMFV8M3S%2FScreenshot%202023-08-31%20at%203.02.17%20PM.png?alt=media\&token=13339536-3fdc-49e9-a224-449900dfa10b)

5. Select **Upload your code** and upload the multicontainer.zip created previously. Give the version a meaningful label.
6. Under **Presets**, select **High Availability**, and proceed.

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2F5xTLmmwv8IEa50NWM5Js%2FElastic%20Beanstalk%20Management%20Console%202022-01-20%2013-32-45.png?alt=media\&token=866cc7f0-3e85-472e-88a9-db505cb6cebb)

7. Choose to **Use an existing service role**. Under **Existing service roles**, select the **aws-elasticbeanstalk-service-role.**
8. Optionally, associate a key pair with the EC2 instances associated with your environment. Refer to the AWS Document "[Amazon EC2 key pairs and Amazon EC2 instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html)" for more information.
9. In the **EC2 instance profile**, select the role previously created in the IAM dashboard, then proceed.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FxSAuIZAPG0jWT0LmOtOa%2FScreenshot%202023-08-31%20at%203.23.05%20PM.png?alt=media&#x26;token=b674303c-fb9b-4d51-bee7-e2972b9ff478" alt=""><figcaption></figcaption></figure>

#### Network, Database, and Tag Configuration

Proceed with the process on AWS.

1. Select the same **VPC** and **Instance Subnets** configured previously. A typical deployment will run the instances in private subnets, and the load balancer in public subnets.
2. Click **Next** to proceed to **instance traffic and scaling**.
3. Set the **Root Volume Type** to  **General Purpose (SSD).**
4. Increase the size of the storage for each instance from the default of 8GB to **12GB.**\
   The PDF server container stores a large volume of fonts. Theis can be fine tuned later based on the deployment requirements.
5. Under **EC2 Security Groups**, select the security group previously created in the DocumentDB cluster above.
6. Select the desired capacity settings. In general:

* **Development Environments:** t3.medium, or higher
* **Production Envrionments:** t3.large, or higher

19. Use the default **Load Balancer, Listeners, Processes, and Rules** settings. TLS listeners are configured later in this document.
20. &#x20;Click **Next** to navigate to updates, monitoring, and logging configuration.
21. Configure the desired **Health Reporting** metrics, **Platform Updates** settings, and **Updates and Deployments** settings. \
    Generally, a **Rolling** deployment policy ensures the Form.io deployment doesn't experience downtime when updating the platform.
22. Provide the following environment variables within the **Environment** **Properties** section. These are the environment variables which will govern the Form.io platform in important ways.

| Setting              | Description                                                                                                                                                                                                            | Example                                                                                                                                                                                                                                                                    |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| MONGO                | The MongoDB connection string to connect to the remote database.                                                                                                                                                       | mongodb://formio:<badPassword@formio-shard-00-00.qa5hm.mongodb.net>:27017,formio-shard-00-01.qa5hm.mongodb.net:27017,formio-shard-00-02.qa5hm.mongodb.net:27017/?replicaSet=atlas-6fxuzs-shard-0\&ssl=true\&authSource=admin\&retryWrites=true\&w=majority\&appName=formio |
| LICENSE\_KEY         | The Form.io Enterprise deployment license key, provided by Form.io.                                                                                                                                                    | <—YOUR LICENSE—>                                                                                                                                                                                                                                                           |
| PORTAL\_ENABLED      | Used to enable the Self-Hosted Portal                                                                                                                                                                                  | true                                                                                                                                                                                                                                                                       |
| ADMIN\_EMAIL         | An admin account to use as the first platform Admin user.                                                                                                                                                              | <admin@example.com>                                                                                                                                                                                                                                                        |
| ADMIN\_PASS          | A password for the first Admin user.                                                                                                                                                                                   | CHANGEME                                                                                                                                                                                                                                                                   |
| DB\_SECRET           | A secure secret that is used to encrypt the project settings.                                                                                                                                                          | CHANGEME                                                                                                                                                                                                                                                                   |
| PORTAL\_SECRET       | If PORTAL\_ENABLED is not set (as in an API Environment), then this secret is used to connect another portal to this environment                                                                                       | CHANGEME                                                                                                                                                                                                                                                                   |
| JWT\_SECRET          | A secure secret that picked by the user to establish secure JWT tokens.                                                                                                                                                | CHANGEME                                                                                                                                                                                                                                                                   |
| FORMIO\_S3\_BUCKET   | The name of the Bucket created in the previous section.                                                                                                                                                                | pdf-server                                                                                                                                                                                                                                                                 |
| FORMIO\_S3\_REGION   | The region in which the S3 bucket was created.                                                                                                                                                                         | us-east-1                                                                                                                                                                                                                                                                  |
| FORMIO\_S3\_KEY\*    | The Key saved earlier. See the following note for important details.                                                                                                                                                   | ATHSLKJK234LSDLLKJS                                                                                                                                                                                                                                                        |
| FORMIO\_S3\_SECRET\* | The Secret Key saved earlier. See the following note for important details.                                                                                                                                            | nsl23lkjsdf9009sllkjowoi8sous923sd                                                                                                                                                                                                                                         |
| KEEP\_ALIVE\_TIMEOUT | <p>The keepAlive timeout, in seconds. Overrides the default node.js keepAlive timeout (5 seconds).<br>This should be set to exceed any timeout set by load balancers over the server to avoid connectivity issues.</p> | 65                                                                                                                                                                                                                                                                         |

{% hint style="warning" %}
**\*NOTE**: It is not strictly necessary to hardcode the S3 bucket credentials here. Removing these lines will rely on a direct network connection to the S3 bucket using the IAM credentials configured in AWS.
{% endhint %}

{% hint style="info" %}
If you wish to secure your environment variables from visibility, consider [Amazon Key Management Service](https://aws.amazon.com/kms)**.**
{% endhint %}

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MPHoF2HwOA0s5HV_AIB%2F-MX8hxwAiWojXORG7kCu%2F-MX8iNjVOxGC3dj8W4Hl%2FElastic%20Beanstalk%20Management%20Console%202021-03-31%2014-17-27.png?alt=media\&token=6edbfa9b-a3f3-420e-a5a6-5fd1d41a364d)

To complete the setup, click **Next** to review the configuration, then click **Submit** to begin the environment creation process.

After a few minutes, the environment will be available and ready for a new Form.io Project.

### Form.io Project

Now that the deployment is complete, verify it is operational by logging in.

On the first page, use the ADMIN\_EMAIL and ADMIN\_PASS values (established in the Environment Variables in a previous step) to authenticate into the developer portal.

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FZUC0aWuB7ArETVpa1S3w%2Flogin.jpg?alt=media\&token=94240907-488e-4b4d-aa16-8a82a6b885ed)

Once logged into the Developer Portal, click **Create Project**.

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FSZHzJHlQiyJR3NgcSfxP%2FCreateProject.jpg?alt=media\&token=147b17e9-4c78-46a5-b3ea-3cbe1c3fd765)

In the popup modal, give the project a title, then click **Create Project.**

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FgIjR7R1nVePMdJkOHgao%2FProject%20Name.jpg?alt=media\&token=f0ebd4f3-02d0-4ff0-8085-b7632b64f4d1)

### Domain Routing (Route 53)

Now that the environment is operational and a project has been created, the next task is to attach a domain to the Elastic Beanstalk deployment.

If  Elastic Beanstalk was configured to use High Availability, it created Elastic Load Balancers in front of the deployment, which can be linked against the DNS records.

{% embed url="<https://drive.google.com/file/d/1oAEFRdAHaIuVlhzQduMH0NiIVzw6a55b/view?usp=sharing>" %}
Setting up Route 53 Domain Routing and validating SSL Certificate using Amazon Credential Manager
{% endembed %}

To get begin:

1. Navigate to the AWS homepage and then search for *Route 53.*

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MPHoF2HwOA0s5HV_AIB%2F-MX8ncaXzF9Wnms71Qe3%2F-MX8ngGVBxKV8a5HxSO1%2Froute53.jpg?alt=media\&token=601981a7-1cbb-4e05-9ca8-a3e706a24ef7)

2. From the left pane, select **Hosted zones** and click **Create hosted zone**.

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MPHoF2HwOA0s5HV_AIB%2F-MX8ni1D7v1OiWg1BDZE%2F-MX8nmWiWYPl_WZGr-kE%2Fhostedzone.jpg?alt=media\&token=4528afd2-3c46-4ba5-a6f0-cb0fa977b844)

3. Provide the domain name and click  **Create hosted zone**.
4. Next, create a new **Record Set** Provide the following record:

* `*`.yourdomain.com
* Type - A Record
* Alias - Yes
* Select the Elastic Load Balancer as the target
* Press **Create**.

When configured, the routes should look something like the following:

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MPHoF2HwOA0s5HV_AIB%2F-MX8nodDjdK6OX41ZtLL%2F-MX8nsC2tQGRmJafE3Uc%2Froutesetup.png?alt=media\&token=17c57ede-90ea-4c6b-9845-db30ed26d2c8)

5. Set the domain nameservers to point to the ones provided by Route 53. Once the domains evaluate, verify the deployed API is visible within that domain.
6. Return to the Formi.io Portal, and configure the **PDF Server URL** that was configured in a previous step with the new DNS name. It should resemble "<https://pdf.yourdomain.com>".

### Configure SSL certificate for Application Load Balancer

Create basic records in Route 53. The following example shows a record for both the root path and for the "www" path:

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2Fz5m4EKO8Zv6FGhA9HDcJ%2Faws1.jpg?alt=media&#x26;token=ecd2b8b6-7450-4a82-a946-e3c31aef4b80" alt=""><figcaption></figcaption></figure>

The route record after the update should look like the following:

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FJOd1zWIeUBgrSjLz4vUx%2Fawstrouble2.jpg?alt=media&#x26;token=75834000-e525-430e-83bb-2b1c73037d3a" alt=""><figcaption></figcaption></figure>

Ensure the IAM use with appropriate permissions is logged in to the [AWS Certificate Manager](https://us-east-2.console.aws.amazon.com/acm/home?region=us-east-2#/welcome) and click the **Request** button.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FhyH2u7eduHnhbbZgon2C%2Fawstrouble3.jpg?alt=media&#x26;token=4cc10477-4c52-46de-acf2-c9692fd027ef" alt=""><figcaption></figcaption></figure>

Add the SSL certificate to the Route 53 domain, then validate the cert. Choose the recommended option for validating the certificate.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FKcatgFtmlBN6Cmu3QBCC%2Fawstrouble4.jpg?alt=media&#x26;token=cca4d08d-f8d7-4aed-b27b-e47546f44788" alt=""><figcaption></figcaption></figure>

If a "CNAME" record type is created in the Route 53 domain, verify that it is the issued certificate from the previous step.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2Ffoz6snimFvyihCw87Cer%2Faws5.jpg?alt=media&#x26;token=cd87b7b1-c40b-44b8-884f-ab743e8e3d3e" alt=""><figcaption></figcaption></figure>

Refresh the certificate screen. It should look similar to the following configuration when the certificate has been issued:

{% hint style="warning" %}
&#x20;If the certificate is not issued, delete and reissue the certificate.
{% endhint %}

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FR9jiBfLHj8Kq1Vb6ec0U%2Faws7.jpg?alt=media&#x26;token=c8a31eac-3687-43bc-95e3-3e98e1722f86" alt=""><figcaption></figcaption></figure>

The next steps will add a listener to the load balancer for port 443 (HTTPS).

1. Navigate to the EC2 Dashboard, then open the **Load Balancers** tab from the left pane.
2. On the main screen open the **Listener** tab, then click **Add Listener**.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FsU6MuwMK0tUSsZBUeouL%2Faws8.jpg?alt=media&#x26;token=a5c5998c-465d-46d6-8041-486138a83e32" alt=""><figcaption></figcaption></figure>

3. Set the listener to **HTTPS** and port to **443**, then choose a Security Policy.&#x20;
4. Click the **Select a Certificate** button.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FtFc4bSFi0YcjlmuTCmbr%2Faws9.jpg?alt=media&#x26;token=c7a71291-239c-4d5f-a2e4-ad191262393f" alt=""><figcaption></figcaption></figure>

5. Navigate back to the **Listeners** tab of the Load Balancer pane:

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FRoIzCUjZAxYyH4FOgGc0%2Faws10.jpg?alt=media&#x26;token=0107bf67-92a1-4c6c-8e2c-ffe8ab79637b" alt=""><figcaption></figcaption></figure>

If a small orange warning icon appears next to the port 443 listener, add an Inbound rule for port 443 to the security group.&#x20;

* [ ] Hover over the icon for details on what security group needs to be updated.
* [ ] Navigate to the Security Groups (EC2 Dashboard > Security Groups). Expand the column to determine which security group it is then click **Edit Inbound Rules**.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2F1qicH4lsEYsbyn0XLsbH%2Faws11.jpg?alt=media&#x26;token=995c9bda-3ced-4d5f-bbad-7a0e5c9913c5" alt=""><figcaption></figcaption></figure>

* [ ] Select **HTTPS**, then choose a source. Click **Save Rules**.&#x20;

This should remove the orange caution mark on the listener's tab shown in the previous step:

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FU51oJOodn91Q47RPvQvP%2Faws12.jpg?alt=media&#x26;token=4bc7850c-0e42-4847-95b6-d511f967f2e8" alt=""><figcaption></figcaption></figure>

Navigate to the domain to see if the SSL Certificate has been configured.

### Troubleshooting

If the deployment fails, the best first step is to download the logs for the container. These can be downloaded in the Elastic Beanstalk console by first navigating to your Elastic Beanstalk deployment, and then click on **Logs**.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FrnK4qERfPGHwb84zsxdU%2FEnvironment%20overview%20-%20logs%20%7C%20Elastic%20Beanstalk%20%7C%20us-east-1%202024-08-23%2008-29-09.png?alt=media&#x26;token=9fb6e92b-e133-46b3-b1f5-bb4df4bddcc0" alt=""><figcaption></figcaption></figure>

Next, you will select **Full** from the **Request Logs** dropdown.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FIykObi1OZ3rAKJp8wL2i%2FScreenshot%202024-08-23%2008-30-53.png?alt=media&#x26;token=38f01c53-95a4-4b8f-a796-1ce049403ac5" alt=""><figcaption></figcaption></figure>

Once the logs have downloaded, unzip the logs provided into the local machine. Use a text editor to open the following log file:&#x20;

```
/log/eb-docker/containers/eb-current-app/eb-stdouterr.log
```

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FRVThw2pmUu9O36ttKZnk%2Feb-current-app%202024-08-23%2008-33-06.png?alt=media&#x26;token=05bd0801-0113-4031-b20d-eed0828a0329" alt=""><figcaption></figcaption></figure>

This file will display the logs from the Docker containers, and explains what happened to the server during the deployment process.

One common issue is that it cannot connect to the DocumentDB database, as seen in the following logs:

```
api-server-1   | Uncaught exception:
api-server-1   | Error: Could not connect to the given Database for server updates: mongodb://formio:<PASSWORD>@abcde.cluster-abcdefg6feh.us-east-1.docdb.amazonaws.com:27017/formio?ssl=true&replicaSet=rs0&retryWrites=false.
api-server-1   |     at /src/node_modules/formio/src/db/index.js:255:17
api-server-1   |     at unlock (/src/node_modules/formio/src/db/index.js:77:14)
api-server-1   |     at /src/node_modules/formio/src/db/index.js:254:9
api-server-1   |     at /src/node_modules/formio/node_modules/mongodb/lib/utils.js:695:9
api-server-1   |     at /src/node_modules/formio/node_modules/mongodb/lib/mongo_client.js:285:23
api-server-1   |     at connectCallback (/src/node_modules/formio/node_modules/mongodb/lib/operations/connect.js:367:5)
api-server-1   |     at /src/node_modules/formio/node_modules/mongodb/lib/operations/connect.js:554:14
api-server-1   |     at connectHandler (/src/node_modules/formio/node_modules/mongodb/lib/core/sdam/topology.js:286:11)
api-server-1   |     at Object.callback (/src/node_modules/formio/node_modules/mongodb/lib/core/sdam/topology.js:672:9)
api-server-1   |     at Timeout._onTimeout (/src/node_modules/formio/node_modules/mongodb/lib/core/sdam/topology.js:443:25)
api-server-1   |     at listOnTimeout (internal/timers.js:557:17)
api-server-1   |     at processTimers (internal/timers.js:500:7)
api-server-1   | Error: Could not connect to the given Database for server updates: mongodb://formio:<PASSWORD>@abcde.cluster-abcdefg6feh.us-east-1.docdb.amazonaws.com:27017/formio?ssl=true&replicaSet=rs0&retryWrites=false.
api-server-1   |     at /src/node_modules/formio/src/db/index.js:255:17
api-server-1   |     at unlock (/src/node_modules/formio/src/db/index.js:77:14)
api-server-1   |     at /src/node_modules/formio/src/db/index.js:254:9
api-server-1   |     at /src/node_modules/formio/node_modules/mongodb/lib/utils.js:695:9
api-server-1   |     at /src/node_modules/formio/node_modules/mongodb/lib/mongo_client.js:285:23
api-server-1   |     at connectCallback (/src/node_modules/formio/node_modules/mongodb/lib/operations/connect.js:367:5)
api-server-1   |     at /src/node_modules/formio/node_modules/mongodb/lib/operations/connect.js:554:14
api-server-1   |     at connectHandler (/src/node_modules/formio/node_modules/mongodb/lib/core/sdam/topology.js:286:11)
api-server-1   |     at Object.callback (/src/node_modules/formio/node_modules/mongodb/lib/core/sdam/topology.js:672:9)
api-server-1   |     at Timeout._onTimeout (/src/node_modules/formio/node_modules/mongodb/lib/core/sdam/topology.js:443:25)
api-server-1   |     at listOnTimeout (internal/timers.js:557:17)
api-server-1   |     at processTimers (internal/timers.js:500:7)
```

When this occurs, consider the following processes to resolve the issue:

#### Unable to connect to Database

When a deployment is unable to connect to the database, the following troubleshooting steps may help:

* Verify the database and Elastic Beanstalk are on the same VPC. \
  Do this by navigating to the Elastic Beanstalk deployment and verify the "vpc-" ID is the same as the database.
* Check the Security Group for DocumentDB.\
  Verify that the Elastic Beanstalk environments have Security Groups that can connect to the DocumentDB.  The security group for the DocumentDB should have Incoming network requests that allow TCP communication on the 27017 port as follows:

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FqaWNUqRR4rzprKNPHLiq%2FSecurityGroup%20%7C%20EC2%20%7C%20us-east-1%202024-08-23%2008-43-04.png?alt=media&#x26;token=f765ba52-6a47-4599-8e4a-3a9bba20e462" alt=""><figcaption></figcaption></figure>

* Check your Security Group for Elastic Beanstalk. \
  After verifying that the security group for DocumentDB, check the Security Group for Elastic Beanstalk. Verify that one security group is configured to allow Outbound rules to allow for TCP communication over the 27017 port.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FsRPJHWhdhvWZPCjPCJzr%2FSecurityGroup%20%7C%20EC2%20%7C%20us-east-1%202024-08-23%2008-45-52.png?alt=media&#x26;token=df89ee23-097c-4320-8aaf-b239fc3c9d72" alt=""><figcaption></figcaption></figure>

* Check the Connection string.\
  Verify that it matches the format as documented in the [DocumentDB](#documentdb) section of this walkthrough tutorial.
* Check for expired Certificates being used on the DocumentDB containers.\
  In order to determine if this is the problem. please refer to the next section, "[Fixing Certificate Expiration Issues.](#fixing-certificate-expiration-issues)"

#### Fixing Certificate Expiration issues&#x20;

One common problem for database connection issues is that the Certificate Authority of the DocumentDB has expired and now refuses to connect.

The following procedure will explain how to diagnose and fix the problem:

1. Navigate to the DocumentDB cluster, then click on each instance of the cluster.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FpZZU4fYZTxwSfKIJWUTg%2FClusters%20%7C%20Amazon%20DocumentDB%20%7C%20us-east-1%202024-08-22%2015-55-09.png?alt=media&#x26;token=9496a7be-22c7-4ac8-9f95-75748012673d" alt=""><figcaption></figcaption></figure>

2. Select on **Configurations** and click **Modify**.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FSwtLF0onJbuINRg62lDj%2FInstances%20%7C%20Amazon%20DocumentDB%20%7C%20us-east-1%202024-08-22%2015-56-53.png?alt=media&#x26;token=2aa0dbb0-ad5e-4601-bf6a-89a81c1b8227" alt=""><figcaption></figcaption></figure>

3. Select the *rds-ca-rsa2048-g1* certificate.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FkuBnGAuysFqhcJw8pXKL%2FMonosnap%202024-08-22%2015-58-43.png?alt=media&#x26;token=eb77153a-0ba1-47c4-8836-6b4bcc278a78" alt=""><figcaption></figcaption></figure>

4. Save the settings for this instance.

Repeat the steps above for all instances in the DocumentDB cluster.

Next, navigate to the Elastic Beanstalk deployment. **Click on Application Versions**, then download the version that is used by the server to the local machine.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2F8didpltJ57RvfzevTvL9%2FElastic%20Beanstalk%20%7C%20us-east-1%202024-08-22%2016-01-30.png?alt=media&#x26;token=fd4354d6-7010-4264-95a6-d8ea1682ac5c" alt=""><figcaption></figcaption></figure>

Extract the contents of this ZIP on the local machine. Use a text editor to open the following file:

```
certs/rds-combined-ca-bundle.pem
```

Download the ˆglobal-bunch.pem" file found at the URL:\
<https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem>

Copy the contents of the “global-bundle.pem” file to the clipboard.

Replace **ALL** the contents of the “rds-combined-ca-bundle.pem” file with the contents of the “global-bundle.pem” file. Make sure to save the file.

Create a NEW .zip file by selecting the “docker-compose.xml” file, along with the other folders in that directory, like so:

{% hint style="danger" %}
DO NOT ZIP THE CONTAINING FOLDER.
{% endhint %}

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FOH1kOVr44mSLNhPZelD8%2FMonosnap%202024-08-22%2016-07-44.png?alt=media&#x26;token=4fa5dba8-8d70-47a1-be2e-8a8f71c731a1" alt=""><figcaption></figcaption></figure>

Give the file a label with the form “9.3.0-NEW-CERT.zip”, using the same version as the deployed version.

Upload this new version to the Application Versions.

Select the version that was just uploaded, and deploy to all environments. It should be able to re-connect to the database after a re-deploy.

If deployment issues persist, SSH into the deployment container to diagnose the issues on the actual container instance.

#### SSH into your deployments

There are many reasons why Docker containers may fail to start. When this happens, troubleshoot the reason by inspecting the logs from those containers.

This can usually be done by downloading the logs from the Elastic Beanstalk. On some rare occasions (such as when a License has been disabled) the containers will not create the logs.

When this occurs, the best course of action is to SSH into the EC2 containers to diagnose the problem by completing the following steps:

1. Create a KeyPair to enable the SSH.\
   Do this by navigating to the **EC2** section of AWS, and then clicking on **Key Pairs**. Then click **Create key pair.**

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MPHoF2HwOA0s5HV_AIB%2F-MX8o7FDmrLLKnplhDtt%2F-MXAalq7UkvhtjY_rT2T%2FKey%20pairs%20%7C%20EC2%20Management%20Console%202021-03-31%2023-02-08.png?alt=media\&token=d65fd0e2-78b4-497f-8bbd-23f9272e5264)

2. Follow the instructions to create a new key pair.\
   When completed, download the private key onto the local machine. Ensure that this downloaded key has the correct permissions by executing the following command:

```
chmod 0400 my-key.pem
```

3. Navigate to the Elastic Beanstalk deployment, and then edit the **Configurations** for the deployment. Click **Edit** on the **Security** section.

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MPHoF2HwOA0s5HV_AIB%2F-MX8o7FDmrLLKnplhDtt%2F-MXAbkBA8E5771N7gN5S%2FFormioenterprise-env%20-%20Configuration%202021-03-31%2023-08-28.png?alt=media\&token=5fb992fe-2e42-4055-8497-bf210ec859b3)

4. Select the new key pair and click **Save**.
5. Once the deployment is finished making these updates, go to the **EC2** section of AWS, then click on **Instances.**
6. Find the instance that is associated with the deployment. Copy the **Public DNS n**ame of that instance.

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MPHoF2HwOA0s5HV_AIB%2F-MXAcPJOONHOnAaNIUYd%2F-MXAchKYjAgwfOFtqJs2%2FInstances%20%7C%20EC2%20Management%20Console%202021-03-31%2023-12-28.png?alt=media\&token=b03f7129-9c74-44ee-92ef-0897b151366d)

You can now ssh into the instance by with the following command:

```
ssh -i ./my-key.pem ec2-user@ec2-xx-xx-xx-xx.eu-central-1.compute.amazonaws.com
```

After logging into the instance, perform the following to see the Docker images:

```
sudo su
docker ps -a
```

This should display the failed container, as seen here:

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MPHoF2HwOA0s5HV_AIB%2F-MX8o7FDmrLLKnplhDtt%2F-MXAVCniHHEZrb_U3xrB%2F2021-03-31%2022-35-22.png?alt=media\&token=bfbb41e2-c10b-4b54-ace9-11392d0c5e07)

Copy the **Container ID** of one of the failed containers. Use the following command to SSH into the failed container:

```
docker commit [CONTAINER_ID] formio-debug
docker run -it \
    -e "LICENSE_KEY=---LICENSE KEY---" \
    -e "MONGO=--- MONGO CONNECTION STRING ---" \
    -e "PORTAL_ENABLED=true" \
    -e "DEBUG=true" \
    -e "ADMIN_EMAIL=admin@example.com" \
    -e "ADMIN_PASS=CHANGEME" \
    -e "DB_SECRET=CHANGEME" \
    -e "JWT_SECRET=CHANGEME" \
    -e "FORMIO_S3_BUCKET=--- PDF BUCKET ---" \
    -e "FORMIO_S3_KEY=--- S3 KEY ---" \
    -e "FORMIO_S3_REGION=us-west-2" \
    -e "FORMIO_S3_SECRET=---- S3 SECRET ---" \
    --rm --entrypoint sh formio-debug
```

{% hint style="info" %}
Change the values in the command to the values configured when deploying the Elastic Beanstalk.
{% endhint %}

Try to manually run the software with the following commands:

#### For pdf-server:

```
node pdf.js
```

#### For formio-enterprise:

```
node formio.js
```

This will output the reason it failed to start. For example, here is an output from a PDF server that could not start:

![](https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MPHoF2HwOA0s5HV_AIB%2F-MX8o7FDmrLLKnplhDtt%2F-MXAVY9cWuO0M4BIN__T%2F2021-03-31%2022-36-57.png?alt=media\&token=559252c4-c0b2-4738-a5d2-50099eadbc96)

This indicates the license for this server has been disabled.
