{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "metadata": {
    "_generator": {
      "name": "bicep",
      "version": "0.37.4.10188",
      "templateHash": "12945636818973572491"
    }
  },
  "parameters": {
    "stackName": {
      "type": "string",
      "metadata": {
        "description": "Stack name"
      }
    },
    "certificateType": {
      "type": "string",
      "defaultValue": "letsencrypt",
      "allowedValues": [
        "selfsigned",
        "owncert",
        "letsencrypt"
      ],
      "metadata": {
        "description": "[selfsigned] Not recommended for production use. Just for testing purposes or development environments. You don't need a FQDN to use this option.\n[owncert] Valid for production environments. Use your own certificate. You need a FQDN to use this option.\n[letsencrypt] Valid for production environments. Can be used with or without a FQDN (if no FQDN is provided, a random sslip.io domain will be used).\n"
      }
    },
    "publicIpAddressObject": {
      "type": "object",
      "metadata": {
        "description": "Previously created Public IP address for the OpenVidu Deployment. Blank will generate a public IP"
      }
    },
    "domainName": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Domain name for the OpenVidu Deployment. Blank will generate default domain"
      }
    },
    "ownPublicCertificate": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "If certificate type is 'owncert', this parameter will be used to specify the public certificate in base64 format"
      }
    },
    "ownPrivateCertificate": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "If certificate type is 'owncert', this parameter will be used to specify the private certificate in base64 format"
      }
    },
    "initialMeetAdminPassword": {
      "type": "securestring",
      "defaultValue": "",
      "metadata": {
        "description": "Initial password for the 'admin' user in OpenVidu Meet. If not provided, a random password will be generated."
      }
    },
    "initialMeetApiKey": {
      "type": "securestring",
      "defaultValue": "",
      "metadata": {
        "description": "Initial API key for OpenVidu Meet. If not provided, no API key will be set and the user can set it later from Meet Console."
      }
    },
    "turnDomainName": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls"
      }
    },
    "turnOwnPublicCertificate": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
      }
    },
    "turnOwnPrivateCertificate": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "(Optional) This setting is applicable if the certificate type is set to 'owncert' and the TurnDomainName is specified. Provide in base64 format."
      }
    },
    "openviduLicense": {
      "type": "securestring",
      "metadata": {
        "description": "Visit https://openvidu.io/account"
      }
    },
    "rtcEngine": {
      "type": "string",
      "defaultValue": "pion",
      "allowedValues": [
        "pion",
        "mediasoup"
      ],
      "metadata": {
        "description": "RTCEngine media engine to use"
      }
    },
    "instanceType": {
      "type": "string",
      "defaultValue": "Standard_B4s",
      "metadata": {
        "description": "Specifies the azure vm size for your OpenVidu instance. You can use any valid Azure VM size (e.g., Standard_B4s, Standard_D4s_v5, Standard_E4ps_v5). See https://learn.microsoft.com/en-us/azure/virtual-machines/sizes for available sizes."
      }
    },
    "adminUsername": {
      "type": "string",
      "metadata": {
        "description": "Username for the Virtual Machine."
      }
    },
    "adminSshKey": {
      "type": "secureObject",
      "metadata": {
        "description": "SSH Key or password for the Virtual Machine."
      }
    },
    "additionalInstallFlags": {
      "type": "string",
      "defaultValue": ""
    },
    "storageAccountName": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Name of an existing storage account. It is essential that this parameter is filled just when you want to save recordings and still using the same container after an update. If not specified, a new storage account will be generated."
      }
    },
    "containerName": {
      "type": "string",
      "defaultValue": "",
      "metadata": {
        "description": "Name of the bucket where OpenVidu will store the recordings if a new Storage account is being creating. If not specified, a default bucket will be created. If you want to use an existing storage account, fill this parameter with the name of the container where the recordings are stored."
      }
    }
  },
  "variables": {
    "isEmptyIp": "[equals(parameters('publicIpAddressObject').newOrExistingOrNone, 'none')]",
    "isEmptyDomain": "[equals(parameters('domainName'), '')]",
    "instanceTypeLower": "[toLower(parameters('instanceType'))]",
    "isArm64Instance": "[or(or(or(or(or(or(or(contains(variables('instanceTypeLower'), 'ps_v'), contains(variables('instanceTypeLower'), 'pls_v')), contains(variables('instanceTypeLower'), 'pds_v')), contains(variables('instanceTypeLower'), 'plds_v')), contains(variables('instanceTypeLower'), 'psv')), contains(variables('instanceTypeLower'), 'plsv')), contains(variables('instanceTypeLower'), 'pdsv')), contains(variables('instanceTypeLower'), 'pldsv'))]",
    "ubuntuSku": "[if(variables('isArm64Instance'), 'server-arm64', 'server')]",
    "networkSettings": {
      "privateIPaddressNetInterface": "10.0.0.5",
      "vNetAddressPrefix": "10.0.0.0/16",
      "subnetAddressPrefix": "10.0.0.0/24",
      "netInterfaceName": "[format('{0}-netInteface', parameters('stackName'))]",
      "vNetName": "[format('{0}-vnet', parameters('stackName'))]",
      "subnetName": "default"
    },
    "openviduVMSettings": {
      "vmName": "[format('{0}-VM-Pro', parameters('stackName'))]",
      "osDiskType": "StandardSSD_LRS",
      "ubuntuOSVersion": {
        "publisher": "Canonical",
        "offer": "ubuntu-24_04-lts",
        "sku": "[variables('ubuntuSku')]",
        "version": "latest"
      },
      "linuxConfiguration": {
        "disablePasswordAuthentication": true,
        "ssh": {
          "publicKeys": [
            {
              "path": "[format('/home/{0}/.ssh/authorized_keys', parameters('adminUsername'))]",
              "keyData": "[parameters('adminSshKey').sshPublicKey]"
            }
          ]
        }
      }
    },
    "keyVaultName": "[format('{0}-keyvault', parameters('stackName'))]",
    "location": "[resourceGroup().location]",
    "tenantId": "[subscription().tenantId]",
    "deploymentUser": "[deployer().objectId]",
    "stringInterpolationParams": {
      "publicIPId": "[variables('publicIPId')]",
      "domainName": "[parameters('domainName')]",
      "turnDomainName": "[parameters('turnDomainName')]",
      "certificateType": "[parameters('certificateType')]",
      "ownPublicCertificate": "[parameters('ownPublicCertificate')]",
      "ownPrivateCertificate": "[parameters('ownPrivateCertificate')]",
      "turnOwnPublicCertificate": "[parameters('turnOwnPublicCertificate')]",
      "turnOwnPrivateCertificate": "[parameters('turnOwnPrivateCertificate')]",
      "initialMeetAdminPassword": "[parameters('initialMeetAdminPassword')]",
      "initialMeetApiKey": "[parameters('initialMeetApiKey')]",
      "keyVaultName": "[variables('keyVaultName')]",
      "openviduLicense": "[parameters('openviduLicense')]",
      "rtcEngine": "[parameters('rtcEngine')]",
      "additionalInstallFlags": "[parameters('additionalInstallFlags')]"
    },
    "installScriptTemplate": "#!/bin/bash -x\nOPENVIDU_VERSION=main\nDOMAIN=\n\necho \"DPkg::Lock::Timeout \\\"-1\\\";\" > /etc/apt/apt.conf.d/99timeout\n\napt-get update && apt-get install -y \\\n  curl \\\n  unzip \\\n  jq \\\n  wget\n\n# Configure Domain\nif [[ \"${domainName}\" == '' ]]; then\n  # Get public IP using the get_public_ip.sh script\n  PUBLIC_IP=$(/usr/local/bin/get_public_ip.sh 2>/dev/null)\n  if [[ $? -ne 0 || -z \"${PUBLIC_IP}\" ]]; then\n    echo \"Could not determine public IP.\"\n    exit 1\n  fi\n\n  RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8)\n  DOMAIN=\"openvidu-$RANDOM_DOMAIN_STRING-$(echo \"$PUBLIC_IP\" | tr '.' '-').sslip.io\"\n  TURN_DOMAIN_NAME_SSLIP_IO=\"turn-$RANDOM_DOMAIN_STRING-$(echo \"$PUBLIC_IP\" | tr '.' '-').sslip.io\"\nelse\n  DOMAIN=${domainName}\nfi\n\nDOMAIN=\"$(/usr/local/bin/store_secret.sh save DOMAIN-NAME \"$DOMAIN\")\"\n\n# Meet initial admin user and password\nMEET_INITIAL_ADMIN_USER=\"$(/usr/local/bin/store_secret.sh save MEET-INITIAL-ADMIN-USER \"admin\")\"\nif [[ \"${initialMeetAdminPassword}\" != '' ]]; then\n  MEET_INITIAL_ADMIN_PASSWORD=\"$(/usr/local/bin/store_secret.sh save MEET-INITIAL-ADMIN-PASSWORD \"${initialMeetAdminPassword}\")\"\nelse\n  MEET_INITIAL_ADMIN_PASSWORD=\"$(/usr/local/bin/store_secret.sh generate MEET-INITIAL-ADMIN-PASSWORD)\"\nfi\nif [[ \"${initialMeetApiKey}\" != '' ]]; then\n  MEET_INITIAL_API_KEY=\"$(/usr/local/bin/store_secret.sh save MEET-INITIAL-API-KEY \"${initialMeetApiKey}\")\"\nelse\n  MEET_INITIAL_API_KEY=\"$(/usr/local/bin/store_secret.sh save MEET-INITIAL-API-KEY \"\")\"\nfi\n\nOPENVIDU_PRO_LICENSE=\"$(/usr/local/bin/store_secret.sh save OPENVIDU-PRO-LICENSE \"${openviduLicense}\")\"\nOPENVIDU_RTC_ENGINE=\"$(/usr/local/bin/store_secret.sh save OPENVIDU-RTC-ENGINE \"${rtcEngine}\")\"\nREDIS_PASSWORD=\"$(/usr/local/bin/store_secret.sh generate REDIS-PASSWORD)\"\nMONGO_ADMIN_USERNAME=\"$(/usr/local/bin/store_secret.sh save MONGO-ADMIN-USERNAME \"mongoadmin\")\"\nMONGO_ADMIN_PASSWORD=\"$(/usr/local/bin/store_secret.sh generate MONGO-ADMIN-PASSWORD)\"\nMONGO_REPLICA_SET_KEY=\"$(/usr/local/bin/store_secret.sh generate MONGO-REPLICA-SET-KEY)\"\nMINIO_ACCESS_KEY=\"$(/usr/local/bin/store_secret.sh save MINIO-ACCESS-KEY \"minioadmin\")\"\nMINIO_SECRET_KEY=\"$(/usr/local/bin/store_secret.sh generate MINIO-SECRET-KEY)\"\nDASHBOARD_ADMIN_USERNAME=\"$(/usr/local/bin/store_secret.sh save DASHBOARD-ADMIN-USERNAME \"dashboardadmin\")\"\nDASHBOARD_ADMIN_PASSWORD=\"$(/usr/local/bin/store_secret.sh generate DASHBOARD-ADMIN-PASSWORD)\"\nGRAFANA_ADMIN_USERNAME=\"$(/usr/local/bin/store_secret.sh save GRAFANA-ADMIN-USERNAME \"grafanaadmin\")\"\nGRAFANA_ADMIN_PASSWORD=\"$(/usr/local/bin/store_secret.sh generate GRAFANA-ADMIN-PASSWORD)\"\nMEET_INITIAL_ADMIN_USER=\"$(/usr/local/bin/store_secret.sh save MEET-INITIAL-ADMIN-USER \"admin\")\"\nLIVEKIT_API_KEY=\"$(/usr/local/bin/store_secret.sh generate LIVEKIT-API-KEY \"API\" 12)\"\nLIVEKIT_API_SECRET=\"$(/usr/local/bin/store_secret.sh generate LIVEKIT-API-SECRET)\"\nENABLED_MODULES=\"$(/usr/local/bin/store_secret.sh save ENABLED-MODULES \"observability,openviduMeet,v2compatibility\")\"\n\n# Base command\nINSTALL_COMMAND=\"sh <(curl -fsSL http://get.openvidu.io/community/singlenode/$OPENVIDU_VERSION/install.sh)\"\n\n# Common arguments\nCOMMON_ARGS=(\n  \"--no-tty\"\n  \"--install\"\n  \"--environment=azure\"\n  \"--deployment-type=single_node_pro\"\n  \"--openvidu-pro-license=$OPENVIDU_PRO_LICENSE\"\n  \"--domain-name=$DOMAIN\"\n  \"--enabled-modules='$ENABLED_MODULES'\"\n  \"--rtc-engine=$OPENVIDU_RTC_ENGINE\"\n  \"--redis-password=$REDIS_PASSWORD\"\n  \"--mongo-admin-user=$MONGO_ADMIN_USERNAME\"\n  \"--mongo-admin-password=$MONGO_ADMIN_PASSWORD\"\n  \"--mongo-replica-set-key=$MONGO_REPLICA_SET_KEY\"\n  \"--minio-access-key=$MINIO_ACCESS_KEY\"\n  \"--minio-secret-key=$MINIO_SECRET_KEY\"\n  \"--dashboard-admin-user=$DASHBOARD_ADMIN_USERNAME\"\n  \"--dashboard-admin-password=$DASHBOARD_ADMIN_PASSWORD\"\n  \"--grafana-admin-user=$GRAFANA_ADMIN_USERNAME\"\n  \"--grafana-admin-password=$GRAFANA_ADMIN_PASSWORD\"\n  \"--meet-initial-admin-password=$MEET_INITIAL_ADMIN_PASSWORD\"\n  \"--meet-initial-api-key=$MEET_INITIAL_API_KEY\"\n  \"--livekit-api-key=$LIVEKIT_API_KEY\"\n  \"--livekit-api-secret=$LIVEKIT_API_SECRET\"\n)\n\n# Include additional installer flags provided by the user\nif [[ \"${additionalInstallFlags}\" != \"\" ]]; then\n  IFS=',' read -ra EXTRA_FLAGS <<< \"${additionalInstallFlags}\"\n  for extra_flag in \"${EXTRA_FLAGS[@]}\"; do\n    # Trim whitespace around each flag\n    extra_flag=\"$(echo -e \"${extra_flag}\" | sed -e 's/^[ \\t]*//' -e 's/[ \\t]*$//')\"\n    if [[ \"$extra_flag\" != \"\" ]]; then\n      COMMON_ARGS+=(\"$extra_flag\")\n    fi\n  done\nfi\n\n# Turn with TLS\nif [[ \"${turnDomainName}\" != '' ]]; then\n  LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT-TURN-DOMAIN-NAME \"${turnDomainName}\")\n  COMMON_ARGS+=(\n    \"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME\"\n  )\nelif [[ \"${TURN_DOMAIN_NAME_SSLIP_IO}\" != '' ]]; then\n  LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT-TURN-DOMAIN-NAME \"${TURN_DOMAIN_NAME_SSLIP_IO}\")\n  COMMON_ARGS+=(\n    \"--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME\"\n  )\nfi\n\n# Certificate arguments\nif [[ \"${certificateType}\" == \"selfsigned\" ]]; then\n  CERT_ARGS=(\n    \"--certificate-type=selfsigned\"\n  )\nelif [[ \"${certificateType}\" == \"letsencrypt\" ]]; then\n  CERT_ARGS=(\n    \"--certificate-type=letsencrypt\"\n  )\nelse\n  # Use base64 encoded certificates directly\n  OWN_CERT_CRT=${ownPublicCertificate}\n  OWN_CERT_KEY=${ownPrivateCertificate}\n\n  CERT_ARGS=(\n    \"--certificate-type=owncert\"\n    \"--owncert-public-key=$OWN_CERT_CRT\"\n    \"--owncert-private-key=$OWN_CERT_KEY\"\n  )\n\n  # Turn with TLS and own certificate\n  if [[ \"${turnDomainName}\" != '' ]]; then\n    # Use base64 encoded certificates directly\n    OWN_CERT_CRT_TURN=${turnOwnPublicCertificate}\n    OWN_CERT_KEY_TURN=${turnOwnPrivateCertificate}\n\n    CERT_ARGS+=(\n      \"--turn-owncert-private-key=$OWN_CERT_KEY_TURN\"\n      \"--turn-owncert-public-key=$OWN_CERT_CRT_TURN\"\n    )\n  fi\nfi\n\n# Construct the final command with all arguments\nFINAL_COMMAND=\"$INSTALL_COMMAND $(printf \"%s \" \"${COMMON_ARGS[@]}\") $(printf \"%s \" \"${CERT_ARGS[@]}\")\"\n\n# Install OpenVidu\nexec bash -c \"$FINAL_COMMAND\"\n",
    "after_installScriptTemplate": "#!/bin/bash\nset -e\n\naz login --identity --allow-no-subscriptions > /dev/null\n\n# Generate URLs\nDOMAIN=$(az keyvault secret show --vault-name ${keyVaultName} --name DOMAIN-NAME --query value -o tsv)\nOPENVIDU_URL=\"https://${DOMAIN}/\"\nLIVEKIT_URL=\"wss://${DOMAIN}/\"\nDASHBOARD_URL=\"https://${DOMAIN}/dashboard/\"\nGRAFANA_URL=\"https://${DOMAIN}/grafana/\"\nMINIO_URL=\"https://${DOMAIN}/minio-console/\"\n\n# Update shared secret\naz keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN\naz keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-URL --value $OPENVIDU_URL\naz keyvault secret set --vault-name ${keyVaultName} --name LIVEKIT-URL --value $LIVEKIT_URL\naz keyvault secret set --vault-name ${keyVaultName} --name DASHBOARD-URL --value $DASHBOARD_URL\naz keyvault secret set --vault-name ${keyVaultName} --name GRAFANA-URL --value $GRAFANA_URL\naz keyvault secret set --vault-name ${keyVaultName} --name MINIO-URL --value $MINIO_URL\n\naz keyvault secret show --vault-name ${keyVaultName} --name MINIO-URL\n\nif [[ $? -ne 0 ]]; then\n    echo \"Error updating keyvault\"\nfi\n",
    "update_config_from_secretScriptTemplate": "#!/bin/bash -x\nset -e\n\naz login --identity --allow-no-subscriptions > /dev/null\n\n# Installation directory\nINSTALL_DIR=\"/opt/openvidu\"\nCONFIG_DIR=\"${INSTALL_DIR}/config\"\n\n# Replace DOMAIN_NAME\nexport DOMAIN=$(az keyvault secret show --vault-name ${keyVaultName} --name DOMAIN-NAME --query value -o tsv)\nif [[ -n \"$DOMAIN\" ]]; then\n    sed -i \"s/DOMAIN_NAME=.*/DOMAIN_NAME=$DOMAIN/\" \"${CONFIG_DIR}/openvidu.env\"\nelse\n    exit 1\nfi\n\n# Replace LIVEKIT_TURN_DOMAIN_NAME\nexport LIVEKIT_TURN_DOMAIN_NAME=$(az keyvault secret show --vault-name ${keyVaultName} --name LIVEKIT-TURN-DOMAIN-NAME --query value -o tsv)\nif [[ -n \"$LIVEKIT_TURN_DOMAIN_NAME\" ]]; then\n    sed -i \"s/LIVEKIT_TURN_DOMAIN_NAME=.*/LIVEKIT_TURN_DOMAIN_NAME=$LIVEKIT_TURN_DOMAIN_NAME/\" \"${CONFIG_DIR}/openvidu.env\"\nfi\n\n# Get the rest of the values\nexport REDIS_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name REDIS-PASSWORD --query value -o tsv)\nexport OPENVIDU_RTC_ENGINE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --query value -o tsv)\nexport OPENVIDU_PRO_LICENSE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-PRO-LICENSE --query value -o tsv)\nexport MONGO_ADMIN_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --query value -o tsv)\nexport MONGO_ADMIN_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name MONGO-ADMIN-PASSWORD --query value -o tsv)\nexport MONGO_REPLICA_SET_KEY=$(az keyvault secret show --vault-name ${keyVaultName} --name MONGO-REPLICA-SET-KEY --query value -o tsv)\nexport DASHBOARD_ADMIN_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name DASHBOARD-ADMIN-USERNAME --query value -o tsv)\nexport DASHBOARD_ADMIN_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name DASHBOARD-ADMIN-PASSWORD --query value -o tsv)\nexport MINIO_ACCESS_KEY=$(az keyvault secret show --vault-name ${keyVaultName} --name MINIO-ACCESS-KEY --query value -o tsv)\nexport MINIO_SECRET_KEY=$(az keyvault secret show --vault-name ${keyVaultName} --name MINIO-SECRET-KEY --query value -o tsv)\nexport GRAFANA_ADMIN_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name GRAFANA-ADMIN-USERNAME --query value -o tsv)\nexport GRAFANA_ADMIN_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name GRAFANA-ADMIN-PASSWORD --query value -o tsv)\nexport LIVEKIT_API_KEY=$(az keyvault secret show --vault-name ${keyVaultName} --name LIVEKIT-API-KEY --query value -o tsv)\nexport LIVEKIT_API_SECRET=$(az keyvault secret show --vault-name ${keyVaultName} --name LIVEKIT-API-SECRET --query value -o tsv)\nexport MEET_INITIAL_ADMIN_USER=$(az keyvault secret show --vault-name ${keyVaultName} --name MEET-INITIAL-ADMIN-USER --query value -o tsv)\nexport MEET_INITIAL_ADMIN_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name MEET-INITIAL-ADMIN-PASSWORD --query value -o tsv)\nif [[ \"${initialMeetApiKey}\" != '' ]]; then\n  export MEET_INITIAL_API_KEY=$(az keyvault secret show --vault-name ${keyVaultName} --name MEET-INITIAL-API-KEY --query value -o tsv)\nfi\nexport ENABLED_MODULES=$(az keyvault secret show --vault-name ${keyVaultName} --name ENABLED-MODULES --query value -o tsv)\n\n\n# Replace rest of the values\nsed -i \"s/REDIS_PASSWORD=.*/REDIS_PASSWORD=$REDIS_PASSWORD/\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s/OPENVIDU_RTC_ENGINE=.*/OPENVIDU_RTC_ENGINE=$OPENVIDU_RTC_ENGINE/\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s/OPENVIDU_PRO_LICENSE=.*/OPENVIDU_PRO_LICENSE=$OPENVIDU_PRO_LICENSE/\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s/MONGO_ADMIN_USERNAME=.*/MONGO_ADMIN_USERNAME=$MONGO_ADMIN_USERNAME/\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s/MONGO_ADMIN_PASSWORD=.*/MONGO_ADMIN_PASSWORD=$MONGO_ADMIN_PASSWORD/\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s/MONGO_REPLICA_SET_KEY=.*/MONGO_REPLICA_SET_KEY=$MONGO_REPLICA_SET_KEY/\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s/DASHBOARD_ADMIN_USERNAME=.*/DASHBOARD_ADMIN_USERNAME=$DASHBOARD_ADMIN_USERNAME/\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s/DASHBOARD_ADMIN_PASSWORD=.*/DASHBOARD_ADMIN_PASSWORD=$DASHBOARD_ADMIN_PASSWORD/\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s/MINIO_ACCESS_KEY=.*/MINIO_ACCESS_KEY=$MINIO_ACCESS_KEY/\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s/MINIO_SECRET_KEY=.*/MINIO_SECRET_KEY=$MINIO_SECRET_KEY/\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s/GRAFANA_ADMIN_USERNAME=.*/GRAFANA_ADMIN_USERNAME=$GRAFANA_ADMIN_USERNAME/\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s/GRAFANA_ADMIN_PASSWORD=.*/GRAFANA_ADMIN_PASSWORD=$GRAFANA_ADMIN_PASSWORD/\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s/LIVEKIT_API_KEY=.*/LIVEKIT_API_KEY=$LIVEKIT_API_KEY/\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s/LIVEKIT_API_SECRET=.*/LIVEKIT_API_SECRET=$LIVEKIT_API_SECRET/\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s/MEET_INITIAL_ADMIN_USER=.*/MEET_INITIAL_ADMIN_USER=$MEET_INITIAL_ADMIN_USER/\" \"${CONFIG_DIR}/meet.env\"\nsed -i \"s/MEET_INITIAL_ADMIN_PASSWORD=.*/MEET_INITIAL_ADMIN_PASSWORD=$MEET_INITIAL_ADMIN_PASSWORD/\" \"${CONFIG_DIR}/meet.env\"\nif [[ \"${initialMeetApiKey}\" != '' ]]; then\n  sed -i \"s/MEET_INITIAL_API_KEY=.*/MEET_INITIAL_API_KEY=$MEET_INITIAL_API_KEY/\" \"${CONFIG_DIR}/meet.env\"\nfi\nsed -i \"s/ENABLED_MODULES=.*/ENABLED_MODULES=$ENABLED_MODULES/\" \"${CONFIG_DIR}/openvidu.env\"\n\n\n# Update URLs in secret\nOPENVIDU_URL=\"https://${DOMAIN}/\"\nLIVEKIT_URL=\"wss://${DOMAIN}/\"\nDASHBOARD_URL=\"https://${DOMAIN}/dashboard/\"\nGRAFANA_URL=\"https://${DOMAIN}/grafana/\"\nMINIO_URL=\"https://${DOMAIN}/minio-console/\"\n\n# Update shared secret\naz keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN\naz keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-URL --value $OPENVIDU_URL\naz keyvault secret set --vault-name ${keyVaultName} --name LIVEKIT-URL --value $LIVEKIT_URL\naz keyvault secret set --vault-name ${keyVaultName} --name DASHBOARD-URL --value $DASHBOARD_URL\naz keyvault secret set --vault-name ${keyVaultName} --name GRAFANA-URL --value $GRAFANA_URL\naz keyvault secret set --vault-name ${keyVaultName} --name MINIO-URL --value $MINIO_URL\n",
    "update_secret_from_configScriptTemplate": "#!/bin/bash\nset -e\n\naz login --identity --allow-no-subscriptions > /dev/null\n\n# Installation directory\nINSTALL_DIR=\"/opt/openvidu\"\nCONFIG_DIR=\"${INSTALL_DIR}/config\"\n\n# Get current values of the config\nREDIS_PASSWORD=\"$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD \"${CONFIG_DIR}/openvidu.env\")\"\nDOMAIN_NAME=\"$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME \"${CONFIG_DIR}/openvidu.env\")\"\nLIVEKIT_TURN_DOMAIN_NAME=\"$(/usr/local/bin/get_value_from_config.sh LIVEKIT_TURN_DOMAIN_NAME \"${CONFIG_DIR}/openvidu.env\")\"\nOPENVIDU_RTC_ENGINE=\"$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE \"${CONFIG_DIR}/openvidu.env\")\"\nOPENVIDU_PRO_LICENSE=\"$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE \"${CONFIG_DIR}/openvidu.env\")\"\nMONGO_ADMIN_USERNAME=\"$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME \"${CONFIG_DIR}/openvidu.env\")\"\nMONGO_ADMIN_PASSWORD=\"$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_PASSWORD \"${CONFIG_DIR}/openvidu.env\")\"\nMONGO_REPLICA_SET_KEY=\"$(/usr/local/bin/get_value_from_config.sh MONGO_REPLICA_SET_KEY \"${CONFIG_DIR}/openvidu.env\")\"\nMINIO_ACCESS_KEY=\"$(/usr/local/bin/get_value_from_config.sh MINIO_ACCESS_KEY \"${CONFIG_DIR}/openvidu.env\")\"\nMINIO_SECRET_KEY=\"$(/usr/local/bin/get_value_from_config.sh MINIO_SECRET_KEY \"${CONFIG_DIR}/openvidu.env\")\"\nDASHBOARD_ADMIN_USERNAME=\"$(/usr/local/bin/get_value_from_config.sh DASHBOARD_ADMIN_USERNAME \"${CONFIG_DIR}/openvidu.env\")\"\nDASHBOARD_ADMIN_PASSWORD=\"$(/usr/local/bin/get_value_from_config.sh DASHBOARD_ADMIN_PASSWORD \"${CONFIG_DIR}/openvidu.env\")\"\nGRAFANA_ADMIN_USERNAME=\"$(/usr/local/bin/get_value_from_config.sh GRAFANA_ADMIN_USERNAME \"${CONFIG_DIR}/openvidu.env\")\"\nGRAFANA_ADMIN_PASSWORD=\"$(/usr/local/bin/get_value_from_config.sh GRAFANA_ADMIN_PASSWORD \"${CONFIG_DIR}/openvidu.env\")\"\nLIVEKIT_API_KEY=\"$(/usr/local/bin/get_value_from_config.sh LIVEKIT_API_KEY \"${CONFIG_DIR}/openvidu.env\")\"\nLIVEKIT_API_SECRET=\"$(/usr/local/bin/get_value_from_config.sh LIVEKIT_API_SECRET \"${CONFIG_DIR}/openvidu.env\")\"\nMEET_INITIAL_ADMIN_USER=\"$(/usr/local/bin/get_value_from_config.sh MEET_INITIAL_ADMIN_USER \"${CONFIG_DIR}/meet.env\")\"\nMEET_INITIAL_ADMIN_PASSWORD=\"$(/usr/local/bin/get_value_from_config.sh MEET_INITIAL_ADMIN_PASSWORD \"${CONFIG_DIR}/meet.env\")\"\nif [[ \"${initialMeetApiKey}\" != '' ]]; then\n  MEET_INITIAL_API_KEY=\"$(/usr/local/bin/get_value_from_config.sh MEET_INITIAL_API_KEY \"${CONFIG_DIR}/meet.env\")\"\nfi\nENABLED_MODULES=\"$(/usr/local/bin/get_value_from_config.sh ENABLED_MODULES \"${CONFIG_DIR}/openvidu.env\")\"\n\n\n# Update shared secret\naz keyvault secret set --vault-name ${keyVaultName} --name REDIS-PASSWORD --value $REDIS_PASSWORD\naz keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN_NAME\naz keyvault secret set --vault-name ${keyVaultName} --name LIVEKIT-TURN-DOMAIN-NAME --value $LIVEKIT_TURN_DOMAIN_NAME\naz keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --value $OPENVIDU_RTC_ENGINE\naz keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-PRO-LICENSE --value $OPENVIDU_PRO_LICENSE\naz keyvault secret set --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --value $MONGO_ADMIN_USERNAME\naz keyvault secret set --vault-name ${keyVaultName} --name MONGO-ADMIN-PASSWORD --value $MONGO_ADMIN_PASSWORD\naz keyvault secret set --vault-name ${keyVaultName} --name MONGO-REPLICA-SET-KEY --value $MONGO_REPLICA_SET_KEY\naz keyvault secret set --vault-name ${keyVaultName} --name MINIO-ACCESS-KEY --value $MINIO_ACCESS_KEY\naz keyvault secret set --vault-name ${keyVaultName} --name MINIO-SECRET-KEY --value $MINIO_SECRET_KEY\naz keyvault secret set --vault-name ${keyVaultName} --name DASHBOARD-ADMIN-USERNAME --value $DASHBOARD_ADMIN_USERNAME\naz keyvault secret set --vault-name ${keyVaultName} --name DASHBOARD-ADMIN-PASSWORD --value $DASHBOARD_ADMIN_PASSWORD\naz keyvault secret set --vault-name ${keyVaultName} --name GRAFANA-ADMIN-USERNAME --value $GRAFANA_ADMIN_USERNAME\naz keyvault secret set --vault-name ${keyVaultName} --name GRAFANA-ADMIN-PASSWORD --value $GRAFANA_ADMIN_PASSWORD\naz keyvault secret set --vault-name ${keyVaultName} --name LIVEKIT-API-KEY --value $LIVEKIT_API_KEY\naz keyvault secret set --vault-name ${keyVaultName} --name LIVEKIT-API-SECRET --value $LIVEKIT_API_SECRET\naz keyvault secret set --vault-name ${keyVaultName} --name MEET-INITIAL-ADMIN-USER --value $MEET_INITIAL_ADMIN_USER\naz keyvault secret set --vault-name ${keyVaultName} --name MEET-INITIAL-ADMIN-PASSWORD --value $MEET_INITIAL_ADMIN_PASSWORD\nif [[ \"${initialMeetApiKey}\" != '' ]]; then\n  az keyvault secret set --vault-name ${keyVaultName} --name MEET-INITIAL-API-KEY --value $MEET_INITIAL_API_KEY\nfi\naz keyvault secret set --vault-name ${keyVaultName} --name ENABLED-MODULES --value $ENABLED_MODULES\n",
    "get_value_from_configScript": "#!/bin/bash -x\nset -e\n\n# Function to get the value of a given key from the environment file\nget_value() {\n    local key=\"$1\"\n    local file_path=\"$2\"\n\n    # Use grep to find the line with the key, ignoring lines starting with #\n    # Use awk to split on '=' and print the second field, which is the value\n    local value=$(grep -E \"^\\s*$key\\s*=\" \"$file_path\" | awk -F= '{print $2}' | sed 's/#.*//; s/^\\s*//; s/\\s*$//')\n\n    # If the value is empty, return \"none\"\n    if [ -z \"$value\" ]; then\n        echo \"none\"\n    else\n        echo \"$value\"\n    fi\n}\n\n# Check if the correct number of arguments are supplied\nif [ \"$#\" -ne 2 ]; then\n    echo \"Usage: $0 <key> <file_path>\"\n    exit 1\nfi\n\n# Get the key and file path from the arguments\nkey=\"$1\"\nfile_path=\"$2\"\n\n# Get and print the value\nget_value \"$key\" \"$file_path\"\n",
    "store_secretScriptTemplate": "#!/bin/bash\nset -e\n\naz login --identity --allow-no-subscriptions > /dev/null\n\n# Modes: save, generate\n# save mode: save the secret in the secret manager\n# generate mode: generate a random password and save it in the secret manager\nMODE=\"$1\"\n\nif [[ \"$MODE\" == \"generate\" ]]; then\n    SECRET_KEY_NAME=\"$2\"\n    PREFIX=\"${3:-}\"\n    LENGTH=\"${4:-44}\"\n    RANDOM_PASSWORD=\"$(openssl rand -base64 64 | tr -d '+/=\\n' | cut -c -${LENGTH})\"\n    RANDOM_PASSWORD=\"${PREFIX}${RANDOM_PASSWORD}\"\n    az keyvault secret set --vault-name ${keyVaultName} --name $SECRET_KEY_NAME --value $RANDOM_PASSWORD > /dev/null\n    if [[ $? -ne 0 ]]; then\n        echo \"Error generating secret\"\n    fi\n    echo \"$RANDOM_PASSWORD\"\nelif [[ \"$MODE\" == \"save\" ]]; then\n    SECRET_KEY_NAME=\"$2\"\n    SECRET_VALUE=\"$3\"\n    # If empty value, store it empty\n    if [[ -z \"$SECRET_VALUE\" ]]; then\n      az keyvault secret set --vault-name ${keyVaultName} --name $SECRET_KEY_NAME --file /dev/null > /dev/null\n    else\n      az keyvault secret set --vault-name ${keyVaultName} --name $SECRET_KEY_NAME --value $SECRET_VALUE > /dev/null\n    fi\n    if [[ $? -ne 0 ]]; then\n        echo \"Error generating secret\"\n    fi\n    echo \"$SECRET_VALUE\"\nelse\n    exit 1\nfi\n",
    "get_public_ip": "#!/bin/bash\naz login --identity --allow-no-subscriptions > /dev/null\n\naz network public-ip show \\\n  --id ${publicIPId} \\\n  --query \"ipAddress\" -o tsv\n",
    "check_app_ready": "#!/bin/bash\nwhile true; do\n  HTTP_STATUS=$(curl -Ik http://localhost:7880 | head -n1 | awk '{print $2}')\n  if [ $HTTP_STATUS == 200 ]; then\n    break\n  fi\n  sleep 5\ndone\n",
    "restart": "#!/bin/bash -x\nset -e\n# Stop all services\nsystemctl stop openvidu\n\n# Update config from secret\n/usr/local/bin/update_config_from_secret.sh\n\n# Start all services\nsystemctl start openvidu\n",
    "config_blobStorageTemplate": "#!/bin/bash\nset -e\n\n# Install dir and config dir\nINSTALL_DIR=\"/opt/openvidu\"\nCONFIG_DIR=\"${INSTALL_DIR}/config\"\n\naz login --identity\n\n# Config azure blob storage\nAZURE_ACCOUNT_NAME=\"${storageAccountName}\"\nAZURE_ACCOUNT_KEY=$(az storage account keys list --account-name ${storageAccountName} --query '[0].value' -o tsv)\nAZURE_CONTAINER_NAME=\"${storageAccountContainerName}\"\n\nsed -i \"s|AZURE_ACCOUNT_NAME=.*|AZURE_ACCOUNT_NAME=$AZURE_ACCOUNT_NAME|\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s|AZURE_ACCOUNT_KEY=.*|AZURE_ACCOUNT_KEY=$AZURE_ACCOUNT_KEY|\" \"${CONFIG_DIR}/openvidu.env\"\nsed -i \"s|AZURE_CONTAINER_NAME=.*|AZURE_CONTAINER_NAME=$AZURE_CONTAINER_NAME|\" \"${CONFIG_DIR}/openvidu.env\"\n",
    "formattedTemplateInstallScript": "[reduce(items(variables('stringInterpolationParams')), createObject('value', variables('installScriptTemplate')), lambda('curr', 'next', createObject('value', replace(lambdaVariables('curr').value, format('${{{0}}}', lambdaVariables('next').key), lambdaVariables('next').value)))).value]",
    "after_installScriptMaster": "[reduce(items(variables('stringInterpolationParams')), createObject('value', variables('after_installScriptTemplate')), lambda('curr', 'next', createObject('value', replace(lambdaVariables('curr').value, format('${{{0}}}', lambdaVariables('next').key), lambdaVariables('next').value)))).value]",
    "get_public_ip_script": "[reduce(items(variables('stringInterpolationParams')), createObject('value', variables('get_public_ip')), lambda('curr', 'next', createObject('value', replace(lambdaVariables('curr').value, format('${{{0}}}', lambdaVariables('next').key), lambdaVariables('next').value)))).value]",
    "update_config_from_secretScript": "[reduce(items(variables('stringInterpolationParams')), createObject('value', variables('update_config_from_secretScriptTemplate')), lambda('curr', 'next', createObject('value', replace(lambdaVariables('curr').value, format('${{{0}}}', lambdaVariables('next').key), lambdaVariables('next').value)))).value]",
    "update_secret_from_configScript": "[reduce(items(variables('stringInterpolationParams')), createObject('value', variables('update_secret_from_configScriptTemplate')), lambda('curr', 'next', createObject('value', replace(lambdaVariables('curr').value, format('${{{0}}}', lambdaVariables('next').key), lambdaVariables('next').value)))).value]",
    "store_secretScript": "[reduce(items(variables('stringInterpolationParams')), createObject('value', variables('store_secretScriptTemplate')), lambda('curr', 'next', createObject('value', replace(lambdaVariables('curr').value, format('${{{0}}}', lambdaVariables('next').key), lambdaVariables('next').value)))).value]",
    "base64install": "[base64(variables('formattedTemplateInstallScript'))]",
    "base64after_install": "[base64(variables('after_installScriptMaster'))]",
    "base64update_config_from_secret": "[base64(variables('update_config_from_secretScript'))]",
    "base64update_secret_from_config": "[base64(variables('update_secret_from_configScript'))]",
    "base64get_value_from_config": "[base64(variables('get_value_from_configScript'))]",
    "base64store_secret": "[base64(variables('store_secretScript'))]",
    "base64get_public_ip": "[base64(variables('get_public_ip_script'))]",
    "base64check_app_ready": "[base64(variables('check_app_ready'))]",
    "base64restart": "[base64(variables('restart'))]",
    "userDataTemplate": "#!/bin/bash -x\nset -eu -o pipefail\n\necho ${base64install} | base64 -d > /usr/local/bin/install.sh\nchmod +x /usr/local/bin/install.sh\n\n# after_install.sh\necho ${base64after_install} | base64 -d > /usr/local/bin/after_install.sh\nchmod +x /usr/local/bin/after_install.sh\n\n# update_config_from_secret.sh\necho ${base64update_config_from_secret} | base64 -d > /usr/local/bin/update_config_from_secret.sh\nchmod +x /usr/local/bin/update_config_from_secret.sh\n\n# update_secret_from_config.sh\necho ${base64update_secret_from_config} | base64 -d > /usr/local/bin/update_secret_from_config.sh\nchmod +x /usr/local/bin/update_secret_from_config.sh\n\n# get_value_from_config.sh\necho ${base64get_value_from_config} | base64 -d > /usr/local/bin/get_value_from_config.sh\nchmod +x /usr/local/bin/get_value_from_config.sh\n\n# store_secret.sh\necho ${base64store_secret} | base64 -d > /usr/local/bin/store_secret.sh\nchmod +x /usr/local/bin/store_secret.sh\n\n# get_public_ip.sh\necho ${base64get_public_ip} | base64 -d > /usr/local/bin/get_public_ip.sh\nchmod +x /usr/local/bin/get_public_ip.sh\n\necho ${base64check_app_ready} | base64 -d > /usr/local/bin/check_app_ready.sh\nchmod +x /usr/local/bin/check_app_ready.sh\n\necho ${base64restart} | base64 -d > /usr/local/bin/restart.sh\nchmod +x /usr/local/bin/restart.sh\n\necho ${base64config_blobStorage} | base64 -d > /usr/local/bin/config_blobStorage.sh\nchmod +x /usr/local/bin/config_blobStorage.sh\n\n# Install azure cli\ncurl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash\n\naz login --identity --allow-no-subscriptions\n\necho \"DPkg::Lock::Timeout \\\"-1\\\";\" > /etc/apt/apt.conf.d/99timeout\n\napt-get update && apt-get install -y\n\nexport HOME=\"/root\"\n\n# Install OpenVidu\n/usr/local/bin/install.sh || { echo \"[OpenVidu] error installing OpenVidu\"; exit 1; }\n\n#Config blob storage\n/usr/local/bin/config_blobStorage.sh || { echo \"[OpenVidu] error configuring Blob Storage\"; exit 1; }\n\n# Start OpenVidu\nsystemctl start openvidu || { echo \"[OpenVidu] error starting OpenVidu\"; exit 1; }\n\n# Update shared secret\n/usr/local/bin/after_install.sh || { echo \"[OpenVidu] error updating shared secret\"; exit 1; }\n\n# Launch on reboot\necho \"@reboot /usr/local/bin/restart.sh >> /var/log/openvidu-restart.log\" 2>&1 | crontab\n\n# Wait for the app\n/usr/local/bin/check_app_ready.sh\n",
    "ipExists": "[equals(parameters('publicIpAddressObject').newOrExistingOrNone, 'existing')]",
    "ipNew": "[equals(parameters('publicIpAddressObject').newOrExistingOrNone, 'new')]",
    "publicIPId": "[if(variables('ipNew'), resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIpAddressObject').name), if(variables('ipExists'), resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIpAddressObject').name), ''))]",
    "isEmptyStorageAccountName": "[equals(parameters('storageAccountName'), '')]",
    "isEmptyContainerName": "[equals(parameters('containerName'), '')]"
  },
  "resources": [
    {
      "type": "Microsoft.KeyVault/vaults",
      "apiVersion": "2023-07-01",
      "name": "[variables('keyVaultName')]",
      "location": "[variables('location')]",
      "properties": {
        "enabledForDeployment": true,
        "enabledForDiskEncryption": false,
        "enabledForTemplateDeployment": true,
        "tenantId": "[variables('tenantId')]",
        "enableSoftDelete": false,
        "accessPolicies": [
          {
            "objectId": "[reference(resourceId('Microsoft.Compute/virtualMachines', variables('openviduVMSettings').vmName), '2023-09-01', 'full').identity.principalId]",
            "tenantId": "[variables('tenantId')]",
            "permissions": {
              "secrets": [
                "get",
                "set",
                "list"
              ]
            }
          },
          {
            "objectId": "[variables('deploymentUser')]",
            "tenantId": "[variables('tenantId')]",
            "permissions": {
              "secrets": [
                "get",
                "list",
                "set",
                "delete",
                "recover",
                "backup",
                "restore"
              ]
            }
          }
        ],
        "sku": {
          "name": "standard",
          "family": "A"
        },
        "networkAcls": {
          "defaultAction": "Allow",
          "bypass": "AzureServices"
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Compute/virtualMachines', variables('openviduVMSettings').vmName)]"
      ]
    },
    {
      "type": "Microsoft.Compute/virtualMachines",
      "apiVersion": "2023-09-01",
      "name": "[variables('openviduVMSettings').vmName]",
      "location": "[variables('location')]",
      "identity": {
        "type": "SystemAssigned"
      },
      "properties": {
        "hardwareProfile": {
          "vmSize": "[parameters('instanceType')]"
        },
        "storageProfile": {
          "osDisk": {
            "createOption": "FromImage",
            "managedDisk": {
              "storageAccountType": "[variables('openviduVMSettings').osDiskType]"
            },
            "diskSizeGB": 100
          },
          "imageReference": "[variables('openviduVMSettings').ubuntuOSVersion]"
        },
        "networkProfile": {
          "networkInterfaces": [
            {
              "id": "[resourceId('Microsoft.Network/networkInterfaces', variables('networkSettings').netInterfaceName)]"
            }
          ]
        },
        "osProfile": {
          "computerName": "[variables('openviduVMSettings').vmName]",
          "adminUsername": "[parameters('adminUsername')]",
          "linuxConfiguration": "[variables('openviduVMSettings').linuxConfiguration]"
        },
        "userData": "[base64(reduce(items(createObject('base64install', variables('base64install'), 'base64after_install', variables('base64after_install'), 'base64update_config_from_secret', variables('base64update_config_from_secret'), 'base64update_secret_from_config', variables('base64update_secret_from_config'), 'base64get_value_from_config', variables('base64get_value_from_config'), 'base64store_secret', variables('base64store_secret'), 'base64get_public_ip', variables('base64get_public_ip'), 'base64check_app_ready', variables('base64check_app_ready'), 'base64restart', variables('base64restart'), 'base64config_blobStorage', base64(reduce(items(createObject('storageAccountName', if(variables('isEmptyStorageAccountName'), uniqueString(resourceGroup().id), parameters('storageAccountName')), 'storageAccountKey', listKeys(resourceId('Microsoft.Storage/storageAccounts', uniqueString(resourceGroup().id)), '2021-04-01').keys[0].value, 'storageAccountContainerName', if(variables('isEmptyContainerName'), 'openvidu-appdata', format('{0}', parameters('containerName'))))), createObject('value', variables('config_blobStorageTemplate')), lambda('curr', 'next', createObject('value', replace(lambdaVariables('curr').value, format('${{{0}}}', lambdaVariables('next').key), lambdaVariables('next').value)))).value))), createObject('value', variables('userDataTemplate')), lambda('curr', 'next', createObject('value', replace(lambdaVariables('curr').value, format('${{{0}}}', lambdaVariables('next').key), lambdaVariables('next').value)))).value)]"
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkInterfaces', variables('networkSettings').netInterfaceName)]",
        "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIpAddressObject').name)]",
        "[resourceId('Microsoft.Storage/storageAccounts', uniqueString(resourceGroup().id))]"
      ]
    },
    {
      "type": "Microsoft.Authorization/roleAssignments",
      "apiVersion": "2022-04-01",
      "name": "[guid(format('roleAssignmentForOpenViduServer{0}', variables('openviduVMSettings').vmName))]",
      "properties": {
        "roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]",
        "principalId": "[reference(resourceId('Microsoft.Compute/virtualMachines', variables('openviduVMSettings').vmName), '2023-09-01', 'full').identity.principalId]",
        "principalType": "ServicePrincipal"
      },
      "dependsOn": [
        "[resourceId('Microsoft.Compute/virtualMachines', variables('openviduVMSettings').vmName)]"
      ]
    },
    {
      "condition": "[equals(variables('ipNew'), true())]",
      "type": "Microsoft.Network/publicIPAddresses",
      "apiVersion": "2023-11-01",
      "name": "[parameters('publicIpAddressObject').name]",
      "location": "[variables('location')]",
      "sku": {
        "name": "Standard",
        "tier": "Regional"
      },
      "properties": {
        "publicIPAddressVersion": "IPv4",
        "publicIPAllocationMethod": "Static",
        "dnsSettings": {
          "domainNameLabel": "[if(variables('isEmptyDomain'), toLower(format('{0}', parameters('stackName'))), null())]"
        }
      }
    },
    {
      "type": "Microsoft.Network/virtualNetworks",
      "apiVersion": "2023-11-01",
      "name": "[variables('networkSettings').vNetName]",
      "location": "[variables('location')]",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[variables('networkSettings').vNetAddressPrefix]"
          ]
        },
        "subnets": [
          {
            "name": "[variables('networkSettings').subnetName]",
            "properties": {
              "addressPrefix": "[variables('networkSettings').subnetAddressPrefix]",
              "privateEndpointNetworkPolicies": "Disabled",
              "privateLinkServiceNetworkPolicies": "Enabled",
              "networkSecurityGroup": {
                "id": "[resourceId('Microsoft.Network/networkSecurityGroups', format('{0}-nsg', parameters('stackName')))]"
              }
            }
          }
        ]
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/networkSecurityGroups', format('{0}-nsg', parameters('stackName')))]"
      ]
    },
    {
      "type": "Microsoft.Network/networkInterfaces",
      "apiVersion": "2023-11-01",
      "name": "[variables('networkSettings').netInterfaceName]",
      "location": "[variables('location')]",
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', variables('networkSettings').vNetName, variables('networkSettings').subnetName)]"
              },
              "publicIPAddress": "[if(variables('isEmptyIp'), null(), createObject('id', if(variables('ipNew'), resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIpAddressObject').name), resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIpAddressObject').name))))]"
            }
          }
        ],
        "networkSecurityGroup": {
          "id": "[resourceId('Microsoft.Network/networkSecurityGroups', format('{0}-nsg', parameters('stackName')))]"
        }
      },
      "dependsOn": [
        "[resourceId('Microsoft.Network/publicIPAddresses', parameters('publicIpAddressObject').name)]",
        "[resourceId('Microsoft.Network/virtualNetworks', variables('networkSettings').vNetName)]",
        "[resourceId('Microsoft.Network/networkSecurityGroups', format('{0}-nsg', parameters('stackName')))]"
      ]
    },
    {
      "type": "Microsoft.Network/networkSecurityGroups",
      "apiVersion": "2023-11-01",
      "name": "[format('{0}-nsg', parameters('stackName'))]",
      "location": "[variables('location')]",
      "properties": {
        "securityRules": [
          {
            "name": "SSH",
            "properties": {
              "protocol": "Tcp",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "22",
              "access": "Allow",
              "priority": 100,
              "direction": "Inbound"
            }
          },
          {
            "name": "HTTP",
            "properties": {
              "protocol": "Tcp",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "80",
              "access": "Allow",
              "priority": 110,
              "direction": "Inbound"
            }
          },
          {
            "name": "HTTPS",
            "properties": {
              "protocol": "Tcp",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "443",
              "access": "Allow",
              "priority": 120,
              "direction": "Inbound"
            }
          },
          {
            "name": "TURN",
            "properties": {
              "protocol": "Udp",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "443",
              "access": "Allow",
              "priority": 130,
              "direction": "Inbound"
            }
          },
          {
            "name": "RTMP",
            "properties": {
              "protocol": "Tcp",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "1935",
              "access": "Allow",
              "priority": 140,
              "direction": "Inbound"
            }
          },
          {
            "name": "WebRTC_over_TCP",
            "properties": {
              "protocol": "Tcp",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "7881",
              "access": "Allow",
              "priority": 150,
              "direction": "Inbound"
            }
          },
          {
            "name": "WebRTC_using_WHIP",
            "properties": {
              "protocol": "Udp",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "7885",
              "access": "Allow",
              "priority": 160,
              "direction": "Inbound"
            }
          },
          {
            "name": "MinIO",
            "properties": {
              "protocol": "Tcp",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*",
              "destinationAddressPrefix": "*",
              "destinationPortRange": "9000",
              "access": "Allow",
              "priority": 170,
              "direction": "Inbound"
            }
          },
          {
            "name": "WebRTC_traffic_UDP",
            "properties": {
              "protocol": "Udp",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*",
              "destinationAddressPrefix": "*",
              "destinationPortRanges": [
                "50000",
                "60000"
              ],
              "access": "Allow",
              "priority": 180,
              "direction": "Inbound"
            }
          },
          {
            "name": "WebRTC_traffic_TCP",
            "properties": {
              "protocol": "Tcp",
              "sourceAddressPrefix": "*",
              "sourcePortRange": "*",
              "destinationAddressPrefix": "*",
              "destinationPortRanges": [
                "50000",
                "60000"
              ],
              "access": "Allow",
              "priority": 190,
              "direction": "Inbound"
            }
          }
        ]
      }
    },
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2023-01-01",
      "name": "[uniqueString(resourceGroup().id)]",
      "location": "[resourceGroup().location]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "StorageV2",
      "properties": {
        "accessTier": "Cool",
        "supportsHttpsTrafficOnly": true
      }
    },
    {
      "type": "Microsoft.Storage/storageAccounts/blobServices/containers",
      "apiVersion": "2023-01-01",
      "name": "[if(variables('isEmptyContainerName'), format('{0}/default/openvidu-appdata', uniqueString(resourceGroup().id)), format('{0}/default/{1}', uniqueString(resourceGroup().id), parameters('containerName')))]",
      "properties": {
        "publicAccess": "None"
      },
      "dependsOn": [
        "[resourceId('Microsoft.Storage/storageAccounts', uniqueString(resourceGroup().id))]"
      ]
    }
  ]
}