AWS Deployment
Last updated
Last updated
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.
This procedure assumes the user has an account with Amazon AWS.
First, download the Form.io multicontainer ZIP archive which includes everything required to deploy to AWS: https://github.com/formio/deploy/blob/main/deployments/compose/multicontainer.zip
certs/global-bundle.pem:
A "certificate bundle" that provides the Certificate Authority keys so that the Form.io deployment can connect to an Amazon Document DB cluster using SSL/TLS. Amazon provides global-bundle.pem for all AWS regions, as well as many region-specific bundles in the "Download certificate bundles" section of the Amazon RDS documentation.
conf.d/default.conf
: The nginx reverse proxy configuration file. By default, this configuration simply redirects traffic from the '/' endpoint to your Enterprise Server Container, and traffic from the '/pdf' endpoint to your PDF Server container.
docker-compose.yml
: The Docker Compose file that defines the services (containers) that run in your multicontainer deployment and how they interrelate. For example, it defines the nginx proxy (and points that container to the path of the default.conf
file above) and "links" it to the Enterprise Server and the PDF Server containers.
Before deployment, create a database to store all the Forms and Submissions within the Form.io deployment. DocumentDB is an AWS managed NoSQL database that can store projects, forms, and submissions.
In the AWS Console, type DocumentDB and click on the link that says Amazon DocumentDB.
On the next page, click on the button that says Launch Amazon DocumentDB.
In the next section, configure the instance with the following parameters:
Cluster Identifier: Keep default or type a unique name.
Engine Version: 5.x and below.
Instance Class:
Production environment: At least db.r5.large
Development environment: At least db.t3.medium
Number of Instances:
Production Environment: At least 2
Development Environment: At least 1
The following diagram illustrates a typical configuration in a Development environment:
In the next section, provide a Master username and a secure password.
Press Create Cluster button.
Now that the DocumentDB cluster is created, click on the cluster link, and copy the application connection string. It should look like the following:
This connection string must be converted to a standard connection string. To do so:
Remove everything after the “:27017/”, and then append the database name to the end, for example, "formio". It should look like:
2. replace <insertYourPassword>
with the Master Password entered in the Authentication fields above. This example uses "badpassword":
Add ?tls=true&readPreference=secondaryPreferred&retryWrites=false
to the end of the URL to indicate a database connection over SSL, and to disable retryWrites since DocumentDB does not support it:
Make sure to copy this connection string for use later.
Lastly, 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.
Before setting up API and PDF servers, set up an S3 Bucket which will contain the uploaded PDFs used by the PDF server. To set up an S3 bucket:
From the Amazon AWS home, type S3 in the Search bar. Click on S3 in the Search results.
On the next page, click on the Create Bucket button.
Next, under General Settings, give it a unique Bucket Name.
Skip over all the other sections, leaving the default configurations. At the bottom of the page, press Create Bucket to create a new S3 bucket.
With the S3 bucket created successfully, create an IAM role with admin rights to this S3 bucket. To do so:
From the AWS home, type IAM in the Search bar.
Within the IAM page, create a new user by clicking on Users and then clicking on Create User.
Specify the user's details. When making a role that will interact with the PDF server, a descriptive name such as pdf-server is helpful. Click Next.
In the Set Permissions page, select Attach existing policies directly, and then select Create Policy.
On the "Specify Permissions" page, under "Select a Service", select S3.
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.
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.
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.
For the remaining Resources, click on each one and enable Any in this account for all of them. It should look like the following:
Click the Next button to view the Review and Create page. Name the policy "pdf-server-s3" and click on the Create policy button.
Now that a policy has been created, the policy must be attached to the IAM role by going back to the AWS home, clicking the Refresh icon, and then searching for pdf-server-s3 in the search bar.
Click Next in the IAM wizard to view the Review and Create page, then click Create User to return to the list of Users.
Select the newly created user and navigate to Security Credentials.
Click Create Access Key, the select Third-party Service. Enter a description for its use.
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!
Now that the database and S3 have been configured, this deployment will use AWS Elastic Beanstalk to manage the Docker deployments.
Before proceeding, configure an EC2 instance profile so the underlying instances can interact with Elastic Beanstalk.
Navigate to the IAM Dashboard.
On the left-hand navigation menu, select Roles.
In the upper right, click Create Role.
Select AWS Service for the Trusted Entity Type, and EC2 for the Use Case, then click Next.
Filter the Permissions Policies by the string "ElasticBeanstalk" and select each of the following:
AWSElasticBeanstalkWebTier
AWSElasticBeanstalkWorkerTier
AWSElasticBeanstalkMulticontainerDocker
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.
Click Create Role to complete the process.
Next, proceed with the Elastic Beanstalk Deployment:
Navigate to the Elastic Beanstalk Dashboard.
Click on the Create Application link. Depending on the AWS confogiration, it may instead read Create New Environment.
Select Web Server Environment and provide a meaningful Application Name.
Select Docker as the managed platform:
Select Upload your code and upload the multicontainer.zip file linked above. Give the version a meaningful label.
IMPORTANT NOTE: This multicontainer.zip file assumes you are using DocumentDB. If you are using any other external database provider, or an internal Community Edition database, then you will need to extract this ZIP file, open up the docker-compose.yml file and then remove the lines that reference the MONGO_CA environment variable. Otherwise the database connection will try to use the AWS certificate to your external database provider and the connection will fail.
Under Presets, select High Availability.
Click Next to proceed to service access configuration.
Select Use an existing service role and select aws-elasticbeanstalk-service-role under Existing service roles.
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" for more information.
Select the role created in the IAM dashboard above under EC2 instance profile.
Click Next to proceed to networking, database, and tag configuration.
Select the same VPC and Instance Subnets provided to the DocumentDB cluster above. A typical deployment will run the instances in private subnets, and the load balancer in public subnets.
Click Next to proceed to instance traffic and scaling.
Select General Purpose (SSD) under Root Volume Type.
Increase the size of the storage for each instance from the default of 8GB to 12GB, since the PDF server container will store a large volume of fonts. These can be fine tuned later based on the deployment requirements.
Under EC2 Security Groups, select the security group created in the DocumentDB cluster above.
Select the desired capacity settings. The follow instance types are suggested
Environment Type | Instance Size |
Development Environments | t3.medium, or higher |
Production Environments | t3.large, or higher |
Use the default Load Balancer, Listeners, Processes, and Rules settings. TLS listeners are configured later in this documentation.
Click Next to navigate to updates, monitoring, and logging configuration.
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.
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 your remote database. This is the value we copied before. | mongodb://formio:badpassword@docdb-2019-02-05-03-07-17.cluster-otsyrtio9xoe.us-east-1.docdb.amazonaws.com:27017/formio?ssl=true&retryWrites=false |
LICENSE_KEY | The license key for your deployment. You will get this when you upgrade a project to Enterprise. | <—YOUR LICENSE—> |
PORTAL_ENABLED | Used to enable the Self-Hosted Portal | true |
ADMIN_EMAIL | An admin account you would like to use as the first Admin user. | admin@example.com |
ADMIN_PASS | A password for the first Admin user. | CHANGEME |
DB_SECRET | A secure secret that you will pick 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 you will pick that is used 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 |
*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.
If you wish to secure your Environment Variables from visibility, then we recommend looking into the Amazon Key Management Service @ https://aws.amazon.com/kms.
If you wish to secure your environment variables from visibility, consider Amazon Key Management Service.
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.
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.
Once logged into the Developer Portal, click Create Project.
In the popup modal, give the project a title, then click Create Project.
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.
To get begin:
Navigate to the AWS homepage and then search for Route 53.
From the left pane, select Hosted zones and click Create hosted zone.
Provide the domain name and click Create hosted zone.
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:
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.
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".
Create basic records in Route 53. The following example shows a record for both the root path and for the "www" path:
The route record after the update should look like the following:
Ensure the IAM use with appropriate permissions is logged in to the AWS Certificate Manager and click the Request button.
Add the SSL certificate to the Route 53 domain, then validate the cert. Choose the recommended option for validating the certificate.
If a "CNAME" record type is created in the Route 53 domain, verify that it is the issued certificate from the previous step.
Refresh the certificate screen. It should look similar to the following configuration when the certificate has been issued:
If the certificate is not issued, delete and reissue the certificate.
The next steps will add a listener to the load balancer for port 443 (HTTPS).
Navigate to the EC2 Dashboard, then open the Load Balancers tab from the left pane.
On the main screen open the Listener tab, then click Add Listener.
Set the listener to HTTPS and port to 443, then choose a Security Policy.
Click the Select a Certificate button.
Navigate back to the Listeners tab of the Load Balancer pane:
If a small orange warning icon appears next to the port 443 listener, add an Inbound rule for port 443 to the security group.
This should remove the orange caution mark on the listener's tab shown in the previous step:
Navigate to the domain to see if the SSL Certificate has been configured.
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.
Next, you will select Full from the Request Logs dropdown.
Once the logs have downloaded, unzip the logs provided into the local machine. Use a text editor to open the following log file:
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:
When this occurs, consider the following processes to resolve the issue:
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:
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.
Check the Connection string. Verify that it matches the format as documented in the 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."
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:
Navigate to the DocumentDB cluster, then click on each instance of the cluster.
Select on Configurations and click Modify.
Select the rds-ca-rsa2048-g1 certificate.
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.
Extract the contents of this ZIP on the local machine. Use a text editor to open the following file:
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:
DO NOT ZIP THE CONTAINING FOLDER.
Give the file a label with the form “8.5.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.
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:
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.
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:
Navigate to the Elastic Beanstalk deployment, and then edit the Configurations for the deployment. Click Edit on the Security section.
Select the new key pair and click Save.
Once the deployment is finished making these updates, go to the EC2 section of AWS, then click on Instances.
Find the instance that is associated with the deployment. Copy the Public DNS name of that instance.
You can now ssh into the instance by with the following command:
After logging into the instance, perform the following to see the Docker images:
This should display the failed container, as seen here:
Copy the Container ID of one of the failed containers. Use the following command to SSH into the failed container:
Change the values in the command to the values configured when deploying the Elastic Beanstalk.
Try to manually run the software with the following commands:
This will output the reason it failed to start. For example, here is an output from a PDF server that could not start:
This indicates the license for this server has been disabled.