Azure Deployment
Microsoft Azure is perfect for Enterprise customers who wish to have a very 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.
A Resource Group is a logical container that holds related resources for an Azure solution. When you create a resource, you need to specify a resource group to host it.
Once you create a new Azure account, the first thing you will want to do is to create a Resource Group that will contain all of the deployments from this walkthrough.
You can do this by clicking on the Resource Groups menu item on the left side of the screen, and then from the Resource Group Dashboard click the + Create button.
- Latency: Choose a region that is closest to your users to minimize latency.
- Compliance: Some regions may be required for compliance with certain regulations or standards.
- Pricing: Prices for resources can vary by region. You may want to consider the cost of resources in different regions to help determine the best fit for your needs.
- Geography: Some regions may be more suitable for your needs based on geography.

Microsoft Azure Resource Group Dashboard
After you click on the + Create button, you will be asked to give a name to your Resource Group and select a region for it to be located in.
This information is important because it helps to identify and organize your resources, and determines where they will be hosted. Please make sure to choose a name and region that best suits your needs.

Select Subscription, Add Resource Group Name, Select Region, then press Review + create
Now that you have a resource group, you can now add all your other resources within this group, starting with a Cosmos database.
Form.io requires a MongoDB compatible database to run its platform. While you could setup a stand alone MongoDB or even use MongoDB Atlas, for Azure, it is also perfectly reasonable to use CosmosDB for the database. Follow these instructions to setup a new database.
- In the left hand column, click on the menu item that says Azure Cosmos DB
- Click on the + Create button
- When asked "Which API best suits your workload?" select Azure Cosmos DB for MongoDB

- On the Basics tab of the Azure Cosmos DB setup page select the previously created Resource Group, then enter a Cosmos DB Account Name, then select a location. It is recommended choose the same location to minimize latency between resources.

- You will then wait a few minutes for your database to create.
- After this is complete, you will then click on Connection String.

- You will now make a copy of the connection string, and then place it in a Text editor. Form.io does require that you use a standard connection string, so you will need to make a small change to what Azure provides you by adding your database name to the connection string. This is placed right after the formio.documents.azure.com:10255/ and before the text ?ssl=true. It should look like the following.
mongodb://formio:[PASSWORD]@formio.documents.azure.com:10255/formio?ssl=true&replicaSet=globaldb
- You will also need to add the variable retrywrites=false to your connection string as well as follows.
mongodb://formio:[PASSWORD]@formio.documents.azure.com:10255/formio?ssl=true&replicaSet=globaldb&retrywrites=false
- Make sure you save this modified connection string in a Text editor for later usage.
Please Note In Cosmos DB (set to Mongo DB) version 3.6: In order to do a sort on a property, there must be an index set. This is different from how MongoDB works as MongoDB allows sorting on any property regardless of an index being set. To resolve this, a wildcard index can be added to the following collections:
db.submissions.createIndex( {"$**": 1 } );
db.forms.createIndex( {"$**": 1 } );
db.projects.createIndex( {"$**": 1 } );
db.actions.createIndex( {"$**": 1 } );
db.roles.createIndex( {"$**": 1 } );
DEPRECATED: Announced February 24, 2022 Azure Blob Storage Minio gateway would be deprecated within 6 months. This means that the Minio gateway is no longer supported by Azure, and users are encouraged to migrate to alternative solutions.
The Minio gateway was a feature of Azure Blob Storage that allowed users to access their Azure storage using the Minio API. It was designed to provide compatibility with Minio client libraries and tools, making it easier for users to interact with their Azure storage from Minio-based applications.
What does this mean for Form.io customers?
Azure Blob Storage integration is only available in version 4.0.0 and greater. If you are using an older version of the product, you will need to upgrade to access this feature.
What if I am unable to upgrade to version 4.0.0?
Use a Minio image to the last version that supported Azure Gateway (minio/minio:RELEASE.2022-04-29T01-27-09Z) so you can still use S3 environment settings w/ PDF server 3.4.0
Click here for more information on installing a MinIO File Server
In order to get PDF File uploads working, you will now need to create an Azure Blob to store all of the pdf files that are uploaded.
To setup this, please perform the following.
- Click on Storage Accounts in the left navigation bar, then click + Create
- Select your existing Resource Group
- Add a Storage Account Name, and select your preferred replication method
- In the Advanced tab enable Enable hierarchical namespace, then enable the checkbox for Enable SFTP
- Click Create, this will take a few moments to create the Storage Account. When it has finished open the side drawer and under Data Storage section select Containers.
- Once on the Containers page press + Container, you will be prompted to create a name for this container, then select the Public Access Level for Blob Storage. When finished press Create.
- This will now create a new Blob Storage for your Azure Account
- Once the instance is created in the side bar menu underneath Security + networking then click on Access Keys option.
- Copy the Connection String from Access Keys section, this will be used when configuring a projects File Storage settings and the PDF Server.

