diff --git a/README.md b/README.md index 6de6992..899ae85 100644 --- a/README.md +++ b/README.md @@ -32,12 +32,12 @@ For information about the architecture of this solution, see [Architecture and R To deploy the reference architecture, select your MATLAB Production Server release from the table and follow the instructions to deploy the server using the provided template. A deployment of MATLAB Production Server supports MATLAB Runtime versions up to six releases back. | Release | Supported MATLAB Runtime Versions | | ------- | --------------------------------- | +| [R2025a](releases/R2025a/README.md) | R2025a, R2024b, R2024a, R2023b, R2023a, R2022b | | [R2024b](releases/R2024b/README.md) | R2024b, R2024a, R2023b, R2023a, R2022b, R2022a | | [R2024a](releases/R2024a/README.md) | R2024a, R2023b, R2023a, R2022b, R2022a, R2021b | | [R2023b](releases/R2023b/README.md) | R2023b, R2023a, R2022b, R2022a, R2021b, R2021a | | [R2023a](releases/R2023a/README.md) | R2023a, R2022b, R2022a, R2021b, R2021a, R2020b | | [R2022b](releases/R2022b/README.md) | R2022b, R2022a, R2021b, R2021a, R2020b, R2020a | -| [R2022a](releases/R2022a/README.md) | R2022a, R2021b, R2021a, R2020b, R2020a, R2019b | > **Note**: MathWorks provides templates for only the six most recent releases of MATLAB Production Server. Earlier templates are removed and are no longer supported. # Architecture and Resources @@ -52,7 +52,7 @@ resource group. ### Matlab Production Server Resources | Resource Name | Resource Name in Azure | Number of Resources | Description | |----------------------------------------------------------------------------|-------------------------|---------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -|Virtual network | `mps-network` | 1 | Provide support and security to the operation of MATLAB Production Server. | +|Virtual network | `mps-network` | 1 | Provides support and security to the operation of MATLAB Production Server. | | Storage account | `serverlog` | 1 | Storage account where the deployable archives (CTF files) created by MATLAB® Compiler SDK™ will be stored. The deployable archives (CTF files) will be stored in a file share. | | Application Insights | `logs-apmservice` | 1 | Enables storing and viewing of all logs associated with deployment. | | Log analytics workspace | `logs-workspace` | 1 | Workspace that contains data collected from various sources. | @@ -63,8 +63,8 @@ resource group. | Virtual machine scale set | `vmss` | 1 | Manages the number of identical VMs to be deployed. Each VM runs an instance of MATLAB Production Server which in turn runs multiple MATLAB workers. | | Application gateway | `vmss-agw` | 1 | Provides routing and load balancing service to MATLAB Production Server instances. The MATLAB Production Server dashboard retrieves the HTTP/HTTPS endpoint for making requests to the server from the application gateway resource.

**NOTE**: Provides HTTPS endpoint to the server for making requests.

| | Virtual network | `vmss-vnet` | 1 | Enables resources to communicate with each other. | -|Network security group | `vmss-rdp-nsg` | 1 | Filter network traffic to and from virtual machine scale set in an Azure virtual network. | -|Public IP address | `Vmss-pip` | 1 | Provide public IP address to virtual machine scale set. | +|Network security group | `vmss-rdp-nsg` | 1 | Filters network traffic to and from virtual machine scale set in an Azure virtual network. | +|Public IP address | `Vmss-pip` | 1 | Provides public IP address to virtual machine scale set. | ### Admin Dashboard Resources | Resource Name | Resource Name in Azure | Number of Resources | Description | @@ -72,7 +72,7 @@ resource group. | MATLAB Production Server dashboard virtual machine | `admindashboard` | 1 | Virtual machine (VM) that hosts the MATLAB Production Server dashboard. Use the dashboard to:
  • Get HTTP/HTTPS endpoint to make requests
  • Upload applications (CTF files) to the server
  • Manage server configurations

For more information, see [Manage MATLAB Production Server Using the Dashboard](https://www.mathworks.com/help/mps/server/use-matlab-production-server-cloud-dashboard-on-azure-reference-architecture.html). | | MATLAB Production Server dashboard public IP | `admindashboard-public-ip` | 1 | Public IP address to connect to MATLAB Production Server dashboard.

**NOTE**: Provides HTTPS endpoint to the dashboard for managing server instances.

| | Disk | `admindashboard_OsDisk_` | 1 | Operating system disk attached to admin dashboard. | -| Network interface | `admindashboard-nic` | 1 | Provide network interface for admin dashboard. | +| Network interface | `admindashboard-nic` | 1 | Provides network interface for admin dashboard. | ### Redis Resources | Resource Name | Resource Name in Azure | Number of Resources | Description | @@ -86,6 +86,52 @@ resource group. # FAQ +## How do I deploy to an existing virtual network? +>**Note:** Your existing virtual network must have at least two available subnets for deployment. + +### Ports to Open in Existing Virtual Network +If you are deploying to an existing virtual network, open these ports in your network: +| Port | Description | +| ------------------|---------------------------------------------------------------------------------------------------------------- | +| `443` | Required for communicating with the dashboard | +| `8000`, `8004`, `8080`, `9090`, `9910` | Required for communication between the dashboard, MATLAB Production Server workers, and various microservices within the virtual network. These ports do not need to be open to the Internet. | +| `27000` | Required for communication between the Network License Manager and the workers. | +| `65200`, `65535` | Required for the Azure application gateway health check to work. These ports need to be accessible over the Internet. For more information, see [MSDN Community](https://social.msdn.microsoft.com/Forums/azure/en-US/96a77f18-3b71-45d2-a213-c4ba63fd4e63/internal-application-gateway-backend-health-is-unkown?forum=WAVirtualMachinesVirtualNetwork). | +| `22`, `3389` | (Optional) Enables Remote Desktop functionality, which can be used for troubleshooting and debugging. | +
+ +You can close ports 22 and 3389 after deployment. + +### Create Service Endpoint in Virtual Network (Since R2025a) +Starting in R2025a, if you are using an existing virtual network and assign a public IP address to the VM hosting MATLAB Production Server, you must manually add a service endpoint to the virtual network *before* deploying MATLAB Production Server in order to create and access the storage account. For more information, see [Grant access from a virtual network](https://learn.microsoft.com/en-us/azure/storage/common/storage-network-security?tabs=azure-portal#grant-access-from-a-virtual-network). + +You can check if such an endpoint already exists by navigating to the Azure Portal, selecting your virtual network, and clicking **Service endpoints**. If no such endpoint is present, follow these steps: +1. In the Azure Portal, click **Resource groups** and select the virtual network for this deployment. +1. In the left navigation menu, expand the **Settings** category and click **Service endpoints**. +1. Click **Add** to add the new endpoint. It must have the following parameters: + + + + +
ServiceMicrosoft.Storage
SubnetName of subnet in which the storage account will be deployed
+ +For more information on creating endpoints, see [Create and associate service endpoint policies](https://learn.microsoft.com/en-us/azure/virtual-network/virtual-network-service-endpoint-policies). + +### Deploy to Existing Virtual Network +To deploy MATLAB Production Server to an existing virtual network, in the deployment template, set the **New or Existing Virtual Network** parameter to `existing`. + +Set the following parameter values in the template based on your existing virtual network. + +| Parameter Name | Value | +|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Virtual Network Name** | Specify the name of your existing virtual network or use the default value. | +| **Virtual Network CIDR Range** | Specify the IP address range of the virtual network in CIDR notation or use the default value. | +| **Subnet 1 CIDR Range** | Specify the IP address range of the first subnet in CIDR notation or use the default value. The first subnet hosts the dashboard and other resources. | +| **Subnet 2 CIDR Range** | Specify the IP address range of the second subnet in CIDR notation or use the default value. The second subnet hosts the application gateway. | +| **Available Subnet 2 IP Address** | Specify an unused IP address from Subnet 2 or use the default value. This IP address serves as the private IP of the application gateway. | +| **Resource Group Name Of Virtual Network** | Specify the resource group name of the virtual network or use the default value. | + + ## Why do requests to the server fail with errors such as “untrusted certificate” or “security exception”? These errors occur either when CORS is not enabled on the server or when the server endpoint uses a self-signed certificate. diff --git a/releases/R2022a/README.md b/releases/R2022a/README.md deleted file mode 100644 index e64c4c8..0000000 --- a/releases/R2022a/README.md +++ /dev/null @@ -1,182 +0,0 @@ -# MATLAB Production Server on Microsoft Azure - -# Requirements - -Before starting, you need the following: - -- A MATLAB® Production Server™ license that meets the following conditions: - - Current on [Software Maintenance Service (SMS)](https://www.mathworks.com/services/maintenance.html). - - Linked to a [MathWorks Account](https://www.mathworks.com/mwaccount/). - - Concurrent license type. To check your license type, see [MathWorks License Center](https://www.mathworks.com/licensecenter/). - - Configured to use a network license manager on the virtual network. By default, the deployment of MATLAB Production Server includes a network license manager, but you can also use an existing license manager. In either case, activate or move the license after deployment. For details, see [Configure MATLAB Production Server Licensing on the Cloud](https://www.mathworks.com/help/licensingoncloud/matlab-production-server-on-the-cloud.html). -- A Microsoft Azure™ account. - -# Costs -You are responsible for the cost of the Azure services used when you create cloud resources using this guide. Resource settings, such as instance type, will affect -the cost of deployment. For cost estimates, see the pricing pages for each Azure -service you will be using. Prices are subject to change. - - -# Introduction - -The following guide will help you automate the process of running MATLAB -Production Server on Azure using your Azure account. The automation is -accomplished using an Azure Resource Manager (ARM) template. The template is a JSON -file that defines the resources needed to deploy and manage MATLAB Production -Server on Azure. Once deployed, you can manage the server using the -MATLAB Production Server Dashboard—a web-based interface to -configure and manage server instances on the cloud. For more information, see [Manage MATLAB Production Server using the Dashboard](https://www.mathworks.com/help/mps/server/use-matlab-production-server-cloud-dashboard-on-azure-reference-architecture.html). -For information about the architecture of this solution, see [Architecture and Resources](#architecture-and-resources). - -# Deployment Steps - -## Step 1. Launch Template -Click the **Deploy to Azure** button to deploy resources on - Azure. This will open the Azure Portal in your web browser. - -[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fmathworks-ref-arch%2Fmatlab-production-server-on-azure%2Fmaster%2Freleases%2FR2022a%2Ftemplates%2Fazuredeploy22a.json) - -> MATLAB Release: R2022a - - -For other releases, see [How do I launch a template that uses a previous MATLAB release?](#how-do-i-launch-a-template-that-uses-a-previous-matlab-release) -

Note: Creating resources on Azure can take at least 30 minutes.

- -## Step 2. Configure Cloud Resources -Provide values for parameters in the custom deployment template on the Azure Portal : - -| Parameter Name | Value | -|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **Subscription** | Choose an Azure subscription to use for purchasing resources.

Example: VERTHAM Dev

| -| **Resource group** | Choose a name for the resource group that will hold the resources. It is recommended you create a new resource group for each deployment. This allows all resources in a group to be deleted simultaneously.

Example: Saveros

| -| **Location** | Choose the region to start resources in. Ensure that you select a location which supports your requested instance types. To check which services are supported in each location, see [Azure Region Services](). We recommend you use East US or East US 2.

Example: East US

| -| **Server VM Instance Size** | Specify the size of the VM you plan on using for deployment. Each MATLAB Production Server instance runs on a VM and each instance will run multiple workers. We recommend you choose a VM size where the number of cores on your VM match the number of MATLAB workers per VM you plan on using. The template defaults to: Standard_D4s_v3. This configuration has 4 vCPUs and 16 GiB of Memory. For more information, see Azure [documentation](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/sizes-general).

Example: Standard_D4s_v3

| -| **Dashboard VM Size** | Specify the size of the VM you plan on using for the MATLAB Production Server dashboard. The dashboard lets you configure server settings and manage deployed application. In most cases, choosing the smallest VM size is adequate. The template defaults to: Standard_D1_v2. For more information, see Azure [documentation](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/sizes-general).

Example: Standard_D1_v2

| -| **Instance Count** | Number of VMs to run MATLAB Production Server instances. Each MATLAB Production Server instance runs on a VM and each instance will run multiple workers.

Example: 6

If you have a standard 24 worker MATLAB Production Server license and select Standard_D4s_v3 VM (4 cores) as the Server VM Instance Size, you will need 6 VMs to fully utilize the workers in your license. Therefore, your instance count will be 6.

You can always under provision the number of VMs. In which case you may end up using fewer workers than you are licensed for.

| -| **Admin Username** | Specify the administrator user name for all VMs. Use this user name to log in to the MATLAB Production Server dashboard and network license manager. | -| **Admin Password** | Specify the administrator password for all VMs. Use this password to log in to the MATLAB Production Server dashboard and network license manager. | -| **Allow connections from** | This is the IP address range that will be allowed to connect to the dashboard that manages the server, and the network license manager. The format for this field is IP Address/Mask.

Example:

10.0.0.1/32
  • This is the public IP address which can be found by searching for "what is my ip address" on the web. The mask determines the number of IP addresses to include.
  • A mask of 32 is a single IP address.
  • Use a [CIDR calculator](https://www.ipaddressguide.com/cidr) if you need a range of more than one IP addresses.
  • You may need to contact your IT administrator to determine which address is appropriate.

| -| **Create Azure Redis Cache**| Choose whether you want to create an Azure Redis Cache service. Creating this service will allow you to use the persistence functionality of the server. Persistence provides a mechanism to cache data between calls to MATLAB code running on a server instance.| -| **Use Public IP Addresses**| Choose 'Yes' if you want to make your solution available over the internet.
If you choose 'No', the ARM template does not assign a public IP address for the VM that hosts the dashboard. To access the dashboard, you can use a different VM located in the same virtual network as the VM that hosts the dashboard. | -|**Platform**| Choose the operating system for the server. Microsoft Windows and Linux are the only available options. | -|**Deploy Network License Manager**| Select whether you want to deploy the Network License Manager for MATLAB to manage your license files. Selecting 'Yes' deploys the Network License Manager for MATLAB reference architecture. Select 'No' if you want to use an exisitng license server. | -|**New or Existing Virtual Network**| Specify whether you want to create a new virtual network for your deployment or use an exisiting one. You can use the default values or enter new values based on your network setup for the following paramaters.

When deploying in a new virtual network, by default, the deployment keeps the ports listed in [How do I use an existing virtual network to deploy MATLAB Production Server?](#How-do-I-use-an-existing-virtual-network-to-deploy-MATLAB-Production-Server) open. You can close ports 22 and 3389 after deployment is complete. | -| **Virtual Network Name** | Specify the name of your existing virtual network or use the default value. | -| **Virtual Network CIDR Range** | Specify the IP address range of the virtual network in CIDR notation or use the default value. | -| **Subnet 1 CIDR Range** | Specify the IP address range of the first subnet in CIDR notation or use the default value. The first subnet hosts the dashboard and other resources. | -| **Subnet 2 CIDR Range** | Specify the IP address range of the second subnet in CIDR notation or use the default value. The second subnet hosts the application gateway. | -| **Available Subnet 2 IP Address** | Specify an unused IP address from Subnet 2 or use the default value. This IP address serves as the private IP of the application gateway. | -| **Resource Group Name Of Virtual Network** | Specify the resource group name of the virtual network or use the default value. | -| **Certificate Input Type** | Specify an SSL certificate for the Azure application gateway to use. The application gateway provides an HTTPS endpoint that you use to connect to server instances and the MATLAB Production Server dashboard.
The deployment template provides an option to use either an SSL certificate that already exists in the Azure KeyVault or specify a string that is a base64-encoded value of an SSL certificate that is in PFX format.

Prerequisites for using the KeyVault:
  • KeyVault with an SSL certificate. For information about creating a KeyVault and adding a certificate, see [Azure documentation](https://docs.microsoft.com/en-us/azure/key-vault/certificates/quick-create-portal).
    Record the secret ID of the certificate. You will need to enter it in the MATLAB Production Server deployment template.
  • User-assigned managed identity in Azure that has permission to access the KeyVault. For details on creating a managed identity, see [Azure documentation](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-manage-ua-identity-portal#create-a-user-assigned-managed-identity).
    Record the resource ID of the managed identity that you create. You will need to enter it in the MATLAB Production Server deployment template.
    Grant your managed identity access to the KeyVault. To do so, navigate to the KeyVault you created earlier and add a role assignment that has at least read access to the KeyVault. For details on adding a role assignment, see [Azure documentation](https://docs.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal?tabs=current#step-2-open-the-add-role-assignment-pane).

Select if you will use a certificate from the Azure KeyVault or enter a base64-encoded PFX certificate string.

If you select KeyVault, enter values for **Managed Identity Resource ID for KeyVault** and **Secret ID of Certificate in KeyVault**.

If you select Base-64 encoded PFX Certificate, enter values for **Base64-encoded PFX Certificate Data** and **Password for Base64-encoded PFX Certificate**.| -| **Secret ID of Certificate in KeyVault** | Enter the secret ID of the SSL certificate present in the KeyVault. | -| **Managed Identity Resource ID for KeyVault** | Enter the resource ID of the managed identity that has permission to access the KeyVault. | -| **Base64Encoded PFX Certificate Data** | Enter a string that is a base64-encoded value of an SSL certificate in PFX format. | -| **Password for Base64-encoded PFX Certificate** | If the certificate requires a password, enter it here. Otherwise, leave the field blank. | - -Click **Purchase** to begin the deployment. This can take up to 40 minutes. - -## Step 3. Upload License File -The Network License Manager for MATLAB manages the MATLAB Production Server license file. The MATLAB Production Server deployment template provides an option to deploy the license manager or use an existing license manager. For more information about the Network License Manager for MATLAB, see [Network License Manager for MATLAB](https://github.com/mathworks-ref-arch/license-manager-for-matlab-on-azure). The following steps show how to upload the license file using the Network License Manager for MATLAB dashboard: -> **Note**: You must provide a fixed license server MAC address to get a license file from the MathWorks License Center. For more information, see [Configure MATLAB Production Server Licensing on the Cloud](https://www.mathworks.com/help/licensingoncloud/matlab-production-server-on-the-cloud.html). -1. In the Azure Portal, click **Resource - groups** and select the resource group containing your cluster resources. -1. Select **Deployments** from the left pane and click **Microsoft.Template**. -1. Click **Outputs**. Copy the parameter value for **networkLicenseManagerURL** and paste it in a browser. -1. Log in using the password that you specified in the [Configure Cloud Resources](#step-2-configure-cloud-resources) step of the deployment process. -1. Follow the instructions in the Network License Manager for MATLAB dashboard to upload your MATLAB Production Server license. - - -## Step 4. Connect and Log In to the Dashboard -The MALAB Production Server dashboard provides a web-based interface to -configure and manage server instances on the cloud. If your solution uses private IP addresses, you can connect to the dashboard from a VM that belongs to the same virtual network as the VM that hosts the dashboard. -> **Note:** Complete these steps only after your resource group has been successfully created. - -> **Note:** The Internet Explorer web browser is not supported for interacting with the dashboard. - -1. In the Azure Portal, click **Resource - groups** and select the resource group you created for this deployment from the list. -1. Select **Deployments** from the left pane and click **Microsoft.Template**. -1. Click **Outputs** from the left pane. Copy the parameter value for **dashboardURL** and paste it in a browser. -1. Log in using the administrator user name and password that you specified in the [Configure Cloud Resources](#step-2-configure-cloud-resources) step of the deployment process. - -![MATLAB Production Server Dashboard](/releases/R2022a/images/dashboardLogin.png?raw=true) - -You are now ready to use MATLAB Production Server on Azure. - -For more information on how to use the dashboard, see [MATLAB Production Server Reference Architecture Dashboard](https://www.mathworks.com/help/mps/server/use-matlab-production-server-cloud-dashboard-on-azure-reference-architecture.html). - -Configuring role-based access control for the dashboard is recommended. Role-based access control uses Azure AD to let you grant users the privileges to perform tasks on the dashboard and server, based on their role. For more information on how to configure role-based access control, see [Dashboard Access Control](https://www.mathworks.com/help/mps/server/dashboard-access-control-for-azure-reference-architecture.html). - -To run applications on MATLAB Production Server, you will need to create applications using MATLAB Compiler SDK. For more information, see [Deployable Archive Creation](https://www.mathworks.com/help/mps/deployable-archive-creation.html) in the MATLAB Production Server product documentation. - -# Architecture and Resources -Deploying this reference architecture will create several resources in your -resource group. - -*Architecture on Azure* - -![Cluster Architecture](/releases/R2022a/images/mps-ref-arch-azure-architecture-diagram.jpg?raw=true) - -### Resources -| Resource Name | Resource Name in Azure | Number of Resources | Description | -|----------------------------------------------------------------------------|-------------------------|---------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| MATLAB Production Server dashboard virtual machine | `servermachine` | 1 | Virtual machine (VM) that hosts the MATLAB Production Server dashboard. Use the dashboard to:
  • Get HTTP/HTTPS endpoint to make requests
  • Upload applications (CTF files) to the server
  • Manage server configurations

For more information, see [MATLAB Production Server Reference Architecture Dashboard](https://www.mathworks.com/help/mps/server/use-matlab-production-server-cloud-dashboard-on-azure-reference-architecture.html). | -| MATLAB Production Server dashboard public IP | `servermachine-public-ip` | 1 | Public IP address to connect to MATLAB Production Server dashboard.

**NOTE**: Provides HTTPS endpoint to the dashboard for managing server instances.

| -| Virtual machine scale set | `vmss` | 1 | Manages the number of identical VMs to be deployed. Each VM runs an instance of MATLAB Production Server which in turn runs multiple MATLAB workers. | -| Application gateway | `vmss-agw` | 1 | Provides routing and load balancing service to MATLAB Production Server instances. The MATLAB Production Server dashboard retrieves the HTTP/HTTPS endpoint for making requests to the server from the application gateway resource.

**NOTE**: Provides HTTPS endpoint to the server for making requests.

| -| Storage account | `serverlog` | 1 | Storage account where the deployable archives (CTF files) created by MATLAB® Compiler SDK™ will be stored. The deployable archives (CTF files) will be stored in a file share. | -| Virtual network | `vmss-vnet` | 1 | Enables resources to communicate with each other. | -| Azure Cache for Redis | `vmssredis` | 1 | Enables caching of data between calls to MATLAB code running on a server instance. | -| Application Insights | `logs-apmservice` | 1 | Enables storing and viewing of all logs associated with deployment. | - -# FAQ -## How do I use an existing virtual network to deploy MATLAB Production Server? -In addition to the parameters specified in the section [Configure Cloud Resources](#step-2-configure-cloud-resources), you will also need to open the following ports in your virtual network: - -| Port | Description | -|------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `443` | Required for communicating with the dashboard. | -| `8000`, `8004`, `8080`, `9090`, `9910` | Required for communication between the dashboard, MATLAB Production Server workers, and various microservices within the virtual network. These ports do not need to be open to the internet. | -| `27000` | Required for communication between network license manager and the workers. | -| `65200` - `65535` | Required for the Azure application gateway health check to work. These ports need to be accessible over the internet. For more information, see [MSDN Community](https://social.msdn.microsoft.com/Forums/azure/en-US/96a77f18-3b71-45d2-a213-c4ba63fd4e63/internal-application-gateway-backend-health-is-unkown?forum=WAVirtualMachinesVirtualNetwork). | -| `22`, `3389` | (Optional) Required for Remote Desktop functionality. This can be used for troubleshooting and debugging. | - -## How do I launch a template that uses a previous MATLAB release? -You may use one of the deploy buttons below to deploy an older release of MATLAB Production Server Reference Architecture. Note that the operating system is a parameter of the ARM template. -| Release | Windows Server / Ubuntu | -|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| R2021b | | -| R2021a | | -| R2020b | | - - -For more information, see [previous releases](/releases). - - -## What versions of MATLAB Runtime are supported? - -| Release | MATLAB Runtime | MATLAB Runtime | MATLAB Runtime | MATLAB Runtime | MATLAB Runtime | MATLAB Runtime | MATLAB Runtime | MATLAB Runtime | MATLAB Runtime | -|----------------|----------------|----------------|----------------|----------------|----------------|----------------|----------------|-----------------|---------------| -| MATLAB R2020b | R2018a | R2018b | R2019a | R2019b | R2020a | R2020b | -| MATLAB R2021a | | R2018b | R2019a | R2019b | R2020a | R2020b | R2021a | -| MATLAB R2021b | | | R2019a | R2019b | R2020a | R2020b |R2021a | R2021b | -| MATLAB R2022a | | | | R2019b | R2020a | R2020b |R2021a | R2021b | R2022a | - - - -## Why do requests to the server fail with errors such as “untrusted certificate” or “security exception”? - -These errors result from either CORS not being enabled on the server or due to the fact that the server endpoint uses a self-signed -certificate. - -If you are making an AJAX request to the server, make sure that CORS is enabled in the server configuration. You can enable CORS by editing the property `--cors-allowed-origins` in the config file. For more information, see [Edit the Server Configuration](http://www.mathworks.com/help/mps/server/use-matlab-production-server-cloud-dashboard-on-azure-reference-architecture.html#mw_d9c9b367-376f-4b31-a97e-ed894abfcbbe). - -Also, some HTTP libraries and Javascript AJAX calls will reject a request originating from a server that uses a self-signed certificate. You may need to manually override the default security behavior of the client application. Or you can add a new -HTTP/HTTPS endpoint to the application gateway. For more information, see [Change SSL Certificate to Application Gateway](https://www.mathworks.com/help/mps/server/configure-azure-resources-reference-architecture.html#mw_6ae700e7-b895-4e90-b0fb-7292e905656e_sep_mw_1fd15ea2-d161-4694-963d-41a81fc773bf). - -# Enhancement Request -Provide suggestions for additional features or capabilities using the following link: -https://www.mathworks.com/cloud/enhancement-request.html - -# Technical Support -If you require assistance or have a request for additional features or capabilities, please contact [MathWorks Technical Support](https://www.mathworks.com/support/contact_us.html). diff --git a/releases/R2022a/images/FinalArchitecture60.png b/releases/R2022a/images/FinalArchitecture60.png deleted file mode 100644 index bb9bbec..0000000 Binary files a/releases/R2022a/images/FinalArchitecture60.png and /dev/null differ diff --git a/releases/R2022a/images/azureScaling.png b/releases/R2022a/images/azureScaling.png deleted file mode 100644 index 0579405..0000000 Binary files a/releases/R2022a/images/azureScaling.png and /dev/null differ diff --git a/releases/R2022a/images/cloudConsoleHome.png b/releases/R2022a/images/cloudConsoleHome.png deleted file mode 100644 index 7819cf1..0000000 Binary files a/releases/R2022a/images/cloudConsoleHome.png and /dev/null differ diff --git a/releases/R2022a/images/cloudConsoleLogin.png b/releases/R2022a/images/cloudConsoleLogin.png deleted file mode 100644 index 796295e..0000000 Binary files a/releases/R2022a/images/cloudConsoleLogin.png and /dev/null differ diff --git a/releases/R2022a/images/mps-ref-arch-azure-architecture-diagram.png b/releases/R2022a/images/mps-ref-arch-azure-architecture-diagram.png deleted file mode 100644 index b95f22b..0000000 Binary files a/releases/R2022a/images/mps-ref-arch-azure-architecture-diagram.png and /dev/null differ diff --git a/releases/R2022a/scripts/scriptScaleSet.sh b/releases/R2022a/scripts/scriptScaleSet.sh deleted file mode 100644 index 55c9358..0000000 --- a/releases/R2022a/scripts/scriptScaleSet.sh +++ /dev/null @@ -1,3 +0,0 @@ -#! /bin/bash -#Put your extra commands here -ls diff --git a/releases/R2022a/templates/azuredeploy22a.json b/releases/R2022a/templates/azuredeploy22a.json deleted file mode 100644 index 3202f0f..0000000 --- a/releases/R2022a/templates/azuredeploy22a.json +++ /dev/null @@ -1,1053 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Location Where the Template will be deployed" - } - }, - "Server VM Instance Size": { - "type": "string", - "defaultValue": "Standard_D4s_v3", - "metadata": { - "description": "Each VM instance will run multiple workers. Select a VM size that is appropriate for your needs. It is recommended that you choose a VM size where the number of cores on your VM match the number of workers per VM you plan on using." - } - }, - "dashboardVMSize": { - "type": "string", - "defaultValue": "Standard_D1_v2", - "metadata": { - "description": "Size of the server dashboard VM. The dashboard manages server settings and deployed applications. Since this VM does not perform any significant computation, a smaller size is recommended." - } - }, - "instanceCount": { - "type": "int", - "defaultValue": 1, - "metadata": { - "description": "Number of VM instances." - }, - "maxValue": 24, - "minValue": 1 - }, - "adminUsername": { - "type": "string", - "metadata": { - "description": "Administrator username on all VMs." - } - }, - "adminPassword": { - "type": "securestring", - "metadata": { - "description": "Administrator password on all VMs." - } - }, - "Allow connections from": { - "type": "string", - "metadata": { - "description": "String identifying the client CIDR or IP range which will be allowed to use the solution." - } - }, - "CreateAzureRedisCache": { - "type": "string", - "allowedValues": ["Yes", "No"], - "defaultValue": "Yes", - "metadata": { - "description": "Specify whether you want to create an Azure Redis Cache that lets you use the data caching functionality on the server." - } - }, - "UsePublicIPAddresses": { - "type": "string", - "allowedValues": ["Yes", "No"], - "defaultValue": "Yes", - "metadata": { - "description": "Specify whether you want to use public IP addresses and make your solution available over the Internet." - } - }, - "Platform": { - "type": "string", - "defaultValue": "Linux", - "allowedValues": ["Windows", "Linux"], - "metadata": { - "description": "Select the operating system for the server." - } - }, - "NewOrExistingVirtualNetwork": { - "type": "string", - "defaultValue": "new", - "allowedValues": ["new", "existing"], - "metadata": { - "description": "Specify whether to create a new Virtual Network or use an existing one." - } - }, - "VirtualNetworkName": { - "type": "string", - "defaultValue": "mps-network", - "metadata": { - "description": "Name of your existing virtual network where you want to deploy this solution." - } - }, - "Subnet1": { - "type": "string", - "defaultValue": "default", - "metadata": { - "description": "Name of the subnet that will host the dashboard and other resources." - } - }, - "Subnet2": { - "type": "string", - "defaultValue": "appGwSubnet", - "metadata": { - "description": "Name of the subnet that will host the application gateway." - } - }, - "VirtualNetworkCIDRRange": { - "type": "string", - "defaultValue": "10.0.0.0/16", - "metadata": { - "description": "CIDR range of the Virtual Network." - } - }, - "Subnet1CIDRRange": { - "type": "string", - "defaultValue": "10.0.0.0/24", - "metadata": { - "description": "CIDR range of the first subnet in the Virtual Network." - } - }, - "Subnet2CIDRRange": { - "type": "string", - "defaultValue": "10.0.1.0/24", - "metadata": { - "description": "CIDR range of the second subnet in the Virtual Network." - } - }, - "AvailableSubnet2IPAddress": { - "type": "string", - "defaultValue": "10.0.1.4", - "metadata": { - "description": "Specify an unused IP address from Subnet 2. This IP address serves as the private IP of the Application Gateway." - } - }, - "ResourceGroupNameOfVirtualNetwork": { - "type": "string", - "defaultValue": "[resourceGroup().name]", - "metadata": { - "description": "Specify the resource group name of the virtual network." - } - }, - "DeployNetworkLicenseManagerforMATLAB": { - "type": "string", - "allowedValues": ["Yes", "No"], - "defaultValue": "Yes", - "metadata": { - "description": "Specify whether you want to deploy the Network License Manager for MATLAB." - } - }, - "CertificateInputType": { - "type": "string", - "metadata": { - "description": "Select if the Application Gateway will use an SSL certificate from the KeyVault or a base64-encoded PFX certificate string. If you select \"KeyVault\", enter values for \"ManagedIdentityResourceIDForKeyVault\" and \"KeyVaultCertificateSecretID\". If you select \"Base64-encoded PFX Certificate\", enter values for \"Base64EncodedPFXCertificateData\" and \"PasswordForBase64EncodedPFXCertificate\"." - }, - "allowedValues": ["KeyVault", "Base64-encoded PFX Certificate"], - "defaultValue": "KeyVault" - }, - "KeyVaultCertificateSecretID": { - "type": "securestring", - "metadata": { - "description": "Secret ID of SSL certificate present in Key Vault." - }, - "defaultValue": "" - }, - "ManagedIdentityResourceIDForKeyVault": { - "type": "string", - "metadata": { - "description": "Resource ID of the managed identity that has permission to access Key Vault." - }, - "defaultValue": "" - }, - "Base64EncodedPFXCertificateData": { - "type": "string", - "metadata": { - "description": "Base64-encoded SSL certificate string in PFX format." - }, - "defaultValue": "" - }, - "PasswordForBase64EncodedPFXCertificate": { - "type": "securestring", - "metadata": { - "description": "Password for Base64-encoded SSL certificate." - }, - "defaultValue": "" - } - }, - "variables": { - "ManagedIdentityResourceIDForKeyVault": { - "type": "UserAssigned", - "userAssignedIdentities": { - "[parameters('ManagedIdentityResourceIDForKeyVault')]": {} - } - }, - "AppGatewaySize": "Standard_v2", - "AppGatewayCount": 1, - "mpsDNSName": "[concat('mps',uniqueString( resourceGroup().id))]", - "storageAccountName": "[concat('serverlog',uniqueString( resourceGroup().id))]", - "storageAccountType": "Standard_LRS", - "vmssName": "vmss1", - "namingInfix": "[toLower(substring(concat(variables('vmssName'), uniqueString(resourceGroup().id)), 0, 9))]", - "addressPrefix": "[parameters('VirtualNetworkCIDRRange')]", - "subnetPrefix": "[parameters('Subnet1CIDRRange')]", - "virtualNetworkName": "[parameters('VirtualNetworkName')]", - "subnetName": "[parameters('Subnet1')]", - "subnetRef": "[resourceId(variables('ResourceGroupNameOfVirtualNetwork'),'Microsoft.Network/virtualNetworks/subnets',variables('virtualNetworkName'),variables('subnetName'))]", - "nicName": "[concat(variables('namingInfix'), 'nic')]", - "ipConfigName": "[concat(variables('namingInfix'), 'ipconfig')]", - "ResourceGroupNameOfVirtualNetwork": "[parameters('ResourceGroupNameOfVirtualNetwork')]", - "virtualNetworkID": "[resourceId(variables('ResourceGroupNameOfVirtualNetwork'), 'Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]", - "appGwPublicIPAddressName": "[concat(variables('namingInfix'), '-pip')]", - "appGwName": "[concat(variables('namingInfix'), '-agw')]", - "appGwPublicIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses',variables('appGwPublicIPAddressName'))]", - "appGwSubnetName": "[parameters('Subnet2')]", - "appGwSubnetPrefix": "[parameters('Subnet2CIDRRange')]", - "appGwSubnetID": "[resourceId(variables('ResourceGroupNameOfVirtualNetwork'),'Microsoft.Network/virtualNetworks/subnets',variables('virtualNetworkName'),variables('appGwSubnetName'))]", - "mpsHttpPortVar": 9910, - "mpsFrontEndPort": 445, - "appGwBePoolName": "[concat(variables('namingInfix'), 'appGwBepool')]", - "networkSecurityGroupName": "[concat(variables('namingInfix'), '-rdp-nsg')]", - "publicIPAddressNameMachine": "servermachine-public-ip", - "redisCacheName": "[concat(variables('namingInfix'), 'redis')]", - "redisenableNonSslPort": true, - "redisCacheCapacity": 1, - "redisCacheFamily": "C", - "redisCacheSKU": "Standard", - "appGWprivateIP": "[parameters('AvailableSubnet2IPAddress')]", - "virtualNetworkNewOrExisting": "[parameters('NewOrExistingVirtualNetwork')]", - "licservernicName": "servermachine-nic", - "vmName": "servermachine", - "publicIPprop1": { - "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressNameMachine'))]" - }, - "Platform": "[parameters('Platform')]", - "WindowsSKUDisk1": "matlab-production-server-payg-master-22a", - "WindowsOfferDisk1": "matlab-production-server-payg-master", - "WindowsSKUDisk2": "matlab-production-server-byol-windows-22a", - "WindowsOfferDisk2": "matlab-production-server-byol-windows", - "LinuxSKUDisk1": "[variables('WindowsSKUDisk1')]", - "LinuxOfferDisk1": "[variables('WindowsOfferDisk1')]", - "LinuxSKUDisk2": "matlab-production-server-byol-linux-22a", - "LinuxOfferDisk2": "matlab-production-server-byol-linux", - "WindowsDisk1Version": "latest", - "WindowsDisk2Version": "latest", - "LinuxDisk1Version": "[variables('WindowsDisk1Version')]", - "LinuxDisk2Version": "latest", - "windowsScriptURL": "[uri(variables('_artifactsLocation'), concat('scriptScaleSet.ps1', variables('_artifactsLocationSasToken')))]", - "linuxScriptURL": "[uri(variables('_artifactsLocation'), concat('scriptScaleSet.sh', variables('_artifactsLocationSasToken')))]", - "masterVMScriptURL": "[uri(variables('_artifactsLocation'), concat('initMasterVM.sh', variables('_artifactsLocationSasToken')))]", - "commandToExecuteWindows": "[concat('powershell -ExecutionPolicy Unrestricted -File scriptScaleSet.ps1 ' )]", - "commandToExecuteLinux": "[concat('echo hello ' )]", - "AppInsights-AppType": "Node.JS", - "AppInsights-requestSource": "rest", - "myAppInsightsInstanceName": "logs-apmservice", - "workspaceName": "logs-workspace", - "keyoperator": "[resourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", - "owner": "[resourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", - "offerType": "BYOL", - "should-deploy-flex": "[parameters('DeployNetworkLicenseManagerforMATLAB')]", - "flex-arm-template-link": "https://raw.githubusercontent.com/mathworks-ref-arch/license-manager-for-matlab-on-azure/master/releases/R2022a/azuredeploy-existing-vnet-R2022a.json", - "flex-parameters": { - "instanceType": { "value": "Standard_D2s_v3" }, - "clientIPAddress": { "value": "[parameters('Allow connections from')]" }, - "adminUsername": { "value": "[parameters('adminUsername')]" }, - "adminPassword": { "value": "[parameters('adminPassword')]" }, - "virtualNetworkResourceID": { - "value": "[variables('virtualNetworkID')]" - }, - "subnetName": { "value": "[variables('subnetName')]" } - }, - "_artifactsLocation":"https://raw.githubusercontent.com/mathworks-ref-arch/matlab-production-server-on-azure/master/releases/R2022a/scripts/", - "_artifactsLocationSasToken":"" - }, - "resources": [ - { - "type": "Microsoft.Resources/deployments", - "name": "flex-lm-server", - "apiVersion": "2020-10-01", - "condition": "[equals(variables('should-deploy-flex'), 'Yes')]", - "dependsOn": [ - "[resourceId('Microsoft.Network/networkInterfaces/',variables('licservernicName'))]", - "[resourceId('Microsoft.Network/virtualNetworks/',variables('virtualNetworkName'))]" - ], - "properties": { - "mode": "Incremental", - "templateLink": { - "uri": "[variables('flex-arm-template-link')]", - "contentVersion": "1.0.0.0" - }, - "parameters": "[variables('flex-parameters')]" - } - }, - { - "type": "Microsoft.Network/networkSecurityGroups", - "name": "[variables('networkSecurityGroupName')]", - "apiVersion": "2022-01-01", - "location": "[parameters('location')]", - "tags": { - "Description": "Network Security Group to control access to resources" - }, - "properties": { - "securityRules": [ - { - "name": "appgw-https", - "properties": { - "priority": 1000, - "sourceAddressPrefix": "[parameters('Allow connections from')]", - "protocol": "Tcp", - "destinationPortRange": "443", - "access": "Allow", - "direction": "Inbound", - "sourcePortRange": "*", - "destinationAddressPrefix": "[parameters('Subnet2CIDRRange')]" - } - }, - { - "name": "nlm-https", - "properties": { - "priority": 1001, - "sourceAddressPrefix": "[parameters('Allow connections from')]", - "protocol": "Tcp", - "destinationPortRange": "443", - "access": "Allow", - "direction": "Inbound", - "sourcePortRange": "*", - "destinationAddressPrefix": "[parameters('Subnet1CIDRRange')]" - } - }, - { - "name": "rdp", - "properties": { - "priority": 1002, - "sourceAddressPrefix": "[parameters('Allow connections from')]", - "protocol": "Tcp", - "destinationPortRange": "3389", - "access": "Allow", - "direction": "Inbound", - "sourcePortRange": "*", - "destinationAddressPrefix": "*" - } - }, - { - "name": "ssh", - "properties": { - "priority": 1003, - "sourceAddressPrefix": "[parameters('Allow connections from')]", - "protocol": "Tcp", - "destinationPortRange": "22", - "access": "Allow", - "direction": "Inbound", - "sourcePortRange": "*", - "destinationAddressPrefix": "*" - } - }, - { - "name": "appgw-required-by-azure", - "properties": { - "priority": 1004, - "sourceAddressPrefix": "GatewayManager", - "protocol": "Tcp", - "destinationPortRange": "65200-65535", - "access": "Allow", - "direction": "Inbound", - "sourcePortRange": "*", - "destinationAddressPrefix": "*" - } - } - ] - } - }, - { - "type": "Microsoft.Network/virtualNetworks", - "name": "[variables('virtualNetworkName')]", - "apiVersion": "2022-01-01", - "condition": "[equals(variables('virtualNetworkNewOrExisting'), 'new')]", - "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]" - ], - "tags": { - "Description": "Virtual network for the MATLAB Production Server deployment" - }, - "properties": { - "addressSpace": { - "addressPrefixes": ["[variables('addressPrefix')]"] - }, - "subnets": [ - { - "name": "[variables('subnetName')]", - "properties": { - "addressPrefix": "[variables('subnetPrefix')]", - "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]" - } - } - }, - { - "name": "[variables('appGwSubnetName')]", - "properties": { - "addressPrefix": "[variables('appGwSubnetPrefix')]", - "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]" - } - } - } - ] - } - }, - { - "type": "Microsoft.Network/publicIPAddresses", - "name": "[variables('publicIPAddressNameMachine')]", - "apiVersion": "2022-01-01", - "condition": "[equals(parameters('UsePublicIPAddresses'), 'Yes')]", - "sku": { - "name": "Standard" - }, - "location": "[parameters('location')]", - "tags": { - "Description": "Public IP Address of the MATLAB Production Server Dashboard" - }, - "properties": { - "publicIPAllocationMethod": "Static" - } - }, - { - "type": "Microsoft.Network/networkInterfaces", - "name": "[variables('licservernicName')]", - "apiVersion": "2022-01-01", - "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressNameMachine'))]", - "[resourceId('Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]", - "[resourceId('Microsoft.Network/virtualNetworks/',variables('virtualNetworkName'))]", - "[resourceId('Microsoft.Network/applicationGateways/', variables('appGwName'))]" - ], - "tags": { - "Description": "Network Interface Card (NIC) for the Admin VM" - }, - "properties": { - "ipConfigurations": [ - { - "name": "ipconfig1", - "properties": { - "privateIPAllocationMethod": "Dynamic", - "publicIPAddress": "[if(equals(parameters('UsePublicIPAddresses'), 'Yes'), variables('publicIPprop1'), json('null'))]", - "subnet": { - "id": "[variables('subnetRef')]" - }, - "applicationGatewayBackendAddressPools": [ - { - "id": "[resourceId('Microsoft.Network/applicationGateways/backendAddressPools',variables('appGwName'), 'dashboardbackend')]" - } - ] - } - } - ], - "networkSecurityGroup": { - "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]" - } - } - }, - { - "type": "Microsoft.Compute/virtualMachines", - "name": "[variables('vmName')]", - "apiVersion": "2021-03-01", - "tags": { - "Description": "Virtual machine running the Admin Dashboard" - }, - "dependsOn": [ - "[resourceId('Microsoft.Network/networkInterfaces/',variables('licservernicName'))]", - "[resourceId('Microsoft.Network/virtualNetworks/',variables('virtualNetworkName'))]", - "[resourceId('Microsoft.Cache/Redis/',variables('redisCacheName'))]", - "[resourceId('Microsoft.Storage/storageAccounts/',variables('storageAccountName'))]", - "[resourceId('Microsoft.Insights/components', variables('myAppInsightsInstanceName'))]" - ], - "identity": { - "type": "SystemAssigned" - }, - "plan": { - "name": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsSKUDisk1'), variables('LinuxSKUDisk1'))]", - "publisher": "mathworks-inc", - "product": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsOfferDisk1'), variables('LinuxOfferDisk1'))]" - }, - "location": "[parameters('location')]", - "properties": { - "hardwareProfile": { - "vmSize": "[parameters('dashboardVMSize')]" - }, - "osProfile": { - "computerName": "[variables('vmName')]", - "adminUsername": "[parameters('adminUsername')]", - "adminPassword": "[parameters('adminPassword')]" - }, - "storageProfile": { - "imageReference": { - "publisher": "mathworks-inc", - "offer": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsOfferDisk1'), variables('LinuxOfferDisk1'))]", - "sku": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsSKUDisk1'), variables('LinuxSKUDisk1'))]", - "version": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsDisk1Version'), variables('LinuxDisk1Version'))]" - }, - "osDisk": { - "createOption": "FromImage", - "managedDisk": { - "storageAccountType": "Standard_LRS" - } - } - }, - "networkProfile": { - "networkInterfaces": [ - { - "id": "[resourceId('Microsoft.Network/networkInterfaces',variables('licservernicName'))]" - } - ] - } - }, - "resources": [ - { - "type": "extensions", - "name": "config-app", - "apiVersion": "2022-03-01", - "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Compute/virtualMachines/', variables('vmName'))]" - ], - "tags": { - "displayName": "config-app" - }, - "properties": { - "publisher": "Microsoft.Azure.Extensions", - "type": "CustomScript", - "typeHandlerVersion": "2.0", - "autoUpgradeMinorVersion": true, - "settings": { - "skipDos2Unix": false, - "timestamp": 123456789 - }, - "protectedSettings": { - "commandToExecute": "[concat( 'sudo ./initMasterVM.sh ''', variables('storageAccountName'), ''' ''', 'mydbConnection', ''' ''', if(equals(parameters('UsePublicIPAddresses'), 'Yes'), concat('https://', reference(variables('appGwPublicIPAddressName')).dnsSettings.fqdn), concat('https://', variables('appGWprivateIP'), ':444')), ''' ''', reference(variables('subnetRef'), '2022-01-01').addressPrefix, ''' ''', 'Azure', ''' ''', variables('Platform'), ''' ''', reference(resourceId('Microsoft.Insights/components', variables('myAppInsightsInstanceName')), '2020-02-02').InstrumentationKey, ''' ''', resourceGroup().name, ''' ''', subscription().subscriptionId, ''' ''', parameters('adminUsername'), ''' ''', parameters('adminPassword'), ''' ''', variables('redisCacheName'), ''' ''', concat('https://', variables('appGWprivateIP'), ':444'), ''' ''', variables('offerType'), '''' )]", - "fileUris": ["[variables('masterVMScriptURL')]"] - } - } - } - ] - }, - { - "type": "Microsoft.Network/publicIPAddresses", - "name": "[variables('appGwPublicIPAddressName')]", - "apiVersion": "2022-01-01", - "sku": { - "name": "Standard" - }, - "location": "[parameters('location')]", - "properties": { - "publicIPAllocationMethod": "Static", - "dnsSettings": { - "domainNameLabel": "[variables('mpsDNSName')]" - } - }, - "tags": { - "Description": "Application Gateway public IP" - } - }, - { - "type": "Microsoft.Network/applicationGateways", - "name": "[variables('appGwName')]", - "apiVersion": "2022-01-01", - "location": "[parameters('location')]", - "dependsOn": [ - "[resourceId('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]", - "[resourceId('Microsoft.Network/publicIPAddresses/', variables('appGwPublicIPAddressName'))]" - ], - "identity": "[if(equals(parameters('CertificateInputType'), 'KeyVault'), variables('ManagedIdentityResourceIDForKeyVault'), json('null'))]", - "tags": { - "Description": "Application Gateway" - }, - "properties": { - "sku": { - "name": "[variables('AppGatewaySize')]", - "tier": "Standard_v2", - "capacity": "[variables('AppGatewayCount')]" - }, - "sslCertificates": [ - { - "name": "appGatewayFrontEndSslCert", - "properties": { - "keyVaultSecretId": "[if(equals(parameters('CertificateInputType'), 'KeyVault'), parameters('KeyVaultCertificateSecretID'), json('null'))]", - "data": "[if(equals(parameters('CertificateInputType'), 'Base64-encoded PFX Certificate'), parameters('Base64EncodedPFXCertificateData'), json('null'))]", - "password": "[if(equals(parameters('CertificateInputType'), 'Base64-encoded PFX Certificate'), parameters('PasswordForBase64EncodedPFXCertificate'), json('null'))]" - } - } - ], - "gatewayIPConfigurations": [ - { - "name": "appGwIpConfig", - "properties": { - "subnet": { - "id": "[variables('appGwSubnetID')]" - } - } - } - ], - "frontendIPConfigurations": [ - { - "name": "appGwFrontendPublicIP", - "properties": { - "PublicIPAddress": { - "id": "[variables('appGwPublicIPAddressID')]" - } - } - }, - { - "name": "appGwFrontendPrivateIP", - "properties": { - "privateIPAddress": "[variables('appGWprivateIP')]", - "privateIPAllocationMethod": "Static", - "subnet": { - "id": "[variables('appGwSubnetID')]" - } - } - } - ], - "frontendPorts": [ - { - "name": "mpsHttpPort", - "properties": { - "Port": "[variables('mpsFrontEndPort')]" - } - }, - { - "name": "mpsHttpPort2", - "properties": { - "Port": 444 - } - }, - { - "name": "dummyPort", - "properties": { - "Port": 449 - } - }, - { - "name": "port_445", - "properties": { - "port": 443 - } - } - ], - "backendAddressPools": [ - { - "name": "[variables('appGwBePoolName')]" - }, - { - "name": "dashboardbackend", - "properties": {} - } - ], - "backendHttpSettingsCollection": [ - { - "name": "appGwBackendMPSHttpSettings", - "properties": { - "Port": "[variables('mpsHttpPortVar')]", - "Protocol": "Http", - "requestTimeout": 300, - "CookieBasedAffinity": "Enabled", - "probe": { - "id": "[resourceId('Microsoft.Network/applicationGateways/probes',variables('appGwName'), 'mpsfileprobe')]" - } - } - }, - { - "name": "dashboardbackend", - "properties": { - "port": 9090, - "protocol": "Http", - "cookieBasedAffinity": "Disabled", - "pickHostNameFromBackendAddress": true, - "affinityCookieName": "ApplicationGatewayAffinity", - "requestTimeout": 20, - "probe": { - "id": "[resourceId('Microsoft.Network/applicationGateways/probes',variables('appGwName'), 'dashboardHealth')]" - } - } - } - ], - "httpListeners": [ - { - "name": "MPSGwHttpListener", - "properties": { - "FrontendIPConfiguration": { - "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendIPConfigurations', variables('appGwName') ,'appGwFrontendPublicIP')]" - }, - "FrontendPort": { - "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendPorts', variables('appGwName'), 'mpsHttpPort')]" - }, - "Protocol": "Https", - "SslCertificate": { - "Id": "[resourceId('Microsoft.Network/applicationGateways/sslCertificates',variables('appGwName'), 'appGatewayFrontEndSslCert')]" - } - } - }, - { - "name": "MPSGwPrivateHttpListener", - "properties": { - "FrontendIPConfiguration": { - "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendIPConfigurations',variables('appGwName'), 'appGwFrontendPrivateIP')]" - }, - "FrontendPort": { - "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendPorts',variables('appGwName'),'mpsHttpPort2')]" - }, - "Protocol": "Https", - "SslCertificate": { - "Id": "[resourceId('Microsoft.Network/applicationGateways/sslCertificates',variables('appGwName'),'appGatewayFrontEndSslCert')]" - } - } - }, - { - "name": "MPSGwDummyHttpListener", - "properties": { - "FrontendIPConfiguration": { - "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendIPConfigurations',variables('appGwName'), 'appGwFrontendPrivateIP')]" - }, - "FrontendPort": { - "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendPorts',variables('appGwName'),'dummyPort')]" - }, - "Protocol": "Https", - "SslCertificate": { - "Id": "[resourceId('Microsoft.Network/applicationGateways/sslCertificates',variables('appGwName'),'appGatewayFrontEndSslCert')]" - } - } - }, - { - "name": "mainentrypoint", - "properties": { - "frontendIPConfiguration": { - "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendIPConfigurations',variables('appGwName'), 'appGwFrontendPublicIP')]" - }, - "frontendPort": { - "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendPorts',variables('appGwName'),'port_445')]" - }, - "protocol": "Https", - "sslCertificate": { - "Id": "[resourceId('Microsoft.Network/applicationGateways/sslCertificates',variables('appGwName'),'appGatewayFrontEndSslCert')]" - }, - "requireServerNameIndication": false - } - } - ], - "urlPathMaps": [ - { - "name": "mainpath", - "properties": { - "defaultBackendAddressPool": { - "id": "[resourceId('Microsoft.Network/applicationGateways/backendAddressPools',variables('appGwName'), variables('appGwBePoolName'))]" - }, - "defaultBackendHttpSettings": { - "id": "[resourceId('Microsoft.Network/applicationGateways/backendHttpSettingsCollection',variables('appGwName'), 'appGwBackendMPSHttpSettings')]" - }, - "pathRules": [ - { - "name": "dashboard", - "properties": { - "paths": ["/dashboard/*", "/dashboard"], - "backendAddressPool": { - "id": "[resourceId('Microsoft.Network/applicationGateways/backendAddressPools',variables('appGwName'), 'dashboardbackend')]" - }, - "backendHttpSettings": { - "id": "[resourceId('Microsoft.Network/applicationGateways/backendHttpSettingsCollection',variables('appGwName'), 'dashboardbackend')]" - } - } - } - ] - } - } - ], - "requestRoutingRules": [ - { - "name": "mainpathPrivate", - "properties": { - "ruleType": "PathBasedRouting", - "httpListener": { - "id": "[resourceId('Microsoft.Network/applicationGateways/httpListeners',variables('appGwName'), 'MPSGwPrivateHttpListener')]" - }, - "urlPathMap": { - "id": "[resourceId('Microsoft.Network/applicationGateways/urlPathMaps',variables('appGwName'), 'mainpath')]" - }, - "priority": 1 - } - }, - { - "name": "mainpath", - "properties": { - "ruleType": "PathBasedRouting", - "httpListener": { - "id": "[if(equals(parameters('UsePublicIPAddresses'), 'Yes'),resourceId('Microsoft.Network/applicationGateways/httpListeners',variables('appGwName'), 'mainentrypoint'), resourceId('Microsoft.Network/applicationGateways/httpListeners',variables('appGwName'), 'MPSGwDummyHttpListener') )]" - }, - "urlPathMap": { - "id": "[resourceId('Microsoft.Network/applicationGateways/urlPathMaps',variables('appGwName'), 'mainpath')]" - }, - "priority": 2 - } - } - ], - "probes": [ - { - "name": "mpsfileprobe", - "properties": { - "protocol": "Http", - "host": "127.0.0.1", - "path": "/~files/hello.html", - "interval": 30, - "timeout": 30, - "unhealthyThreshold": 3 - } - }, - { - "name": "dashboardHealth", - "properties": { - "protocol": "Http", - "host": "127.0.0.1", - "path": "/dashboard/index.html", - "interval": 30, - "timeout": 30, - "unhealthyThreshold": 3, - "pickHostNameFromBackendHttpSettings": false, - "minServers": 0 - } - } - ] - } - }, - { - "type": "Microsoft.Compute/virtualMachineScaleSets", - "name": "[variables('namingInfix')]", - "apiVersion": "2022-03-01", - "location": "[parameters('location')]", - "identity": { - "type": "SystemAssigned" - }, - "dependsOn": [ - "[resourceId('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]", - "[resourceId('Microsoft.Network/applicationGateways/', variables('appGwName'))]" - ], - "tags": { - "Description": "VM Scale set that controls how many instances are running" - }, - "sku": { - "name": "[parameters('Server VM Instance Size')]", - "tier": "Standard", - "capacity": "[parameters('instanceCount')]" - }, - "plan": { - "name": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsSKUDisk2'), variables('LinuxSKUDisk2'))]", - "publisher": "mathworks-inc", - "product": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsOfferDisk2'), variables('LinuxOfferDisk2'))]" - }, - "properties": { - "overprovision": "true", - "upgradePolicy": { - "mode": "Manual" - }, - "virtualMachineProfile": { - "storageProfile": { - "imageReference": { - "publisher": "mathworks-inc", - "offer": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsOfferDisk2'), variables('LinuxOfferDisk2'))]", - "sku": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsSKUDisk2'), variables('LinuxSKUDisk2'))]", - "version": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsDisk2Version'), variables('LinuxDisk2Version'))]" - }, - "osDisk": { - "createOption": "fromImage", - "managedDisk": { - "storageAccountType": "Standard_LRS" - } - } - }, - "osProfile": { - "computerNamePrefix": "[variables('namingInfix')]", - "adminUsername": "[parameters('adminUsername')]", - "adminPassword": "[parameters('adminPassword')]" - }, - "networkProfile": { - "networkInterfaceConfigurations": [ - { - "name": "[variables('nicName')]", - "properties": { - "primary": true, - "ipConfigurations": [ - { - "name": "[variables('ipConfigName')]", - "properties": { - "subnet": { - "id": "[variables('subnetRef')]" - }, - "ApplicationGatewayBackendAddressPools": [ - { - "id": "[resourceId('Microsoft.Network/applicationGateways/backendAddressPools',variables('appGwName'), variables('appGwBePoolName'))]" - } - ] - } - } - ] - } - } - ] - }, - "extensionProfile": { - "extensions": [ - { - "name": "[concat(variables('vmssName'), 'SetEnvironmentVar')]", - "properties": { - "publisher": "[if(equals(variables('Platform'), 'Windows'), 'Microsoft.Compute', 'Microsoft.Azure.Extensions')]", - "forceUpdateTag": "1", - "type": "[if(equals(variables('Platform'), 'Windows'), 'CustomScriptExtension', 'CustomScript')]", - "typeHandlerVersion": "[if(equals(variables('Platform'), 'Windows'), '1.9', '2.0')]", - "autoUpgradeMinorVersion": true, - "settings": { - "fileUris": [ - "[if(equals(variables('Platform'), 'Windows'), variables('windowsScriptURL'), variables('linuxScriptURL'))]" - ] - }, - "protectedSettings": { - "commandToExecute": "[if(equals(variables('Platform'), 'Windows'), variables('commandToExecuteWindows'), variables('commandToExecuteLinux'))]" - } - } - } - ] - } - } - } - }, - { - "type": "Microsoft.Storage/storageAccounts", - "name": "[variables('storageAccountName')]", - "apiVersion": "2021-06-01", - "location": "[parameters('location')]", - "tags": { - "Description": "Storage account that stores application and config files" - }, - "sku": { - "name": "[variables('storageAccountType')]" - }, - "kind": "storage", - "properties": {} - }, - { - "type": "Microsoft.Cache/Redis", - "name": "[variables('redisCacheName')]", - "apiVersion": "2020-12-01", - "condition": "[equals(parameters('CreateAzureRedisCache'), 'Yes')]", - "tags": { - "Description": "Azure Cache for Redis to store persistence data" - }, - "location": "[parameters('location')]", - "properties": { - "enableNonSslPort": "[variables('redisenableNonSslPort')]", - "sku": { - "capacity": "[variables('redisCacheCapacity')]", - "family": "[variables('redisCacheFamily')]", - "name": "[variables('redisCacheSKU')]" - } - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces", - "name": "[variables('workspaceName')]", - "apiVersion": "2021-06-01", - "location": "[parameters('location')]", - "properties": { - "sku": { - "name": "PerGB2018" - } - } - }, - { - "type": "Microsoft.Insights/Components", - "name": "[variables('myAppInsightsInstanceName')]", - "apiVersion": "2020-02-02", - "dependsOn": [ - "[resourceId('Microsoft.OperationalInsights/workspaces', variables('workspaceName'))]" - ], - "tags": { - "Description": "Application Insights instance that stores solution logs" - }, - "location": "[parameters('location')]", - "properties": { - "Application_Type": "[variables('AppInsights-AppType')]", - "Flow_Type": "Redfield", - "Request_Source": "[variables('AppInsights-requestSource')]", - "WorkspaceResourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', variables('workspaceName'))]" - } - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "name": "[guid(resourceGroup().id, deployment().name,'12')]", - "apiVersion": "2022-04-01", - "scope": "[concat('Microsoft.Storage/storageAccounts', '/', variables('storageAccountName'))]", - "dependsOn": [ - "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" - ], - "properties": { - "roleDefinitionId": "[variables('keyoperator')]", - "principalId": "[reference(resourceId('Microsoft.Compute/virtualMachines', variables('vmName')), '2022-03-01', 'Full').identity.principalId]", - "principalType": "ServicePrincipal" - } - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "name": "[guid(resourceGroup().id, deployment().name,'16')]", - "apiVersion": "2022-04-01", - "scope": "[concat('Microsoft.Storage/storageAccounts', '/', variables('storageAccountName'))]", - "dependsOn": [ - "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" - ], - "properties": { - "roleDefinitionId": "[variables('keyoperator')]", - "principalId": "[reference(resourceId('Microsoft.Compute/virtualMachineScaleSets', variables('namingInfix')), '2022-03-01', 'Full').identity.principalId]", - "principalType": "ServicePrincipal" - } - }, - { - "type": "Microsoft.Authorization/roleAssignments", - "name": "[guid(resourceGroup().id, deployment().name,'22')]", - "apiVersion": "2022-04-01", - "condition": "[equals(parameters('CreateAzureRedisCache'), 'Yes')]", - "scope": "[concat('Microsoft.Cache/Redis', '/', variables('redisCacheName'))]", - "dependsOn": [ - "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]", - "[resourceId('Microsoft.Cache/Redis', variables('redisCacheName'))]" - ], - "properties": { - "roleDefinitionId": "[variables('owner')]", - "principalId": "[reference(resourceId('Microsoft.Compute/virtualMachines', variables('vmName')), '2022-03-01', 'Full').identity.principalId]", - "principalType": "ServicePrincipal" - } - } - ], - "outputs": { - "adminDashboardURL": { - "value": "[uri(if(equals(parameters('UsePublicIPAddresses'), 'Yes'), concat('https://', reference(variables('appGwPublicIPAddressName')).dnsSettings.fqdn, '/dashboard/admin'), concat('https://', variables('appGWprivateIP'), ':444/dashboard/admin')), '')]", - "type": "string" - }, - "managerAndAppAuthorDashboardURL": { - "value": "[uri(if(equals(parameters('UsePublicIPAddresses'), 'Yes'), concat('https://', reference(variables('appGwPublicIPAddressName')).dnsSettings.fqdn, '/dashboard'), concat('https://', variables('appGWprivateIP'), ':444/dashboard')), '')]", - "type": "string" - }, - "networkLicenseManagerURL": { - "value": "[if(equals(variables('should-deploy-flex'), 'Yes'), reference('flex-lm-server').outputs.NetworkLicenseManagerAddress.value, 'none')]", - "type": "string" - }, - "MATLABExecutionEndpoint": { - "value": "[if(equals(parameters('UsePublicIPAddresses'), 'Yes'), concat('https://', reference(variables('appGwPublicIPAddressName')).dnsSettings.fqdn), concat('https://', variables('appGWprivateIP'),':444'))]", - "type": "string" - } - } -} diff --git a/releases/R2022b/README.md b/releases/R2022b/README.md index e50ae33..bfcb5e7 100644 --- a/releases/R2022b/README.md +++ b/releases/R2022b/README.md @@ -107,7 +107,7 @@ configure and manage server instances on the cloud. If your solution uses privat 1. Click **Outputs** from the left pane. Copy the parameter value for **dashboardURL** and paste it in a browser. 1. Log in using the administrator username and password that you specified in the [Configure Cloud Resources](#step-2-configure-cloud-resources) step of the deployment process. -![MATLAB Production Server Dashboard](/releases/R2022a/images/dashboardLogin.png?raw=true) +![MATLAB Production Server Dashboard](/releases/R2022b/images/dashboardLogin.png?raw=true) You are now ready to use MATLAB Production Server on Azure. diff --git a/releases/R2023a/README.md b/releases/R2023a/README.md index 2775b21..245b397 100644 --- a/releases/R2023a/README.md +++ b/releases/R2023a/README.md @@ -76,7 +76,7 @@ configure and manage server instances on the cloud. If your solution uses privat 1. Click **Outputs** from the left pane. Copy the parameter value for **dashboardURL** and paste it in a browser. 1. Log in using the administrator username and password that you specified in the [Configure Cloud Resources](#step-2-configure-cloud-resources) step of the deployment process. -![MATLAB Production Server Dashboard](/releases/R2022a/images/dashboardLogin.png?raw=true) +![MATLAB Production Server Dashboard](/releases/R2023a/images/dashboardLogin.png?raw=true) You are now ready to use MATLAB Production Server on Azure. diff --git a/releases/R2023b/README.md b/releases/R2023b/README.md index f727348..5bb1adf 100644 --- a/releases/R2023b/README.md +++ b/releases/R2023b/README.md @@ -76,7 +76,7 @@ configure and manage server instances on the cloud. If your solution uses privat 1. Click **Outputs** from the left pane. Copy the parameter value for **dashboardURL** and paste it in a browser. 1. Log in using the administrator username and password that you specified in the [Configure Cloud Resources](#step-2-configure-cloud-resources) step of the deployment process. -![MATLAB Production Server Dashboard](/releases/R2022a/images/dashboardLogin.png?raw=true) +![MATLAB Production Server Dashboard](/releases/R2023b/images/dashboardLogin.png?raw=true) You are now ready to use MATLAB Production Server on Azure. diff --git a/releases/R2024a/README.md b/releases/R2024a/README.md index 7b871dd..fc7bf3d 100644 --- a/releases/R2024a/README.md +++ b/releases/R2024a/README.md @@ -76,7 +76,7 @@ configure and manage server instances on the cloud. If your solution uses privat 1. Click **Outputs** from the left pane. Copy the parameter value for **dashboardURL** and paste it in a browser. 1. Log in using the administrator username and password that you specified in the [Configure Cloud Resources](#step-2-configure-cloud-resources) step of the deployment process. -![MATLAB Production Server Dashboard](/releases/R2022a/images/dashboardLogin.png?raw=true) +![MATLAB Production Server Dashboard](/releases/R2024a/images/dashboardLogin.png?raw=true) You are now ready to use MATLAB Production Server on Azure. diff --git a/releases/R2024b/README.md b/releases/R2024b/README.md index 5d57539..4ecf74a 100644 --- a/releases/R2024b/README.md +++ b/releases/R2024b/README.md @@ -76,7 +76,7 @@ configure and manage server instances on the cloud. If your solution uses privat 1. Click **Outputs** from the left pane. Copy the parameter value for **dashboardURL** and paste it in a browser. 1. Log in using the administrator username and password that you specified in the [Configure Cloud Resources](#step-2-configure-cloud-resources) step of the deployment process. -![MATLAB Production Server Dashboard](/releases/R2022a/images/dashboardLogin.png?raw=true) +![MATLAB Production Server Dashboard](/releases/R2024b/images/dashboardLogin.png?raw=true) You are now ready to use MATLAB Production Server on Azure. diff --git a/releases/R2022a/LICENSE.md b/releases/R2025a/LICENSE.md similarity index 100% rename from releases/R2022a/LICENSE.md rename to releases/R2025a/LICENSE.md diff --git a/releases/R2025a/README.md b/releases/R2025a/README.md new file mode 100644 index 0000000..0edcb41 --- /dev/null +++ b/releases/R2025a/README.md @@ -0,0 +1,92 @@ +# MATLAB Production Server on Microsoft Azure - R2025a +Follow these steps to deploy the R2025a MATLAB Production Server reference architecture on Microsoft Azure. To deploy reference architectures for other releases, see [Deploy Reference Architecture for Your Release](/README.md#deploy-reference-architecture-for-your-release). + +## Prerequisites +Before deploying MATLAB Production within an existing virtual network, you must configure the virtual network to enable connectivity. For details, see [How do I deploy to an existing virtual network?](/README.md#how-do-i-deploy-to-an-existing-virtual-network) + + +## Step 1. Launch Template +To deploy resources on Azure, click **Deploy to Azure**. The Azure Portal opens in your web browser. + +[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fmathworks-ref-arch%2Fmatlab-production-server-on-azure%2Fmaster%2Freleases%2FR2025a%2Ftemplates%2Fazuredeploy25a.json) + +> MATLAB Release: R2025a + +

Creating resources on Azure can take at least 30 minutes.

+ +## Step 2. Configure Cloud Resources + +Provide values for parameters in the custom deployment template on the Azure Portal: + +| Parameter Name | Value | +|--------------- | ----- | +| **Subscription** | Choose an Azure subscription to use for purchasing resources.

Example: VERTHAM Dev

| +| **Resource group** | Choose a name for the resource group that will hold the resources. It is recommended you create a new resource group for each deployment. This allows all resources in a group to be deleted simultaneously.

Example: Saveros

| +| **Region** | Choose the region to start resources in. Ensure that you select a location which supports your requested instance types. To check which services are supported in each location, see [Azure Region Services](). MathWorks recommends using `East US` or `East US 2`.

Example: `East US`

| +| **Location** | Region to store resources in. All resources are deployed in the same region as the resource group.

Examples: `eastus`, `westus`, `westus3`

| | +| **Dashboard VM Size** | Specify the size of the VM you plan on using for the MATLAB Production Server dashboard. The dashboard lets you configure server settings and manage deployed applications. In most cases, choosing the smallest VM size is adequate. The template defaults to Standard_D1_v2. For more information, see the [Azure documentation](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/sizes-general).

Example: Standard_D1_v2

| +| **Instance Count** | Number of VMs to run MATLAB Production Server instances. Each MATLAB Production Server instance runs on a VM and each instance runs multiple workers.

Example: 6

If you have a standard 24 worker MATLAB Production Server license and select Standard_D4s_v3 VM (4 cores) as the Server VM Instance Size, you need 6 VMs to fully use the workers in your license. Therefore, your instance count will be 6.

You can always underprovision the number of VMs, in which case you may end up using fewer workers than you are licensed for.

| +| **Admin Username** | Specify the administrator username for all VMs. Use this username to log in to the MATLAB Production Server dashboard and Network License Manager. | +| **Admin Password** | Specify the administrator password for all VMs. Use this password to log in to the MATLAB Production Server dashboard and Network License Manager. | +| **Allow connections from** | Specify the IP address range that is allowed to connect to the MATLAB Production Server instance, the Network License Manager, and the dashboard that manages the server. The IP addresses you specify here are allowed to execute deployed MATLAB functions. If you deploy a new Network License Manager instance along with MATLAB Production Server, then only the specified addresses can access Network License Manager. If you use a previously deployed instance of Network License Manager, you can use the Azure Portal to specify additional IP address ranges that can access the storage account. To do so, in your storage account settings under **Networking**, add IP address ranges using the IP Address/Mask format.

Example: `x.x.x.x/24`

You can also specify multiple IP addresses with a comma-separated format, without spaces.

Example: `x.x.x.x/24,z.z.z.z/24`

  • To determine your IP address, you can search for "**what is my ip address**" on the web. The mask determines the number of IP addresses to include.
  • A mask of 32 is a single IP address.
  • If you need a range of IP addresses, use a [CIDR calculator](https://www.ipaddressguide.com/cidr).
  • To determine which address is appropriate, contact your IT administrator.

| +| **Create Azure Redis Cache**| Choose whether you want to create an Azure Redis Cache service. Creating this service will allow you to use the persistence functionality of the server. Persistence provides a mechanism to cache data between calls to MATLAB code running on a server instance.| +| **Use Public IP Addresses**| Specify whether to assign a public IP address to the virtual machine hosting the server. This setting also controls which IP addresses are allowed to access the storage account.
  • If you select `Yes`, Azure assigns the MATLAB Production Server VM a public IP address, and you can access the storage account using the MATLAB Production Server VM.
    Additionally, the first entry in **Allow Connections From** template parameter is allowed to access the storage account. You can use the Azure Portal to specify additional IP address ranges that can access the storage account. To do so, in your storage account settings under **Networking**, add IP address ranges using the IP Address/Mask format.
    **Note:** If you select `Yes` and are using an existing virtual network, then you must manually add a service endpoint to the virtual network before deploying MATLAB Production Server in order to create and access the storage account. For details, see [How do I deploy to an existing virtual network?](/README.md#how-do-i-deploy-to-an-existing-virtual-network)
  • If you select `No`, the MATLAB Production Server VM is assigned a private IP, and the storage account's public network access is disabled. You can access the storage account, the home page, or remotely connect to the server machine by creating a new virtual machine that is in the same virtual network as the MATLAB Production Server deployment. This VM is called a Bastion host or jumpbox. For details, see [Overview of Azure Bastion host and jumpboxes](https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/scenarios/cloud-scale-analytics/architectures/connect-to-environments-privately).
| +|**Platform**| Choose the operating system for the server. Microsoft Windows and Linux are the only available options. | +|**New or Existing Virtual Network**| Select `new` to create a new virtual network for your deployment using the default values shown in the parameters after this one. Any changes to these parameter values are ignored.

When deploying to a new virtual network, by default, the ports listed [here](/README.md#ports-to-open-in-existing-virtual-network) are opened. Depending on your security requirements, you can choose to close ports 22 and 3389 after the deployment is complete.

If you are deploying to an existing virtual network, you may need to configure the network before deployment. For details, see [How do I deploy to an existing virtual network?](/README.md#how-do-i-deploy-to-an-existing-virtual-network) | +| **Virtual Network Name** | Specify the name of your existing virtual network or use the default value. | +| **Virtual Network CIDR Range** | Specify the IP address range of the virtual network in CIDR notation or use the default value. | +| **Subnet 1 CIDR Range** | Specify the IP address range of the first subnet in CIDR notation or use the default value. The first subnet hosts the dashboard and other resources. | +| **Subnet 2 CIDR Range** | Specify the IP address range of the second subnet in CIDR notation or use the default value. The second subnet hosts the application gateway. | +| **Available Subnet 2 IP Address** | Specify an unused IP address from Subnet 2 or use the default value. This IP address serves as the private IP of the application gateway. | +| **Resource Group Name Of Virtual Network** | Specify the resource group name of the virtual network or use the default value. | +|**Deploy Network License Manager for MATLAB**| Select whether you want to deploy the Network License Manager for MATLAB to manage your license files. Selecting `Yes` deploys the Network License Manager for the MATLAB reference architecture. Select `No` if you want to use an existing license server. | +| **Certificate Input Type** | Select how you want to specify the SSL certificate for the Azure application gateway to use. The Azure application gateway provides an HTTPS endpoint that you use to connect to server instances and the MATLAB Production Server dashboard. You must select one of these options:

  • KeyVault: Specify an SSL certificate that exists in the Azure Key Vault.
  • Base64-encoded PFX Certificate: Specify a string that is a base64-encoded value of an SSL certificate that is in PFX format.

Specify the certificate data for your selected option in the parameters that follow. | + +If you set **Certificate Input Type** to 'KeyVault', specify these parameters: +| Parameter Name | Value | +|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Key Vault Certificate Secret ID** | Enter the secret ID of the SSL certificate present in the Key Vault. To create a Key Vault and add a certificate, see [Add a certificate to Key Vault](https://learn.microsoft.com/en-us/azure/key-vault/certificates/quick-create-portal#add-a-certificate-to-key-vault) (Azure).
| +| **Managed Identity Resource ID for Key Vault** | Enter the resource ID of the user-assigned managed identity that has permission to access the Key Vault. If your managed identity does not have access to the Key Vault, the deployment fails.

  • To create a managed identity, see [Create a user-assigned managed identity](https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/how-to-manage-ua-identity-portal#create-a-user-assigned-managed-identity) (Azure).
  • To grant your managed identity access to the Key Vault, assign it an access policy with at least "Get" permissions to the key, secret, and certificate. See [Assign a Key Vault access policy](https://learn.microsoft.com/en-us/azure/key-vault/general/assign-access-policy) (Azure).
| + +If you set **Certificate Input Type** to 'Base64-encoded PFX Certificate', specify these parameters: +| Parameter Name | Value | +|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Base64Encoded PFX Certificate Data** | Enter a string that is a base64-encoded value of an SSL certificate in PFX format. | +| **Password For Base64Encoded PFX Certificate** | If the certificate requires a password, enter it here. Otherwise, leave the parameter blank. | + +Click **Create** to begin the deployment. This can take up to 40 minutes. + +## Step 3. Upload License File +The Network License Manager for MATLAB manages the MATLAB Production Server license file. The MATLAB Production Server deployment template provides an option to deploy the license manager or use an existing license manager. For more information about the Network License Manager for MATLAB, see [Network License Manager for MATLAB](https://github.com/mathworks-ref-arch/license-manager-for-matlab-on-azure). The following steps show how to upload the license file using the Network License Manager for MATLAB dashboard: +> **Note**: You must provide a fixed license server MAC address to get a license file from the MathWorks License Center. For more information, see [Configure MATLAB Production Server License for Use on the Cloud](https://www.mathworks.com/help/mps/server/configure-matlab-production-server-license-for-use-on-the-cloud.html). +1. In the Azure Portal, click **Resource + groups** and select the resource group containing your cluster resources. +1. Select **Deployments** from the left pane and click **Microsoft.Template**. +1. Click **Outputs**. Copy the parameter value for **networkLicenseManagerURL** and paste it in a browser. +1. Log in using the administrator username and password that you specified in the [Configure Cloud Resources](#step-2-configure-cloud-resources) step of the deployment process. +1. Follow the instructions in the Network License Manager for MATLAB dashboard to upload your MATLAB Production Server license. + + +## Step 4. Connect and Log In to the Dashboard +The MALAB Production Server dashboard provides a web-based interface to +configure and manage server instances on the cloud. If your solution uses private IP addresses, you can connect to the dashboard from a VM that belongs to the same virtual network as the VM that hosts the dashboard. +> **Note:** Complete these steps only after your resource group has been successfully created. + +> **Note:** The Internet Explorer web browser is not supported for interacting with the dashboard. + +1. In the Azure Portal, click **Resource + groups** and select the resource group you created for this deployment from the list. +1. Select **Deployments** from the left pane and click **Microsoft.Template**. +1. Click **Outputs** from the left pane. Copy the parameter value for **dashboardURL** and paste it in a browser. +1. Log in using the administrator username and password that you specified in the [Configure Cloud Resources](#step-2-configure-cloud-resources) step of the deployment process. + +![MATLAB Production Server Dashboard](/releases/R2025a/images/dashboardLogin.png?raw=true) + +You are now ready to use MATLAB Production Server on Azure. + +For more information on how to use the dashboard, see [Manage MATLAB Production Server Using the Dashboard](https://www.mathworks.com/help/mps/server/use-matlab-production-server-cloud-dashboard-on-azure-reference-architecture.html). + +Configuring role-based access control for the dashboard is recommended. Role-based access control uses Azure AD to let you grant users the privileges to perform tasks on the dashboard and server, based on their role. For more information on how to configure role-based access control, see [Dashboard Access Control](https://www.mathworks.com/help/mps/server/dashboard-access-control-for-azure-reference-architecture.html). + +To run applications on MATLAB Production Server, you will need to create applications using MATLAB Compiler SDK. For more information, see [Create Deployable Archive for MATLAB Production Server](https://www.mathworks.com/help/compiler_sdk/mps_dev_test/create-a-deployable-archive-for-matlab-production-server.html). + diff --git a/releases/R2022a/images/dashboardLogin.png b/releases/R2025a/images/dashboardLogin.png similarity index 100% rename from releases/R2022a/images/dashboardLogin.png rename to releases/R2025a/images/dashboardLogin.png diff --git a/releases/R2022a/images/mps-ref-arch-azure-architecture-diagram.jpg b/releases/R2025a/images/mps-ref-arch-azure-architecture-diagram.jpg similarity index 100% rename from releases/R2022a/images/mps-ref-arch-azure-architecture-diagram.jpg rename to releases/R2025a/images/mps-ref-arch-azure-architecture-diagram.jpg diff --git a/releases/R2022a/scripts/initMasterVM.sh b/releases/R2025a/scripts/initAdminVM.sh similarity index 77% rename from releases/R2022a/scripts/initMasterVM.sh rename to releases/R2025a/scripts/initAdminVM.sh index 2daf401..84558b9 100644 --- a/releases/R2022a/scripts/initMasterVM.sh +++ b/releases/R2025a/scripts/initAdminVM.sh @@ -2,6 +2,14 @@ WORKSPACE=/opt/mathworks +LOG_DIR=/var/log/custom_script +LOG_FILE=$LOG_DIR/custom_script.log + +# Create log directory and file +sudo mkdir -p $LOG_DIR +sudo touch $LOG_FILE +sudo chmod 666 $LOG_FILE + # $0 is the file name storageAccountName="$1" @@ -70,6 +78,18 @@ cp ./.shadow ./bin/. echo "Copied shadow file" +# Update package lists and log errors +sudo apt-get update 2>> $LOG_FILE +if [ $? -ne 0 ]; then + echo "apt update failed. Check the log file at $LOG_FILE" | tee -a $LOG_FILE +fi + +# Install openssh-server and log errors +sudo apt-get install -y openssh-server 2>> $LOG_FILE +if [ $? -ne 0 ]; then + echo "apt install failed. Check the log file at $LOG_FILE" | tee -a $LOG_FILE +fi + systemctl restart refarchcontroller echo "Restarted daemon successfully!" diff --git a/releases/R2022a/scripts/scriptScaleSet.ps1 b/releases/R2025a/scripts/scriptScaleSet.ps1 similarity index 100% rename from releases/R2022a/scripts/scriptScaleSet.ps1 rename to releases/R2025a/scripts/scriptScaleSet.ps1 diff --git a/releases/R2025a/scripts/scriptScaleSet.sh b/releases/R2025a/scripts/scriptScaleSet.sh new file mode 100644 index 0000000..c8e1d66 --- /dev/null +++ b/releases/R2025a/scripts/scriptScaleSet.sh @@ -0,0 +1,23 @@ +#! /bin/bash +#Put your extra commands here +LOG_DIR=/var/log/custom_script +LOG_FILE=$LOG_DIR/custom_script.log + +# Create log directory and file +sudo mkdir -p $LOG_DIR +sudo touch $LOG_FILE +sudo chmod 666 $LOG_FILE + +# Update package lists and log errors +sudo apt-get update 2>> $LOG_FILE +if [ $? -ne 0 ]; then + echo "apt update failed. Check the log file at $LOG_FILE" | tee -a $LOG_FILE +fi + +# Install openssh-server and log errors +sudo apt-get install -y openssh-server 2>> $LOG_FILE +if [ $? -ne 0 ]; then + echo "apt install failed. Check the log file at $LOG_FILE" | tee -a $LOG_FILE +fi + +ls diff --git a/releases/R2025a/templates/azuredeploy25a.json b/releases/R2025a/templates/azuredeploy25a.json new file mode 100644 index 0000000..22169b1 --- /dev/null +++ b/releases/R2025a/templates/azuredeploy25a.json @@ -0,0 +1,1289 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "Server VM Instance Size": { + "defaultValue": "Standard_D4s_v3", + "type": "String", + "metadata": { + "description": "Each VM instance will run multiple workers. Select a VM size that is appropriate for your needs. It is recommended that you choose a VM size where the number of cores on your VM match the number of workers per VM you plan on using." + } + }, + "dashboardVMSize": { + "defaultValue": "Standard_D1_v2", + "type": "String", + "metadata": { + "description": "Size of the server dashboard VM. The dashboard manages server settings and deployed applications. Since this VM does not perform any significant computation, a smaller size is recommended." + } + }, + "instanceCount": { + "defaultValue": 1, + "minValue": 1, + "maxValue": 24, + "type": "Int", + "metadata": { + "description": "Number of VM instances." + } + }, + "adminUsername": { + "type": "String", + "metadata": { + "description": "Administrator username on all VMs." + } + }, + "adminPassword": { + "type": "SecureString", + "metadata": { + "description": "Administrator password on all VMs." + } + }, + "Allow connections from": { + "type": "String", + "metadata": { + "description": "Specify the range of IP addresses in CIDR notation which will be allowed to use the solution. For example: 192.168.1.0/24. This can be a comma-separated list of CIDR ranges (no spaces), i.e. 192.168.1.0/24,10.0.0.0/8,172.16.0.0/16." + } + }, + "CreateAzureRedisCache": { + "defaultValue": "No", + "allowedValues": [ + "Yes", + "No" + ], + "type": "String", + "metadata": { + "description": "Specify whether you want to create an Azure Redis Cache that lets you use the data caching functionality on the server." + } + }, + "UsePublicIPAddresses": { + "defaultValue": "Yes", + "allowedValues": [ + "Yes", + "No" + ], + "type": "String", + "metadata": { + "description": "Specify whether you want to use public IP addresses and make your solution available over the Internet." + } + }, + "Platform": { + "defaultValue": "Linux", + "allowedValues": [ + "Windows", + "Linux" + ], + "type": "String", + "metadata": { + "description": "Select the operating system for the server." + } + }, + "NewOrExistingVirtualNetwork": { + "defaultValue": "new", + "allowedValues": [ + "new", + "existing" + ], + "type": "String", + "metadata": { + "description": "Specify whether to create a new virtual network or use an existing one." + } + }, + "VirtualNetworkName": { + "defaultValue": "mps-network", + "type": "String", + "metadata": { + "description": "Name of your existing virtual network where you want to deploy this solution." + } + }, + "Subnet1": { + "defaultValue": "default", + "type": "String", + "metadata": { + "description": "Name of the subnet that will host the dashboard and other resources." + } + }, + "Subnet2": { + "defaultValue": "appGwSubnet", + "type": "String", + "metadata": { + "description": "Name of the subnet that will host the application gateway." + } + }, + "VirtualNetworkCIDRRange": { + "defaultValue": "10.0.0.0/16", + "type": "String", + "metadata": { + "description": "CIDR range of the virtual network." + } + }, + "Subnet1CIDRRange": { + "defaultValue": "10.0.0.0/24", + "type": "String", + "metadata": { + "description": "CIDR range of the first subnet in the virtual network." + } + }, + "Subnet2CIDRRange": { + "defaultValue": "10.0.1.0/24", + "type": "String", + "metadata": { + "description": "CIDR range of the second subnet in the virtual network." + } + }, + "AvailableSubnet2IPAddress": { + "defaultValue": "10.0.1.4", + "type": "String", + "metadata": { + "description": "Specify an unused IP address from Subnet 2. This IP address serves as the private IP of the Application Gateway." + } + }, + "ResourceGroupNameOfVirtualNetwork": { + "defaultValue": "[resourceGroup().name]", + "type": "String", + "metadata": { + "description": "Specify the resource group name of the virtual network." + } + }, + "DeployNetworkLicenseManagerforMATLAB": { + "defaultValue": "Yes", + "allowedValues": [ + "Yes", + "No" + ], + "type": "String", + "metadata": { + "description": "Specify whether you want to deploy the Network License Manager for MATLAB." + } + }, + "CertificateInputType": { + "defaultValue": "KeyVault", + "allowedValues": [ + "KeyVault", + "Base64-encoded PFX Certificate" + ], + "type": "String", + "metadata": { + "description": "Select if the Application Gateway will use an SSL certificate from the KeyVault or a base64-encoded PFX certificate string. If you select \"KeyVault\", enter values for \"ManagedIdentityResourceIDForKeyVault\" and \"KeyVaultCertificateSecretID\". If you select \"Base64-encoded PFX Certificate\", enter values for \"Base64EncodedPFXCertificateData\" and \"PasswordForBase64EncodedPFXCertificate\"." + } + }, + "KeyVaultCertificateSecretID": { + "defaultValue": "", + "type": "SecureString", + "metadata": { + "description": "Secret ID of SSL certificate present in Key Vault. Required if \"Certificate Input Type\" is \"KeyVault\"." + } + }, + "ManagedIdentityResourceIDForKeyVault": { + "defaultValue": "", + "type": "String", + "metadata": { + "description": "Resource ID of the managed identity that has permission to access Key Vault. Required if \"Certificate Input Type\" is \"KeyVault\"." + } + }, + "Base64EncodedPFXCertificateData": { + "defaultValue": "", + "type": "String", + "metadata": { + "description": "Base64-encoded SSL certificate string in PFX format. Required if \"Certificate Input Type\" is \"Base64-encoded PFX Certificate\"." + } + }, + "PasswordForBase64EncodedPFXCertificate": { + "defaultValue": "", + "type": "SecureString", + "metadata": { + "description": "Password for Base64-encoded SSL certificate. Required if \"Certificate Input Type\" is \"Base64-encoded PFX Certificate\"." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Location for all resources. This is automatically set to the resource group location. Do not change." + } + } + }, + "variables": { + "ManagedIdentityResourceIDForKeyVault": { + "type": "UserAssigned", + "userAssignedIdentities": { + "[parameters('ManagedIdentityResourceIDForKeyVault')]": {} + } + }, + "AppGatewaySize": "Standard_v2", + "AppGatewayCount": 1, + "mpsDNSName": "[concat('mps',uniqueString( resourceGroup().id))]", + "storageAccountName": "[concat('serverlog',uniqueString( resourceGroup().id))]", + "storageAccountType": "Standard_LRS", + "storagePrivateEndpointName": "storagePrivateEndpoint", + "fileStorageDnsZone": "[concat('privatelink.file.', environment().suffixes.storage)]", + "storagePrivateEndpointDnsGroupName": "[format('{0}/mwStorageDnsZoneGroup', variables('storagePrivateEndpointName'))]", + "vmssName": "vmss1", + "namingInfix": "[toLower(substring(concat(variables('vmssName'), uniqueString(resourceGroup().id)), 0, 9))]", + "addressPrefix": "[parameters('VirtualNetworkCIDRRange')]", + "subnetPrefix": "[parameters('Subnet1CIDRRange')]", + "virtualNetworkName": "[parameters('VirtualNetworkName')]", + "subnetName": "[parameters('Subnet1')]", + "subnetRef": "[resourceId(variables('ResourceGroupNameOfVirtualNetwork'),'Microsoft.Network/virtualNetworks/subnets',variables('virtualNetworkName'),variables('subnetName'))]", + "nicName": "[concat(variables('namingInfix'), 'nic')]", + "ipConfigName": "[concat(variables('namingInfix'), 'ipconfig')]", + "allowedIpArray": "[split(parameters('Allow connections from'), ',')]", + "ResourceGroupNameOfVirtualNetwork": "[parameters('ResourceGroupNameOfVirtualNetwork')]", + "virtualNetworkID": "[resourceId(variables('ResourceGroupNameOfVirtualNetwork'), 'Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]", + "appGwPublicIPAddressName": "[concat(variables('namingInfix'), '-pip')]", + "appGwName": "[concat(variables('namingInfix'), '-agw')]", + "appGwPublicIPAddressID": "[resourceId('Microsoft.Network/publicIPAddresses',variables('appGwPublicIPAddressName'))]", + "appGwSubnetName": "[parameters('Subnet2')]", + "appGwSubnetPrefix": "[parameters('Subnet2CIDRRange')]", + "appGwSubnetID": "[resourceId(variables('ResourceGroupNameOfVirtualNetwork'),'Microsoft.Network/virtualNetworks/subnets',variables('virtualNetworkName'),variables('appGwSubnetName'))]", + "backendCertData": "MIIB2DCCAX8CFFvkwj8cUBb+KNQffgdLa+w7BSu+MAoGCCqGSM49BAMCMG8xCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMQ8wDQYDVQQHDAZuYXRpY2sxEjAQBgNVBAoMCU1hdGhXb3JrczELMAkGA1UECwwCREMxFjAUBgNVBAMMDW1hdGh3b3Jrcy5jb20wHhcNMjIxMjE1MDIzMjA4WhcNMzIxMjEyMDIzMjA4WjBvMQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVzZXR0czEPMA0GA1UEBwwGbmF0aWNrMRIwEAYDVQQKDAlNYXRoV29ya3MxCzAJBgNVBAsMAkRDMRYwFAYDVQQDDA1tYXRod29ya3MuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESCAyt8cSVzBBX5/9WZf3YolAo20yXbQi2hoPNp+yAQ41P0Z4IOzdWoVVHwGXSJly7w0GGfuvPUqfpKZgyFwimjAKBggqhkjOPQQDAgNHADBEAiBBGDad5/W52Ed5YVdvQv8wzhTTobDVDWk2twYdc1waWQIgClqMtAKY5zjkOXfXUGhL1SoIWxJTj4cGqFCw/MAkfrc=", + "mpsHttpPortVar": 9910, + "mpsFrontEndPort": 445, + "appGwBePoolName": "[concat(variables('namingInfix'), 'appGwBepool')]", + "networkSecurityGroupName": "[concat(variables('namingInfix'), '-rdp-nsg')]", + "publicIPAddressNameMachine": "admindashboard-public-ip", + "redisCacheName": "[concat(variables('namingInfix'), 'redis')]", + "redisenableNonSslPort": true, + "redisCacheCapacity": 1, + "redisCacheFamily": "C", + "redisCacheSKU": "Standard", + "privateEndpointName": "redisPrivateEndpoint", + "privateDnsZoneName": "privatelink.redis.cache.windows.net", + "privateEndpointDnsGroupName": "[format('{0}/mydnsgroupname', variables('privateEndpointName'))]", + "appGWprivateIP": "[parameters('AvailableSubnet2IPAddress')]", + "virtualNetworkNewOrExisting": "[parameters('NewOrExistingVirtualNetwork')]", + "licservernicName": "admindashboard-nic", + "vmName": "admindashboard", + "publicIPprop1": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressNameMachine'))]" + }, + "Platform": "[parameters('Platform')]", + "WindowsSKUDisk1": "matlab-production-server-admin-vm-25a", + "WindowsOfferDisk1": "matlab-production-server-payg-master", + "WindowsSKUDisk2": "matlab-production-server-worker-windows-25a", + "WindowsOfferDisk2": "matlab-production-server-byol-windows", + "LinuxSKUDisk1": "[variables('WindowsSKUDisk1')]", + "LinuxOfferDisk1": "[variables('WindowsOfferDisk1')]", + "LinuxSKUDisk2": "matlab-production-server-worker-linux-25a", + "LinuxOfferDisk2": "matlab-production-server-byol-linux", + "WindowsDisk1Version": "latest", + "WindowsDisk2Version": "latest", + "LinuxDisk1Version": "[variables('WindowsDisk1Version')]", + "LinuxDisk2Version": "latest", + "windowsScriptURL": "[uri(variables('_artifactsLocation'), concat('scriptScaleSet.ps1', variables('_artifactsLocationSasToken')))]", + "linuxScriptURL": "[uri(variables('_artifactsLocation'), concat('scriptScaleSet.sh', variables('_artifactsLocationSasToken')))]", + "adminVMScriptURL": "[uri(variables('_artifactsLocation'), concat('initAdminVM.sh', variables('_artifactsLocationSasToken')))]", + "commandToExecuteWindows": "[concat('powershell -ExecutionPolicy Unrestricted -File scriptScaleSet.ps1 ' )]", + "commandToExecuteLinux": "[concat('sudo ./scriptScaleSet.sh')]", + "AppInsights-AppType": "Node.JS", + "AppInsights-requestSource": "rest", + "myAppInsightsInstanceName": "logs-apmservice", + "workspaceName": "logs-workspace", + "keyoperator": "[resourceId('Microsoft.Authorization/roleDefinitions', '81a9662b-bebf-436f-a333-f67b29880f12')]", + "owner": "[resourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "offerType": "BYOL", + "should-deploy-flex": "[parameters('DeployNetworkLicenseManagerforMATLAB')]", + "flex-arm-template-link": "https://mwappdeployment.blob.core.windows.net/webappserver-artifacts-r2025a/license-manager.json?sp=racwd&st=2024-12-23T15:07:25Z&se=2025-05-27T22:07:25Z&spr=https&sv=2022-11-02&sr=b&sig=xfakCE61Mlx2N7Wv00k0gQGWg7ZhEU1yespjZK4dc98%3D", + "flex-parameters": { + "instanceType": { + "value": "Standard_D2s_v3" + }, + "clientIPAddressList": { + "value": "[parameters('Allow connections from')]" + }, + "adminUsername": { + "value": "[parameters('adminUsername')]" + }, + "adminPassword": { + "value": "[parameters('adminPassword')]" + }, + "existingVnetResourceID": { + "value": "[variables('virtualNetworkID')]" + }, + "existingSubnetName": { + "value": "[variables('subnetName')]" + }, + "createPublicIPAddress": { + "value": "[parameters('UsePublicIPAddresses')]" + } + }, + "_artifactsLocation": "https://raw.githubusercontent.com/mathworks-ref-arch/matlab-production-server-on-azure/staging/releases/R2025a/scripts/", + "_artifactsLocationSasToken": "" + }, + "resources": [ + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "flex-lm-server", + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces/',variables('licservernicName'))]", + "[resourceId('Microsoft.Network/virtualNetworks/',variables('virtualNetworkName'))]" + ], + "properties": { + "mode": "Incremental", + "templateLink": { + "uri": "[variables('flex-arm-template-link')]", + "contentVersion": "1.0.0.0" + }, + "parameters": "[variables('flex-parameters')]" + }, + "condition": "[equals(variables('should-deploy-flex'), 'Yes')]" + }, + { + "type": "Microsoft.Network/networkSecurityGroups", + "apiVersion": "2024-03-01", + "name": "[variables('networkSecurityGroupName')]", + "location": "[parameters('location')]", + "tags": { + "Description": "Network Security Group to control access to resources" + }, + "properties": { + "securityRules": [ + { + "name": "appgw-https", + "properties": { + "priority": 1000, + "sourceAddressPrefixes": "[variables('allowedIpArray')]", + "protocol": "Tcp", + "destinationPortRange": "443", + "access": "Allow", + "direction": "Inbound", + "sourcePortRange": "*", + "destinationAddressPrefix": "[parameters('Subnet2CIDRRange')]" + } + }, + { + "name": "nlm-https", + "properties": { + "priority": 1001, + "sourceAddressPrefixes": "[variables('allowedIpArray')]", + "protocol": "Tcp", + "destinationPortRange": "443", + "access": "Allow", + "direction": "Inbound", + "sourcePortRange": "*", + "destinationAddressPrefix": "[parameters('Subnet1CIDRRange')]" + } + }, + { + "name": "rdp", + "properties": { + "priority": 1002, + "sourceAddressPrefixes": "[variables('allowedIpArray')]", + "protocol": "Tcp", + "destinationPortRange": "3389", + "access": "Allow", + "direction": "Inbound", + "sourcePortRange": "*", + "destinationAddressPrefix": "*" + } + }, + { + "name": "ssh", + "properties": { + "priority": 1003, + "sourceAddressPrefixes": "[variables('allowedIpArray')]", + "protocol": "Tcp", + "destinationPortRange": "22", + "access": "Allow", + "direction": "Inbound", + "sourcePortRange": "*", + "destinationAddressPrefix": "*" + } + }, + { + "name": "appgw-required-by-azure", + "properties": { + "priority": 1004, + "sourceAddressPrefix": "GatewayManager", + "protocol": "Tcp", + "destinationPortRange": "65200-65535", + "access": "Allow", + "direction": "Inbound", + "sourcePortRange": "*", + "destinationAddressPrefix": "*" + } + } + ] + } + }, + { + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2024-03-01", + "name": "[variables('virtualNetworkName')]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]" + ], + "tags": { + "Description": "Virtual network for the MATLAB Production Server deployment" + }, + "properties": { + "addressSpace": { + "addressPrefixes": [ + "[variables('addressPrefix')]" + ] + }, + "subnets": [ + { + "name": "[variables('subnetName')]", + "properties": { + "addressPrefix": "[variables('subnetPrefix')]", + "networkSecurityGroup": { + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]" + }, + "serviceEndpoints": [ + { + "service": "Microsoft.Storage", + "locations": "[parameters('location')]" + } + ] + } + }, + { + "name": "[variables('appGwSubnetName')]", + "properties": { + "addressPrefix": "[variables('appGwSubnetPrefix')]", + "networkSecurityGroup": { + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]" + } + } + } + ] + }, + "condition": "[equals(variables('virtualNetworkNewOrExisting'), 'new')]" + }, + { + "type": "Microsoft.Network/publicIPAddresses", + "apiVersion": "2024-03-01", + "name": "[variables('publicIPAddressNameMachine')]", + "location": "[parameters('location')]", + "tags": { + "Description": "Public IP Address of the MATLAB Production Server Dashboard" + }, + "sku": { + "name": "Standard" + }, + "properties": { + "publicIPAllocationMethod": "Static" + }, + "condition": "[equals(parameters('UsePublicIPAddresses'), 'Yes')]" + }, + { + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2024-03-01", + "name": "[variables('licservernicName')]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressNameMachine'))]", + "[resourceId('Microsoft.Network/networkSecurityGroups/', variables('networkSecurityGroupName'))]", + "[resourceId('Microsoft.Network/virtualNetworks/',variables('virtualNetworkName'))]", + "[resourceId('Microsoft.Network/applicationGateways/', variables('appGwName'))]" + ], + "tags": { + "Description": "Network Interface Card (NIC) for the Admin VM" + }, + "properties": { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "privateIPAllocationMethod": "Dynamic", + "publicIPAddress": "[if(equals(parameters('UsePublicIPAddresses'), 'Yes'), variables('publicIPprop1'), json('null'))]", + "subnet": { + "id": "[variables('subnetRef')]" + }, + "applicationGatewayBackendAddressPools": [ + { + "id": "[resourceId('Microsoft.Network/applicationGateways/backendAddressPools',variables('appGwName'), 'dashboardbackend')]" + } + ] + } + } + ], + "networkSecurityGroup": { + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]" + } + } + }, + { + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2024-03-01", + "name": "[variables('vmName')]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces/',variables('licservernicName'))]", + "[resourceId('Microsoft.Network/virtualNetworks/',variables('virtualNetworkName'))]", + "[resourceId('Microsoft.Cache/Redis/',variables('redisCacheName'))]", + "[resourceId('Microsoft.Storage/storageAccounts/',variables('storageAccountName'))]", + "[resourceId('Microsoft.Insights/components', variables('myAppInsightsInstanceName'))]" + ], + "tags": { + "Description": "Virtual machine running the Admin Dashboard" + }, + "identity": { + "type": "SystemAssigned" + }, + "plan": { + "name": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsSKUDisk1'), variables('LinuxSKUDisk1'))]", + "publisher": "mathworks-inc", + "product": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsOfferDisk1'), variables('LinuxOfferDisk1'))]" + }, + "properties": { + "hardwareProfile": { + "vmSize": "[parameters('dashboardVMSize')]" + }, + "osProfile": { + "computerName": "[variables('vmName')]", + "adminUsername": "[parameters('adminUsername')]", + "adminPassword": "[parameters('adminPassword')]" + }, + "storageProfile": { + "imageReference": { + "publisher": "mathworks-inc", + "offer": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsOfferDisk1'), variables('LinuxOfferDisk1'))]", + "sku": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsSKUDisk1'), variables('LinuxSKUDisk1'))]", + "version": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsDisk1Version'), variables('LinuxDisk1Version'))]" + }, + "osDisk": { + "createOption": "FromImage", + "managedDisk": { + "storageAccountType": "Standard_LRS" + } + } + }, + "networkProfile": { + "networkInterfaces": [ + { + "id": "[resourceId('Microsoft.Network/networkInterfaces',variables('licservernicName'))]" + } + ] + } + }, + "resources": [ + { + "type": "extensions", + "apiVersion": "2024-03-01", + "name": "config-app", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines/', variables('vmName'))]" + ], + "tags": { + "displayName": "config-app" + }, + "properties": { + "publisher": "Microsoft.Azure.Extensions", + "type": "CustomScript", + "typeHandlerVersion": "2.0", + "autoUpgradeMinorVersion": true, + "settings": { + "skipDos2Unix": false, + "timestamp": 123456789 + }, + "protectedSettings": { + "commandToExecute": "[concat( 'sudo ./initAdminVM.sh ''', variables('storageAccountName'), ''' ''', 'mydbConnection', ''' ''', if(equals(parameters('UsePublicIPAddresses'), 'Yes'), concat('https://', reference(variables('appGwPublicIPAddressName')).dnsSettings.fqdn), concat('https://', variables('appGWprivateIP'), ':444')), ''' ''', if(contains(reference(variables('subnetRef'), '2022-01-01'), 'addressPrefix'), reference(variables('subnetRef'), '2022-01-01').addressPrefix, first(reference(variables('subnetRef'), '2022-01-01').addressPrefixes)), ''' ''', 'Azure', ''' ''', variables('Platform'), ''' ''', reference(resourceId('Microsoft.Insights/components', variables('myAppInsightsInstanceName')), '2020-02-02').InstrumentationKey, ''' ''', resourceGroup().name, ''' ''', subscription().subscriptionId, ''' ''', parameters('adminUsername'), ''' ''', parameters('adminPassword'), ''' ''', variables('redisCacheName'), ''' ''', concat('https://', variables('appGWprivateIP'), ':444'), ''' ''', variables('offerType'), '''' )]", + "fileUris": [ + "[variables('adminVMScriptURL')]" + ] + } + } + } + ] + }, + { + "type": "Microsoft.Network/publicIPAddresses", + "apiVersion": "2024-03-01", + "name": "[variables('appGwPublicIPAddressName')]", + "location": "[parameters('location')]", + "tags": { + "Description": "Application Gateway public IP" + }, + "sku": { + "name": "Standard" + }, + "properties": { + "publicIPAllocationMethod": "Static", + "dnsSettings": { + "domainNameLabel": "[variables('mpsDNSName')]" + } + } + }, + { + "type": "Microsoft.Network/applicationGateways", + "apiVersion": "2024-03-01", + "name": "[variables('appGwName')]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]", + "[resourceId('Microsoft.Network/publicIPAddresses/', variables('appGwPublicIPAddressName'))]" + ], + "tags": { + "Description": "Application Gateway" + }, + "identity": "[if(equals(parameters('CertificateInputType'), 'KeyVault'), variables('ManagedIdentityResourceIDForKeyVault'), json('null'))]", + "properties": { + "sku": { + "name": "[variables('AppGatewaySize')]", + "tier": "Standard_v2", + "capacity": "[variables('AppGatewayCount')]" + }, + "sslCertificates": [ + { + "name": "appGatewayFrontEndSslCert", + "properties": { + "keyVaultSecretId": "[if(equals(parameters('CertificateInputType'), 'KeyVault'), parameters('KeyVaultCertificateSecretID'), json('null'))]", + "data": "[if(equals(parameters('CertificateInputType'), 'Base64-encoded PFX Certificate'), parameters('Base64EncodedPFXCertificateData'), json('null'))]", + "password": "[if(equals(parameters('CertificateInputType'), 'Base64-encoded PFX Certificate'), parameters('PasswordForBase64EncodedPFXCertificate'), json('null'))]" + } + } + ], + "trustedRootCertificates": [ + { + "properties": { + "data": "[variables('backendCertData')]" + }, + "name": "backendRootCert" + } + ], + "gatewayIPConfigurations": [ + { + "name": "appGwIpConfig", + "properties": { + "subnet": { + "id": "[variables('appGwSubnetID')]" + } + } + } + ], + "frontendIPConfigurations": [ + { + "name": "appGwFrontendPublicIP", + "properties": { + "PublicIPAddress": { + "id": "[variables('appGwPublicIPAddressID')]" + } + } + }, + { + "name": "appGwFrontendPrivateIP", + "properties": { + "privateIPAddress": "[variables('appGWprivateIP')]", + "privateIPAllocationMethod": "Static", + "subnet": { + "id": "[variables('appGwSubnetID')]" + } + } + } + ], + "frontendPorts": [ + { + "name": "mpsHttpPort", + "properties": { + "Port": "[variables('mpsFrontEndPort')]" + } + }, + { + "name": "mpsHttpPort2", + "properties": { + "Port": 444 + } + }, + { + "name": "dummyPort", + "properties": { + "Port": 449 + } + }, + { + "name": "port_445", + "properties": { + "port": 443 + } + } + ], + "backendAddressPools": [ + { + "name": "[variables('appGwBePoolName')]" + }, + { + "name": "dashboardbackend", + "properties": {} + } + ], + "backendHttpSettingsCollection": [ + { + "name": "appGwBackendMPSHttpSettings", + "properties": { + "Port": "[variables('mpsHttpPortVar')]", + "Protocol": "Http", + "requestTimeout": 300, + "CookieBasedAffinity": "Enabled", + "probe": { + "id": "[resourceId('Microsoft.Network/applicationGateways/probes',variables('appGwName'), 'mpsfileprobe')]" + } + } + }, + { + "name": "dashboardbackend", + "properties": { + "port": 9090, + "protocol": "Https", + "cookieBasedAffinity": "Disabled", + "affinityCookieName": "ApplicationGatewayAffinity", + "requestTimeout": 300, + "probe": { + "id": "[resourceId('Microsoft.Network/applicationGateways/probes',variables('appGwName'), 'dashboardHealth')]" + }, + "hostName": "www.myprodserver.com", + "trustedRootCertificates": [ + { + "id": "[resourceId('Microsoft.Network/applicationGateways/trustedRootCertificates',variables('appGwName'), 'backendRootCert')]" + } + ] + } + } + ], + "httpListeners": [ + { + "name": "MPSGwHttpListener", + "properties": { + "FrontendIPConfiguration": { + "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendIPConfigurations', variables('appGwName') ,'appGwFrontendPublicIP')]" + }, + "FrontendPort": { + "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendPorts', variables('appGwName'), 'mpsHttpPort')]" + }, + "Protocol": "Https", + "SslCertificate": { + "Id": "[resourceId('Microsoft.Network/applicationGateways/sslCertificates',variables('appGwName'), 'appGatewayFrontEndSslCert')]" + } + } + }, + { + "name": "MPSGwPrivateHttpListener", + "properties": { + "FrontendIPConfiguration": { + "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendIPConfigurations',variables('appGwName'), 'appGwFrontendPrivateIP')]" + }, + "FrontendPort": { + "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendPorts',variables('appGwName'),'mpsHttpPort2')]" + }, + "Protocol": "Https", + "SslCertificate": { + "Id": "[resourceId('Microsoft.Network/applicationGateways/sslCertificates',variables('appGwName'),'appGatewayFrontEndSslCert')]" + } + } + }, + { + "name": "MPSGwDummyHttpListener", + "properties": { + "FrontendIPConfiguration": { + "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendIPConfigurations',variables('appGwName'), 'appGwFrontendPrivateIP')]" + }, + "FrontendPort": { + "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendPorts',variables('appGwName'),'dummyPort')]" + }, + "Protocol": "Https", + "SslCertificate": { + "Id": "[resourceId('Microsoft.Network/applicationGateways/sslCertificates',variables('appGwName'),'appGatewayFrontEndSslCert')]" + } + } + }, + { + "name": "mainentrypoint", + "properties": { + "frontendIPConfiguration": { + "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendIPConfigurations',variables('appGwName'), 'appGwFrontendPublicIP')]" + }, + "frontendPort": { + "Id": "[resourceId('Microsoft.Network/applicationGateways/frontendPorts',variables('appGwName'),'port_445')]" + }, + "protocol": "Https", + "sslCertificate": { + "Id": "[resourceId('Microsoft.Network/applicationGateways/sslCertificates',variables('appGwName'),'appGatewayFrontEndSslCert')]" + }, + "requireServerNameIndication": false + } + } + ], + "urlPathMaps": [ + { + "name": "mainpath", + "properties": { + "defaultBackendAddressPool": { + "id": "[resourceId('Microsoft.Network/applicationGateways/backendAddressPools',variables('appGwName'), variables('appGwBePoolName'))]" + }, + "defaultBackendHttpSettings": { + "id": "[resourceId('Microsoft.Network/applicationGateways/backendHttpSettingsCollection',variables('appGwName'), 'appGwBackendMPSHttpSettings')]" + }, + "pathRules": [ + { + "name": "dashboard", + "properties": { + "paths": [ + "/dashboard/*", + "/dashboard" + ], + "backendAddressPool": { + "id": "[resourceId('Microsoft.Network/applicationGateways/backendAddressPools',variables('appGwName'), 'dashboardbackend')]" + }, + "backendHttpSettings": { + "id": "[resourceId('Microsoft.Network/applicationGateways/backendHttpSettingsCollection',variables('appGwName'), 'dashboardbackend')]" + } + } + } + ] + } + } + ], + "requestRoutingRules": [ + { + "name": "mainpathPrivate", + "properties": { + "ruleType": "PathBasedRouting", + "httpListener": { + "id": "[resourceId('Microsoft.Network/applicationGateways/httpListeners',variables('appGwName'), 'MPSGwPrivateHttpListener')]" + }, + "urlPathMap": { + "id": "[resourceId('Microsoft.Network/applicationGateways/urlPathMaps',variables('appGwName'), 'mainpath')]" + }, + "priority": 1 + } + }, + { + "name": "mainpath", + "properties": { + "ruleType": "PathBasedRouting", + "httpListener": { + "id": "[if(equals(parameters('UsePublicIPAddresses'), 'Yes'),resourceId('Microsoft.Network/applicationGateways/httpListeners',variables('appGwName'), 'mainentrypoint'), resourceId('Microsoft.Network/applicationGateways/httpListeners',variables('appGwName'), 'MPSGwDummyHttpListener') )]" + }, + "urlPathMap": { + "id": "[resourceId('Microsoft.Network/applicationGateways/urlPathMaps',variables('appGwName'), 'mainpath')]" + }, + "priority": 2 + } + } + ], + "probes": [ + { + "name": "mpsfileprobe", + "properties": { + "protocol": "Http", + "host": "127.0.0.1", + "path": "/~files/hello.html", + "interval": 30, + "timeout": 30, + "unhealthyThreshold": 3, + "match": { + "statusCodes": [ + "200-399" + ] + } + } + }, + { + "name": "dashboardHealth", + "properties": { + "protocol": "Https", + "path": "/dashboard/index.html", + "interval": 30, + "timeout": 30, + "unhealthyThreshold": 3, + "pickHostNameFromBackendHttpSettings": true, + "minServers": 0, + "match": { + "statusCodes": [ + "200-399" + ] + } + } + } + ] + } + }, + { + "type": "Microsoft.Compute/virtualMachineScaleSets", + "apiVersion": "2024-03-01", + "name": "[variables('namingInfix')]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]", + "[resourceId('Microsoft.Network/applicationGateways/', variables('appGwName'))]" + ], + "tags": { + "Description": "VM Scale set that controls how many instances are running" + }, + "sku": { + "name": "[parameters('Server VM Instance Size')]", + "tier": "Standard", + "capacity": "[parameters('instanceCount')]" + }, + "identity": { + "type": "SystemAssigned" + }, + "plan": { + "name": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsSKUDisk2'), variables('LinuxSKUDisk2'))]", + "publisher": "mathworks-inc", + "product": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsOfferDisk2'), variables('LinuxOfferDisk2'))]" + }, + "properties": { + "overprovision": "true", + "upgradePolicy": { + "mode": "Manual" + }, + "virtualMachineProfile": { + "storageProfile": { + "imageReference": { + "publisher": "mathworks-inc", + "offer": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsOfferDisk2'), variables('LinuxOfferDisk2'))]", + "sku": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsSKUDisk2'), variables('LinuxSKUDisk2'))]", + "version": "[if(equals(variables('Platform'), 'Windows'), variables('WindowsDisk2Version'), variables('LinuxDisk2Version'))]" + }, + "osDisk": { + "createOption": "fromImage", + "managedDisk": { + "storageAccountType": "Standard_LRS" + } + } + }, + "osProfile": { + "computerNamePrefix": "[variables('namingInfix')]", + "adminUsername": "[parameters('adminUsername')]", + "adminPassword": "[parameters('adminPassword')]" + }, + "networkProfile": { + "networkInterfaceConfigurations": [ + { + "name": "[variables('nicName')]", + "properties": { + "primary": true, + "ipConfigurations": [ + { + "name": "[variables('ipConfigName')]", + "properties": { + "subnet": { + "id": "[variables('subnetRef')]" + }, + "ApplicationGatewayBackendAddressPools": [ + { + "id": "[resourceId('Microsoft.Network/applicationGateways/backendAddressPools',variables('appGwName'), variables('appGwBePoolName'))]" + } + ] + } + } + ] + } + } + ] + }, + "extensionProfile": { + "extensions": [ + { + "name": "[concat(variables('vmssName'), 'SetEnvironmentVar')]", + "properties": { + "publisher": "[if(equals(variables('Platform'), 'Windows'), 'Microsoft.Compute', 'Microsoft.Azure.Extensions')]", + "forceUpdateTag": "1", + "type": "[if(equals(variables('Platform'), 'Windows'), 'CustomScriptExtension', 'CustomScript')]", + "typeHandlerVersion": "[if(equals(variables('Platform'), 'Windows'), '1.9', '2.0')]", + "autoUpgradeMinorVersion": true, + "settings": { + "fileUris": [ + "[if(equals(variables('Platform'), 'Windows'), variables('windowsScriptURL'), variables('linuxScriptURL'))]" + ] + }, + "protectedSettings": { + "commandToExecute": "[if(equals(variables('Platform'), 'Windows'), variables('commandToExecuteWindows'), variables('commandToExecuteLinux'))]" + } + } + } + ] + } + } + } + }, + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2023-05-01", + "name": "[variables('storageAccountName')]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', variables('virtualNetworkName'))]" + ], + "tags": { + "Description": "Storage account that stores application and config files" + }, + "sku": { + "name": "[variables('storageAccountType')]" + }, + "kind": "StorageV2", + "properties": { + "allowBlobPublicAccess": false, + "minimumTlsVersion": "TLS1_2", + "publicNetworkAccess": "[if(equals(parameters('usePublicIPAddresses'), 'Yes'), 'Enabled', 'Disabled')]", + "networkAcls": { + "virtualNetworkRules": "[if(equals(parameters('usePublicIPAddresses'), 'Yes'), createArray(createObject('id', variables('subnetRef'))), createArray())]", + "ipRules": "[if(equals(parameters('usePublicIPAddresses'), 'Yes'), createArray(createObject('action', 'Allow', 'value', if(endsWith(variables('allowedIpArray')[0], '/32'), substring(variables('allowedIpArray')[0], 0, sub(length(variables('allowedIpArray')[0]), 3)), variables('allowedIpArray')[0]))), createArray())]", + "defaultAction": "Deny" + } + } + }, + { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2024-03-01", + "name": "[variables('storagePrivateEndpointName')]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]", + "[resourceId('Microsoft.Network/virtualNetworks', variables('VirtualNetworkName'))]" + ], + "properties": { + "subnet": { + "id": "[variables('subnetRef')]" + }, + "privateLinkServiceConnections": [ + { + "name": "[variables('storagePrivateEndpointName')]", + "properties": { + "privateLinkServiceId": "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]", + "groupIds": [ + "file" + ] + } + } + ] + }, + "condition": "[equals(parameters('usePublicIPAddresses'), 'No')]" + }, + { + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2024-06-01", + "name": "[variables('fileStorageDnsZone')]", + "location": "global", + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', variables('VirtualNetworkName'))]" + ], + "properties": {}, + "condition": "[equals(parameters('usePublicIPAddresses'), 'No')]" + }, + { + "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", + "apiVersion": "2024-06-01", + "name": "[format('{0}/{1}', variables('fileStorageDnsZone'), format('{0}-link', variables('fileStorageDnsZone')))]", + "location": "global", + "dependsOn": [ + "[resourceId('Microsoft.Network/privateDnsZones', variables('fileStorageDnsZone'))]", + "[resourceId('Microsoft.Network/virtualNetworks', variables('VirtualNetworkName'))]" + ], + "properties": { + "registrationEnabled": false, + "virtualNetwork": { + "id": "[resourceId(variables('ResourceGroupNameOfVirtualNetwork'),'Microsoft.Network/virtualNetworks', variables('VirtualNetworkName'))]" + } + }, + "condition": "[equals(parameters('usePublicIPAddresses'), 'No')]" + }, + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2024-03-01", + "name": "[variables('storagePrivateEndpointDnsGroupName')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/privateDnsZones', variables('fileStorageDnsZone'))]", + "[resourceId('Microsoft.Network/privateEndpoints', variables('storagePrivateEndpointName'))]" + ], + "properties": { + "privateDnsZoneConfigs": [ + { + "name": "config1", + "properties": { + "privateDnsZoneId": "[resourceId('Microsoft.Network/privateDnsZones', variables('fileStorageDnsZone'))]" + } + } + ] + }, + "condition": "[equals(parameters('usePublicIPAddresses'), 'No')]" + }, + { + "type": "Microsoft.Cache/Redis", + "apiVersion": "2023-08-01", + "name": "[variables('redisCacheName')]", + "location": "[parameters('location')]", + "tags": { + "Description": "Azure Cache for Redis to store persistence data" + }, + "properties": { + "enableNonSslPort": "[variables('redisenableNonSslPort')]", + "sku": { + "capacity": "[variables('redisCacheCapacity')]", + "family": "[variables('redisCacheFamily')]", + "name": "[variables('redisCacheSKU')]" + } + }, + "condition": "[equals(parameters('CreateAzureRedisCache'), 'Yes')]" + }, + { + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2024-03-01", + "name": "[variables('privateEndpointName')]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Cache/Redis', variables('redisCacheName'))]", + "[resourceId('Microsoft.Network/virtualNetworks', variables('VirtualNetworkName'))]" + ], + "properties": { + "subnet": { + "id": "[variables('subnetRef')]" + }, + "privateLinkServiceConnections": [ + { + "name": "[variables('privateEndpointName')]", + "properties": { + "privateLinkServiceId": "[resourceId('Microsoft.Cache/Redis', variables('redisCacheName'))]", + "groupIds": [ + "redisCache" + ] + } + } + ] + }, + "condition": "[equals(parameters('CreateAzureRedisCache'), 'Yes')]" + }, + { + "type": "Microsoft.Network/privateDnsZones", + "apiVersion": "2024-06-01", + "name": "[variables('privateDnsZoneName')]", + "location": "global", + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', variables('VirtualNetworkName'))]" + ], + "properties": {}, + "condition": "[equals(parameters('CreateAzureRedisCache'), 'Yes')]" + }, + { + "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", + "apiVersion": "2024-06-01", + "name": "[format('{0}/{1}', variables('privateDnsZoneName'), format('{0}-link', variables('privateDnsZoneName')))]", + "location": "global", + "dependsOn": [ + "[resourceId('Microsoft.Network/privateDnsZones', variables('privateDnsZoneName'))]", + "[resourceId('Microsoft.Network/virtualNetworks', variables('VirtualNetworkName'))]" + ], + "properties": { + "registrationEnabled": false, + "virtualNetwork": { + "id": "[resourceId(variables('ResourceGroupNameOfVirtualNetwork'),'Microsoft.Network/virtualNetworks', variables('VirtualNetworkName'))]" + } + }, + "condition": "[equals(parameters('CreateAzureRedisCache'), 'Yes')]" + }, + { + "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", + "apiVersion": "2024-03-01", + "name": "[variables('privateEndpointDnsGroupName')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/privateDnsZones', variables('privateDnsZoneName'))]", + "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpointName'))]" + ], + "properties": { + "privateDnsZoneConfigs": [ + { + "name": "config1", + "properties": { + "privateDnsZoneId": "[resourceId('Microsoft.Network/privateDnsZones', variables('privateDnsZoneName'))]" + } + } + ] + }, + "condition": "[equals(parameters('CreateAzureRedisCache'), 'Yes')]" + }, + { + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2023-09-01", + "name": "[variables('workspaceName')]", + "location": "[parameters('location')]", + "properties": { + "sku": { + "name": "PerGB2018" + } + } + }, + { + "type": "Microsoft.Insights/Components", + "apiVersion": "2020-02-02", + "name": "[variables('myAppInsightsInstanceName')]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.OperationalInsights/workspaces', variables('workspaceName'))]" + ], + "tags": { + "Description": "Application Insights instance that stores solution logs" + }, + "properties": { + "Application_Type": "[variables('AppInsights-AppType')]", + "Flow_Type": "Redfield", + "Request_Source": "[variables('AppInsights-requestSource')]", + "WorkspaceResourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', variables('workspaceName'))]" + } + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "name": "[guid(resourceGroup().id, deployment().name,'12')]", + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" + ], + "properties": { + "roleDefinitionId": "[variables('keyoperator')]", + "principalId": "[reference(resourceId('Microsoft.Compute/virtualMachines', variables('vmName')), '2023-09-01', 'Full').identity.principalId]", + "principalType": "ServicePrincipal" + }, + "scope": "[concat('Microsoft.Storage/storageAccounts', '/', variables('storageAccountName'))]" + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "name": "[guid(resourceGroup().id, deployment().name,'16')]", + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]" + ], + "properties": { + "roleDefinitionId": "[variables('keyoperator')]", + "principalId": "[reference(resourceId('Microsoft.Compute/virtualMachineScaleSets', variables('namingInfix')), '2023-09-01', 'Full').identity.principalId]", + "principalType": "ServicePrincipal" + }, + "scope": "[concat('Microsoft.Storage/storageAccounts', '/', variables('storageAccountName'))]" + }, + { + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "name": "[guid(resourceGroup().id, deployment().name,'22')]", + "dependsOn": [ + "[resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName'))]", + "[resourceId('Microsoft.Cache/Redis', variables('redisCacheName'))]" + ], + "properties": { + "roleDefinitionId": "[variables('owner')]", + "principalId": "[reference(resourceId('Microsoft.Compute/virtualMachines', variables('vmName')), '2023-09-01', 'Full').identity.principalId]", + "principalType": "ServicePrincipal" + }, + "scope": "[concat('Microsoft.Cache/Redis', '/', variables('redisCacheName'))]", + "condition": "[equals(parameters('CreateAzureRedisCache'), 'Yes')]" + } + ], + "outputs": { + "adminDashboardURL": { + "type": "String", + "value": "[uri(if(equals(parameters('UsePublicIPAddresses'), 'Yes'), concat('https://', reference(variables('appGwPublicIPAddressName')).dnsSettings.fqdn, '/dashboard/admin'), concat('https://', variables('appGWprivateIP'), ':444/dashboard/admin')), '')]" + }, + "managerAndAppAuthorDashboardURL": { + "type": "String", + "value": "[uri(if(equals(parameters('UsePublicIPAddresses'), 'Yes'), concat('https://', reference(variables('appGwPublicIPAddressName')).dnsSettings.fqdn, '/dashboard'), concat('https://', variables('appGWprivateIP'), ':444/dashboard')), '')]" + }, + "networkLicenseManagerURL": { + "type": "String", + "value": "[if(equals(variables('should-deploy-flex'), 'Yes'), reference('flex-lm-server').outputs.NetworkLicenseManagerAddress.value, 'none')]" + }, + "MATLABExecutionEndpoint": { + "type": "String", + "value": "[if(equals(parameters('UsePublicIPAddresses'), 'Yes'), concat('https://', reference(variables('appGwPublicIPAddressName')).dnsSettings.fqdn), concat('https://', variables('appGWprivateIP'),':444'))]" + } + } +} \ No newline at end of file diff --git a/releases/release-notes.md b/releases/release-notes.md new file mode 100644 index 0000000..0677993 --- /dev/null +++ b/releases/release-notes.md @@ -0,0 +1,13 @@ +## Release Notes for MATLAB Production Server on Microsoft Azure + +### R2025a +- You can now deploy MATLAB Production Server R2025a using the Microsoft Azure reference architecture. +- The **Assign Public IP Address to VM Hosting MATLAB Production Server** parameter of the deployment template now controls access to the storage account. For details, see the **Assign Public IP Address to VM Hosting MATLAB Production Server** parameter in the [Configure Cloud Resources](/releases/R2025a/README.md#step-2-configure-cloud-resources) step of the deployment process. + - If you assign a public IP address to the VM hosting MATLAB Production Server, then public network access to the storage account is enabled only from selected virtual networks and IP addresses. Previously, public network access was enabled from all networks. + - If you assign a private IP address to the VM hosting MATLAB Production Server, then public network access to the storage account is disabled. You must use a bastion host or jump box VM to connect to the storage account. Previously, storage account access was enabled from all networks. +- If you deploy using an existing virtual network and assign a public IP address to the VM hosting MATLAB Production Server, you must manually add a service endpoint to the virtual network before deploying MATLAB Production Server in order to create and access the storage account. For details, see [How do I deploy to an existing virtual network?](/README.md#how-do-i-deploy-to-an-existing-virtual-network) + +### R2024b +- You can now deploy MATLAB Production Server R2024b using the Microsoft Azure reference architecture. +- You can assign a private IP address for the Network License Manager VM. Previously, you could only assign the Network License Manager VM a public IP address. +- You can allow a range of IP addresses to access the Network License Manager dashboard. \ No newline at end of file