# Azure App Service

[**Azure App Service**](https://azure.microsoft.com/en-us/products/app-service/#overview) is a fully managed platform-as-a-service (PaaS) that allows developers to build, deploy, and scale web, mobile, and API applications.

## Create Azure App Service

1. Within your Azure App Service Dashboard, click on **+ Create** at the top left of the page above the Filter for any field.
2. This will navigate you to a page called **Create Web App.**
3. On the **Basics Tab** enter these settings.
   * Under Project Details choose a **Subscription**
   * Under the Project Details choose a **Resource Group**
   * Under Instance Details enter an **App Service Name**.
   * Under Instance Details select **Docker Container** as the **Publish** method.
   * Under Instance Details choose **Linux** as the **Operating System**.
   * Under Instance Details select a **Region.**
     * Recommend using the **same region that your Cosmos DB** is running in. Be aware that choosing certain regions will affect your options for Zone redundancy.
   * Under Pricing Plans choose a **Linux Plan.** Dependent on the chosen region.
   * Under Pricing Plans choose a **Pricing** **Plan** that is suitable for your environment requirements. Dependent on the chosen region.

{% hint style="info" %}
**NOTE:** Availability of instance types will vary across regions.
{% endhint %}

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FS6anh77PFtJFdsI44j84%2FScreenshot%202023-07-28%20130458.png?alt=media&#x26;token=3249435c-c116-45ac-a47d-0ddd49a65e94" alt=""><figcaption></figcaption></figure>

## Single Container Azure App Service

{% hint style="info" %}
**NOTE:** Single Container deployment of Azure App Service does not require the use of a Nginx container deployment.
{% endhint %}

1. On the **Docker Tab** enter these settings.

   * For **Options** select **Single Container**.
   * For **Image Source** choose **Docker Hub**.
   * Under Docker hub options for **Access Type** choose **Public**
   * Under Docker hub options for **Image and Tag** enter path to the image on [API Server Docker Hub Registry](https://hub.docker.com/r/formio/formio-enterprise/tags). *Example:* *formio/formio-enterprise:9.3.0*

   <figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FvsjM50rZpoqlXdIg2hfK%2Fimage.png?alt=media&#x26;token=c0f0e377-08b1-4a0f-a31d-8d1aef585924" alt=""><figcaption></figcaption></figure>
2. On the **Review + create** tab review the App Service settings then press the **Create** button.
3. To deploy the **PDF server** repeat the steps in [Create Azure App Service](#create-azure-app-service)&#x20;
4. On the **Docker Tab** enter these settings.

   * For **Options** select **Single Container**.
   * For **Image Source** choose **Docker Hub**.
   * Under Docker hub options for **Access Type** choose **Public**
   * Under Docker hub options for **Image and Tag** enter path to the image on [PDF Server Docker Hub Registry](https://hub.docker.com/r/formio/pdf-server/tags). *Example:* *formio/pdf-server:5.6.0*

   <figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FwemUYh86DMLTPVogPNEY%2Fimage.png?alt=media&#x26;token=90aef1fc-ec6f-4067-af12-c782efdad70d" alt=""><figcaption></figcaption></figure>
5. On the **Review + create** tab review the App Service settings then press the **Create** button.
6. Upon completion of the previous steps of the Single Container deployment on Azure App Service you can skip the "Multi-container Azure App Service" section and continue with steps following [Adding Environment Variables](#adding-environment-variables).

## Multi-container Azure App Service

{% hint style="info" %}
**NOTE:** Azure App Service option for Docker Compose has been in [**Preview**](https://learn.microsoft.com/en-us/azure/app-service/quickstart-multi-container).&#x20;

*Preview features let you opt in to new functionality before it's released. Some preview features are available to anyone who wants to opt in.*

Review [Microsoft Azure Preview Policy](https://azure.microsoft.com/en-us/support/legal/preview-supplemental-terms/) before utilizing the multi-container deployment.
{% endhint %}

In this section, we will deploy a **docker-compose.yml** file to **Azure App Service** and connect it to the **Cosmos DB** and **Blob Storage** services previously mentioned.&#x20;

{% file src="<https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FaygwLuqzIAvffFx3GXSI%2Fformio-multicontainer-azure-app-service.zip?alt=media&token=7daa991f-3f1c-4a14-b363-a15fcd5294a2>" %}

1. On the **Docker Tab** enter these settings.
   * For **Options** select **Docker Compose (Preview)**.
   * For **Image Source** choose **Docker Hub**.
   * Under Docker hub options for **Access Type** choose **Public**
   * For your **Configuration File** select the `docker-compose.yml` from the [downloaded zip](https://help.form.io/deployments/deployment-guide/cloud-deployment/azure/azure-app-service) at the top of this page.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FyjkiPlOQsPNqUn5mWaOo%2FScreenshot%202023-07-28%20131631.png?alt=media&#x26;token=1e4df672-f4b3-4578-8c2a-04b0e187196c" alt=""><figcaption></figcaption></figure>

{% code title="docker-compose.yml" lineNumbers="true" %}

```yaml
## FILE: docker-compose.yml
version: '3'
services:
  ###############################################################################################################
  ## Nginx Proxy
  ##-------------------------------------------------------------------------------------------------------------
  ## Documentation for Azure Volume Mount Storage
  ## https://stackoverflow.com/questions/64019780/create-volume-for-container-running-on-azure-app-service-linux
  ## https://learn.microsoft.com/en-us/azure/app-service/tutorial-multi-container-app#modify-configuration-file
  ###############################################################################################################
  nginx:
    container_name: nginx
    image: nginx
    restart: always
    volumes:
      - ${WEBAPP_STORAGE_HOME}/site/wwwroot/conf.d:/etc/nginx/conf.d
    ports:
      - 80:80
    links:
      - api-server
      - pdf-server
    ## 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:9.3.0
    restart: always
    ports:
      - "3000:3000"
    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}
    ## Comment out if running locally, for streaming logs to Azure
    logging:
      driver: stdout
  ##############################################
  ## PDF SERVER (Optional)
  ##############################################
  pdf-server:
    container_name: pdf-server
    image: formio/pdf-server:5.6.0
    restart: always
    ports:
      - "4005:4005"
    environment:
      LICENSE_KEY: ${LICENSE_KEY}
      MONGO: ${MONGO}
      FORMIO_AZURE_CONNECTION_STRING: ${FORMIO_AZURE_CONNECTION_STRING}
      FORMIO_AZURE_CONTAINER: ${FORMIO_AZURE_CONTAINER}
      FORMIO_PDF_PORT: 4005
      DEBUG: "pdf.*"
    ## Comment out if running locally, for streaming logs to Azure
    logging:
      driver: stdout
```

{% endcode %}

5. On the **Review + create** tab review the App Service settings then press the **Create** button.

### Configure Volume Mount Storage for Nginx Proxy

1. From the App Service Dashboard on the left side navigation panel, locate **Development Tools** and select **Advanced Tools** option. Then the **Go->** button.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FxYcDWdthneqzLuRmmgsC%2Fimage.png?alt=media&#x26;token=554b5c45-906d-48ea-bbb2-0a367e9fd2bd" alt=""><figcaption><p>Azure App Service Dashboard</p></figcaption></figure>

2. This will take you to a **Advanced Tools** section for the deployment where you can view container logs, application settings, and deployment information.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FMgCFTNk0KlmIMhHEXVLV%2Fimage.png?alt=media&#x26;token=4c0fb5e7-506c-4270-98e7-361ed3ff8f65" alt=""><figcaption><p>Advanced Tools Section</p></figcaption></figure>

3. At the top of the page click the link that says **Bash**, which will navigate into a terminal window where we were can create our `default.conf` file for our Nginx proxy container.

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FJ3aobFIqmKZAdb2Yjsfk%2Fimage.png?alt=media&#x26;token=482716cc-a58d-4f37-8296-62a190db5e12" alt=""><figcaption><p>Bash File System</p></figcaption></figure>

4. In the terminal when run the following commands to navigate to the correct directory, create a `conf.d` folder inside of `~/site/wwwroot` then inside the `conf.d` folder create a file called `default.conf` that our Nginx container will use to proxy traffic to the correct containers.

```bash
## Navigate to static file directory and create conf.d folder
cd site/wwwroot && mkdir conf.d

## Change into the newly created conf.d directory and create default.conf file
cd conf.d && vi default.conf
```

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2F3Yku8h8npU1FdYjVLJAm%2Fimage.png?alt=media&#x26;token=8f64e91f-e9bf-4ea0-a687-4ba7e12e0d63" alt=""><figcaption><p>Created default.conf</p></figcaption></figure>

4. You will then copy the `default.conf` from the [formio-multicontainer-azure-app-service.zip ](#deploy-azure-app-service)at the top of the page and save the file by typing **:wq** and pressing **Enter**.
5. To verify that this worked you can go back to the **Advanced Tools** page and click on the link at the bottom of the page under **Browse Directory** section where it says **Site wwwroot**

<figure><img src="https://3305536326-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FXQ4WcainGostRWQuG2Ju%2Fimage.png?alt=media&#x26;token=b4aa5898-84f0-4467-aa07-41bf37f5b08c" alt=""><figcaption></figcaption></figure>

## Adding Environment Variables

1. 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.
2. On the left-side column underneath the **Settings** section select **Configuration**.
3. Once on the **Configuration** page click on **Advanced Edit**.

<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2Ft61ZYSg3hLz6Ly6XfYx0%2FImage%202023-01-16%2014.59.45.png?alt=media&#x26;token=7f974a5b-e2fa-4396-8d0e-773de442bf48" alt=""><figcaption></figcaption></figure>

4. Copy and Paste the json from **env.json** in the **azure-app-service-multcontainer.zip** above.&#x20;
5. Edit the environment variables to for your environment before clicking **OK**.

<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2F3jfcKWHQuujlyKxZxKYL%2FImage%202023-01-16%2015.21.19.png?alt=media&#x26;token=e50de9a7-2fb3-4ea3-9a29-9de0830f545e" alt=""><figcaption></figcaption></figure>

6. Once you've finished editing your environment variables in the **Advanced Editing** section click **Save** button to persist your current configuration.

### API Server Environment Variables

<table data-full-width="false"><thead><tr><th>Name</th><th>Description</th><th>Example</th></tr></thead><tbody><tr><td>LICENSE_KEY</td><td>Form.io Enterprise license key</td><td>&#x3C;formio-enterprise-license></td></tr><tr><td>PORT</td><td>Port API server will be served on</td><td>3000</td></tr><tr><td>DEBUG</td><td>Application Logging Settings.</td><td>Less Verbose: "formio.*"<br>Most Verbose: "*.*"</td></tr><tr><td>PORTAL_ENABLED</td><td>Used to enable or disable the developer portal within a remote environment.</td><td>true</td></tr><tr><td>MONGO</td><td>Defines your MongoDB compatiable database string.</td><td>mongodb+srv://formiodbusername:supersecretpassword@formio-cosmos-db.global.mongocluster.cosmos.azure.com/formio?tls=true&#x26;authMechanism=SCRAM-SHA-256&#x26;retrywrites=true&#x26;maxIdleTimeMS=120000</td></tr><tr><td>ADMIN_EMAIL</td><td>Used to set the email address of the default root user login when the PORTAL_ENABLED variable is set to "true".</td><td>admin@example.com</td></tr><tr><td>ADMIN_PASS</td><td>Used to set the password of the default root user login.</td><td>CHANGEME</td></tr><tr><td>DB_SECRET</td><td>The database encryption secret</td><td>CHANGEME</td></tr><tr><td>JWT_SECRET</td><td>Used as the secret for JWT token encryption. It is used to generate and validate JSON Web Tokens (JWT) for authentication purposes.</td><td>CHANGEME</td></tr><tr><td>PDF_SERVER</td><td>Used to specify the URL or IP address of the PDF server or load balancer. If you are not using Web PDFs and only need to generate PDFs of submissions, you do not need to make the PDF server available on the internet and it only needs to be accessible to the Form.io Server.</td><td><strong>Docker Compose:</strong> http://pdf-server:4005<br><strong>Single Container:</strong> https://formio-pdf-server.azurewebsites.net <em>(PDF App Service Default Domain)</em></td></tr></tbody></table>

### PDF Server Environment Variables

| Name                              | Description                                                                                                                                                                                              | Example                                                                                                                                      |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| MONGO                             | Defines your MongoDB compatiable database string.                                                                                                                                                        | mongodb://formio-cosmos-db:@:10255/formio?ssl=true\&replicaSet=globaldb\&retrywrites=false\&maxIdleTimeMS=120000\&appName=@formio-cosmos-db@ |
| LICENSE\_KEY                      | Form.io Enterprise license key                                                                                                                                                                           | \<formio-enterprise-license>                                                                                                                 |
| FORMIO\_AZURE\_CONNECTION\_STRING | Connection string for accessing the Azure Blob Storage. Configures project's File Storage settings and the PDF Server.                                                                                   | DefaultEndpointsProtocol=https;AccountName=formioblobstoragecontainer;AccountKey=;EndpointSuffix=core.windows.net                            |
| FORMIO\_AZURE\_CONTAINER          | Specifies the name of the container in Azure Blob Storage where the files will be stored.                                                                                                                | formio-blob-storage-container                                                                                                                |
| FORMIO\_PDF\_PORT                 | Port PDF server will be served from.                                                                                                                                                                     | 4005                                                                                                                                         |
| WEBSITES\_PORT                    | \*Only required for a single container deployment of the PDF server. It tells Azure App Service that the PDF server container is listening on this port. It should match the value of FORMIO\_PDF\_PORT. | 4005                                                                                                                                         |
| DEBUG                             | Application Logging Settings.                                                                                                                                                                            | <p>Less Verbose: "pdf.*"<br>Most Verbose: "*.\*"</p>                                                                                         |

## Enable App Service Logs

1. 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** section.
2. Where it says **Application Logging** toggle it to **File System**, and set some quota thresholds and a log retention period.

<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2F8XCmSMzhLFWx9rybaWyc%2FImage%202023-02-06%2013.41.19.png?alt=media&#x26;token=08e440ec-cbef-4093-bd95-d036e7565d6f" alt=""><figcaption></figcaption></figure>

## Register Azure App Service IP with Cosmos DB Firewall

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.

1. In the **Overview** page of the Azure App Service, copy the **Virtual IP address** under the **Networking** section.
2. 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.
3. In the **Firewall** section of the Cosmos DB **Networking** page add the **Virtual IP address** from the Azure App Service **Networking** section.

<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MPHoF2HwOA0s5HV_AIB%2Fuploads%2FmXzrjbT36lWLDaTzCmJv%2FImage%202023-02-06%2015.01.18.png?alt=media&#x26;token=53960baa-ed53-42d6-b37a-bc59a4a4f24b" alt=""><figcaption></figcaption></figure>