Copy connection for use in File Storage settings and when starting PDF server
- Next will want to configure the Resource Sharing (CORS) options for the Blob Service. Please choose settings most suitable for your requirements. We used the following settings for this guide.
- Allowed origins and Allow headers are set to *
- Allowed methods are set to GET, HEAD, OPTIONS, and PUT

Click "Resource Sharing" to open CORS page, add Blob Service options, press Save when done.
NOTE: You can also use the following above to provide settings for the File Upload component. The documentation for this is provided in our
You are now ready to setup your hosted Virtual Machine.
DEPRECATION WARNING: On August 31, 2024, Azure will retire Basic and Standard A-series virtual machines (VMs). Before that date, migrate your workloads to Av2-series VMs, which provide more memory per vCPU and faster storage on solid-state drives (SSDs).
You will now setup the API Server by using the Azure Container Instances setup.
- An On-Premise Enterprise license is required to complete this installation
- In the left menu, click on the Virtual Machines menu item, and then press + Create button.
- In the dropdown select Azure Virtual machine.
- Click the link that says See all images underneath the Image field.
- In the see all images, type the word Docker, and then click on the Docker on Ubuntu Server
- You will now need to select your Instance for your machine. Please note that Azure does not make all VM sizes available in every region so select region and VM size carefully. We recommend the following.
- Test Environments - A1_v2 Standard
- Production Environments - A6 Standard

Select Resource Group, Add a virtual machine name, select availability options, select VM size.
- Next, will we setup a root user account credentials for SSH access.

Set the root access user information for connecting to Azure VM via SSH
- At the bottom left of the page there will be a Review + create button. Click on this button to launch the Virtual Machine.
- You will now wait for this machine to be created, and once it is, we will need to open up the HTTP port 80 on this machine.
- To do this, you will click on this machine in the Virtual Machines section, and then click on Endpoints and then click + Add
- We will now configure the following endpoint.
- Name: HTTP
- Protocol: TCP
- Public Port: 80
- Private Port: 80
- Press OK
- Now that we have an HTTP port open on this machine, we can now SSH into the machine using your computers Terminal.
- To login to this machine, you will first need to get the Public IP Address by clicking on the Overview tab.
- You will then see the Public IP Address, which you will then need to copy.

In order to login via SSH to your server copy the Public IP Address.
- Next, you will open up a Terminal on your local computer and type the following.ssh [user]@[publicIpAddress]Make sure you replace
[user]
with the username that you used to create the virtual machine, and the[publicIpAddress]
with the name you just copied. - You will then be prompted to enter your password which you will enter the same password you provided when you created the virtual machine.
- You should then see the console of the Ubuntu virtual machine. You will now download the Docker containers. While it is recommended to put the API Server and the PDF Server on separate Virtual machines, for this example, we will just download both of them on the same machine.
- docker pull formio/formio-enterprise:$IMAGE_VERSIONdocker pull formio/pdf-server:$IMAGE_VERSION
- You will now need to create an “internal” network that you will use to connect all the internal docker containers together.docker network create formio
- Next we will spin up our API Server using the following command.## Start Form.io API Serverdocker run -d \-e "LICENSE_KEY=$YOURLICENSE" \-e "MONGO=mongodb://formio:[PASSWORD]@formio.documents.azure.com:10255/formio?ssl=true&replicaSet=globaldb" \-e "PORT=3000" \-e "PORTAL_ENABLED=true" \-e "[email protected]" \-e "ADMIN_PASS=CHANGEME" \-e "DB_SECRET=CHANGEME" \-e "JWT_SECRET=CHANGEME" \-e "PDF_SERVER=http://pdf-server:4005" \--restart unless-stopped \--network formio \--link pdf-server:pdf-server \--name formio-server \-p 3000:3000 \formio/formio-enterprise:$IMAGE_VERSIONYou will need to make sure that you change out the values for ADMIN_PASS, JWT_SECRET, DB_SECRET, MONGO to be the values that you saved in your editor during the setup process.
- After this runs for a minute, you should then be able to type the following to check on the status.
- Next, we will deploy our PDF server to point to both the API server + Minio File Server.## Start Form.io PDF Serverdocker run -itd \-e "LICENSE_KEY=$YOURLICENSE" \-e "MONGO=mongodb://formio:[PASSWORD]@formio.documents.azure.com:10255/formio?ssl=true&replicaSet=globaldb" \-e "FORMIO_AZURE_CONNECTION_STRING=$YOURCONNECTIONSTRING" \-e "FORMIO_AZURE_CONTAINER=pdfs" \--network formio \--restart unless-stopped \--name pdf-server \-p 4005:4005 \formio/pdf-server:$IMAGE_VERSION
- Once this is running, you should be able to type the following.docker logs pdf-serverand then see the following.
- You should now have two public ports accessible on this machine.
- API Server: Port 3000
- PDF Server: Port 4005
- We can now make all of this fall under a single HTTP port by configuring an NGINX proxy on our server.
In order to bring all of these locally hosted servers into a single HTTP interface, we can use NGINX to sit in front of these servers.
To setup this configuration, please go through the following steps.
- Install NGINX using the following command.sudo apt-get updatesudo apt-get install nginx
- We can check to ensure that we have NGINX running with the following command.systemctl status nginx
- We now need to edit the nginx.conf file to redirect HTTP traffic to the internal servers.sudo nano /etc/nginx/sites-available/formio
- Put the following contents in that file.server {listen 80;server_name ~^(www\.)?(.+)$;client_max_body_size 20M;############# Use the following for SSL ################# listen 443 ssl;# ssl_certificate /usr/local/etc/nginx/nginx.crt;# ssl_certificate_key /usr/local/etc/nginx/nginx.key;########################################################location / {proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;proxy_pass http://localhost:3000;proxy_read_timeout 90;proxy_redirect http://localhost:3000 https://$host;}location /pdf/ {rewrite ^/pdf/(.*)$ /$1 break;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;proxy_pass http://localhost:4005;proxy_read_timeout 90;proxy_redirect http://localhost:4005 https://$host;}}server {listen 80;server_name ~^minio.(.+)$;client_max_body_size 20M;############# Use the following for SSL ################# listen 443 ssl;# ssl_certificate /usr/local/etc/nginx/nginx.crt;# ssl_certificate_key /usr/local/etc/nginx/nginx.key;########################################################location / {proxy_buffering off;proxy_set_header Host $http_host;proxy_pass http://localhost:9000;}}Note, for this configuration to work with Minio, you will need to create a subdomain @ http://minio.yourserver.com that points to this server. Minio does not support being hosted outside of the root domain.
- Now save that file, and then switch this out for the
default
serversudo rm /etc/nginx/sites-enabled/defaultsudo ln -s /etc/nginx/sites-available/formio /etc/nginx/sites-enabled/defaultsudo systemctl restart nginx - We can now test that we have both an API server and a PDF Server running by going to the following URLs in our Browser.
- http://formio-server-6ht0yqu8.cloudapp.net/status (should show the API Server status)
- http://formio-server-6ht0yqu8.cloudapp.net/pdf/ (should show the PDF Server status)
Azure App Service is a fully managed platform-as-a-service (PaaS) that allows developers to build, deploy, and scale web, mobile, and API applications.
In this section, we will deploy a docker-compose.yml file to Azure App Service and connect it to the CosmosDB and Blob Storage services previously mentioned.
- Within your Azure portal, click on + Create at the top left of the page above the Filter for any field.

- Once you've pressed you will then be directed to a page called Create Web App. The below headings outlines the tabs and sections of this page.
- Project Details
- Select a Resource Group under the Project Details section.

- Instance Details
- Enter a Web App name for the Name setting.
- Select Docker Container as the option for Publish setting.
- Operating System should be Linux as default option selected.
- For Region, would recommend using the same region that your Cosmos DB is running for this tutorial. Be aware that choosing certain regions will affect your options for Zone redundancy.
- Pricing Plans
- NOTE: Availability of instance types will vary across regions.
- Select a pricing plan that is suitable for your needs, for this tutorial we used Basic B1 for our development environment.
- Select Docker Compose as the option for Options setting.
- Select Docker Hub as the option for Image Source setting.
- Leave Public as the default option for Access Type.
- Next you will want to download azure-app-service-multicontainer.zip below and extract the contents to a folder.
azure-app-service-multicontainer.zip
2KB
Binary
The docker-compose.yml below (extracted from zip file) will be uploaded to Azure App Service, we cannot use a volume to point at our nginx.conf due to Azure App Service only allows us to upload the Docker compose file to the Configuration setting.
As a workaround we've built a custom docker container with the nginx.conf pre-configured as a custom image.
## FILE: docker-compose.yml
version: '3'
#########################################################
## DOCKER NETWORK
#########################################################
networks:
formio-network:
driver: bridge
services:
##############################################
## PROXY
##############################################
proxy:
container_name: proxy
image: ryanformio/formio-proxy
ports:
- 80:80
links:
- api-server
- pdf-server
networks:
- formio-network
## Comment out if running locally, for streaming logs to Azure
logging:
driver: stdout
##############################################
## API SERVER
##############################################
api-server:
container_name: api-server
image: formio/formio-enterprise:8.0.0
environment:
PORT: 3000
DEBUG: "formio.*"
PDF_SERVER: http://pdf-server:4005
PORTAL_ENABLED: 1
MONGO: ${MONGO}
LICENSE_KEY: ${LICENSE_KEY}
ADMIN_KEY: ${ADMIN_KEY}
ADMIN_EMAIL: ${ADMIN_EMAIL}
ADMIN_PASS: ${ADMIN_PASS}
DB_SECRET: ${DB_SECRET}
JWT_SECRET: ${JWT_SECRET}
networks:
- formio-network
## Comment out if running locally, for streaming logs to Azure
logging:
driver: stdout
##############################################
## PDF SERVER
##############################################
pdf-server:
container_name: pdf-server
image: formio/pdf-server:5.0.0-rc.3
ports:
- "4005:4005"
environment:
MONGO: ${MONGO}
LICENSE_KEY: ${LICENSE_KEY}
FORMIO_AZURE_CONNECTION_STRING: ${FORMIO_AZURE_CONNECTION_STRING}
FORMIO_AZURE_CONTAINER: ${FORMIO_AZURE_CONTAINER}
FORMIO_PDF_PORT: 4005
DEBUG: "pdf.*"
networks:
- formio-network
## Comment out if running locally, for streaming logs to Azure
logging:
driver: stdout
- After uploading the docker-compose.yml file to the Configuration option in the Docker Hub Options section you can jump to the Review + create to vaildate the configuration.
- If satisfied click Create button at the bottom left side of the of the page.

- Once the App Service resource has been created you should have clicked Go to Resource, where you will be directed to an Overview page for the App Service.
- On the left-side column underneath the Settings section select Configuration.
- Once on the Configuration page click on Advanced Edit.

- Copy and Paste the json from env.json in the azure-app-service-multcontainer.zip above.
- Edit the environment variables to for your environment before clicking OK.

- Once you've finished editing your environment variables in the Advanced Editing section click Save button to persist your current configuration.
- The logs are not turned on by default so as a last step go to App Service Logs on the side bar underneath the Monitoring seciton.
- Where it says Application Logging toggle it to File System, and set some quota thresholds and a log retention period.

- That is all you need to configure the logs, you can now move on to configuring the Cosmos DB Firewall to accept the Virtual IP address from our Azure App Service deployment.
If you followed along and reach this point and are receiving connection issues with the database. The most likely cause is that you will need to register the Azure App Service IP address with your Cosmos DB Firewall.
- In the Overview page of the Azure App Service, copy the Virtual IP address under the Networking section.
- To add your IP to the Firewall settings in Cosmos DB first select the database. Then in the left bar under Settings select the Networking option.

- In the Firewall section of the Cosmos DB Networking page add the Virtual IP address from the Azure App Service Networking section.