mirror of https://github.com/OpenVidu/openvidu.git
2960 lines
93 KiB
Bicep
2960 lines
93 KiB
Bicep
@description('Stack name')
|
|
param stackName string
|
|
|
|
@description('''
|
|
[selfsigned] Not recommended for production use. If you don't have a FQDN, (DomainName parameter) you can use this option to generate a self-signed certificate.
|
|
[owncert] Valid for productions environments. If you have a FQDN, (DomainName parameter)
|
|
and an Elastic IP, you can use this option to use your own certificate.
|
|
[letsencrypt] Valid for production environments. If you have a FQDN, (DomainName parameter)
|
|
and an Elastic IP, you can use this option to generate a Let's Encrypt certificate.
|
|
''')
|
|
@allowed([
|
|
'selfsigned'
|
|
'owncert'
|
|
'letsencrypt'
|
|
])
|
|
param certificateType string = 'selfsigned'
|
|
|
|
@description('Domain name for the OpenVidu Deployment. Blank will generate default domain')
|
|
param domainName string
|
|
|
|
@description('If certificate type is \'owncert\', this parameter will be used to specify the public certificate')
|
|
param ownPublicCertificate string = ''
|
|
|
|
@description('If certificate type is \'owncert\', this parameter will be used to specify the private certificate')
|
|
param ownPrivateCertificate string = ''
|
|
|
|
@description('If certificate type is \'letsencrypt\', this email will be used for Let\'s Encrypt notifications')
|
|
param letsEncryptEmail string = ''
|
|
|
|
@description('Name of the PublicIPAddress resource in Azure when using certificateType \'owncert\' or \'letsencrypt\'')
|
|
param publicIpAddressResourceName string = ''
|
|
|
|
@description('(Optional) Domain name for the TURN server with TLS. Only needed if your users are behind restrictive firewalls')
|
|
param turnDomainName string = ''
|
|
|
|
@description('(Optional) This setting is applicable if the certificate type is set to \'owncert\' and the TurnDomainName is specified.')
|
|
param turnOwnPublicCertificate string = ''
|
|
|
|
@description('(Optional) This setting is applicable if the certificate type is set to \'owncert\' and the TurnDomainName is specified.')
|
|
param turnOwnPrivateCertificate string = ''
|
|
|
|
@description('Name of the PublicIPAddress resource in Azure when using TURN server with TLS')
|
|
param turnPublicIpAddressResourceName string = ''
|
|
|
|
@description('Visit https://openvidu.io/account')
|
|
@secure()
|
|
param openviduLicense string
|
|
|
|
@description('RTCEngine media engine to use')
|
|
@allowed([
|
|
'pion'
|
|
'mediasoup'
|
|
])
|
|
param rtcEngine string = 'pion'
|
|
|
|
@description('Specifies the EC2 instance type for your OpenVidu Master Node')
|
|
@allowed([
|
|
'Standard_B1s'
|
|
'Standard_B1ms'
|
|
'Standard_B2s'
|
|
'Standard_B2ms'
|
|
'Standard_B4ms'
|
|
'Standard_B8ms'
|
|
'Standard_D2_v3'
|
|
'Standard_D4_v3'
|
|
'Standard_D8_v3'
|
|
'Standard_D16_v3'
|
|
'Standard_D32_v3'
|
|
'Standard_D48_v3'
|
|
'Standard_D64_v3'
|
|
'Standard_D2_v4'
|
|
'Standard_D4_v4'
|
|
'Standard_D8_v4'
|
|
'Standard_D16_v4'
|
|
'Standard_D32_v4'
|
|
'Standard_D48_v4'
|
|
'Standard_D64_v4'
|
|
'Standard_D96_v4'
|
|
'Standard_D2_v5'
|
|
'Standard_D4_v5'
|
|
'Standard_D8_v5'
|
|
'Standard_D16_v5'
|
|
'Standard_D32_v5'
|
|
'Standard_D48_v5'
|
|
'Standard_D64_v5'
|
|
'Standard_D96_v5'
|
|
'Standard_F2'
|
|
'Standard_F4'
|
|
'Standard_F8'
|
|
'Standard_F16'
|
|
'Standard_F32'
|
|
'Standard_F64'
|
|
'Standard_F72'
|
|
'Standard_F2s_v2'
|
|
'Standard_F4s_v2'
|
|
'Standard_F8s_v2'
|
|
'Standard_F16s_v2'
|
|
'Standard_F32s_v2'
|
|
'Standard_F64s_v2'
|
|
'Standard_F72s_v2'
|
|
'Standard_E2_v3'
|
|
'Standard_E4_v3'
|
|
'Standard_E8_v3'
|
|
'Standard_E16_v3'
|
|
'Standard_E32_v3'
|
|
'Standard_E48_v3'
|
|
'Standard_E64_v3'
|
|
'Standard_E96_v3'
|
|
'Standard_E2_v4'
|
|
'Standard_E4_v4'
|
|
'Standard_E8_v4'
|
|
'Standard_E16_v4'
|
|
'Standard_E32_v4'
|
|
'Standard_E48_v4'
|
|
'Standard_E64_v4'
|
|
'Standard_E2_v5'
|
|
'Standard_E4_v5'
|
|
'Standard_E8_v5'
|
|
'Standard_E16_v5'
|
|
'Standard_E32_v5'
|
|
'Standard_E48_v5'
|
|
'Standard_E64_v5'
|
|
'Standard_E96_v5'
|
|
'Standard_M64'
|
|
'Standard_M128'
|
|
'Standard_M208ms_v2'
|
|
'Standard_M416ms_v2'
|
|
'Standard_L4s_v2'
|
|
'Standard_L8s_v2'
|
|
'Standard_L16s_v2'
|
|
'Standard_L32s_v2'
|
|
'Standard_L64s_v2'
|
|
'Standard_L80s_v2'
|
|
'Standard_NC6'
|
|
'Standard_NC12'
|
|
'Standard_NC24'
|
|
'Standard_NC24r'
|
|
'Standard_ND6s'
|
|
'Standard_ND12s'
|
|
'Standard_ND24s'
|
|
'Standard_ND24rs'
|
|
'Standard_NV6'
|
|
'Standard_NV12'
|
|
'Standard_NV24'
|
|
'Standard_H8'
|
|
'Standard_H16'
|
|
'Standard_H16r'
|
|
'Standard_H16mr'
|
|
'Standard_HB120rs_v2'
|
|
'Standard_HC44rs'
|
|
'Standard_DC2s'
|
|
'Standard_DC4s'
|
|
'Standard_DC2s_v2'
|
|
'Standard_DC4s_v2'
|
|
'Standard_DC8s_v2'
|
|
'Standard_DC16s_v2'
|
|
'Standard_DC32s_v2'
|
|
'Standard_A1_v2'
|
|
'Standard_A2_v2'
|
|
'Standard_A4_v2'
|
|
'Standard_A8_v2'
|
|
'Standard_A2m_v2'
|
|
'Standard_A4m_v2'
|
|
'Standard_A8m_v2'
|
|
])
|
|
param masterNodeInstanceType string = 'Standard_B2s'
|
|
|
|
@description('Size of the disk in GB')
|
|
param masterNodesDiskSize int = 100
|
|
|
|
@description('Specifies the EC2 instance type for your OpenVidu Media Nodes')
|
|
@allowed([
|
|
'Standard_B1s'
|
|
'Standard_B1ms'
|
|
'Standard_B2s'
|
|
'Standard_B2ms'
|
|
'Standard_B4ms'
|
|
'Standard_B8ms'
|
|
'Standard_D2_v3'
|
|
'Standard_D4_v3'
|
|
'Standard_D8_v3'
|
|
'Standard_D16_v3'
|
|
'Standard_D32_v3'
|
|
'Standard_D48_v3'
|
|
'Standard_D64_v3'
|
|
'Standard_D2_v4'
|
|
'Standard_D4_v4'
|
|
'Standard_D8_v4'
|
|
'Standard_D16_v4'
|
|
'Standard_D32_v4'
|
|
'Standard_D48_v4'
|
|
'Standard_D64_v4'
|
|
'Standard_D96_v4'
|
|
'Standard_D2_v5'
|
|
'Standard_D4_v5'
|
|
'Standard_D8_v5'
|
|
'Standard_D16_v5'
|
|
'Standard_D32_v5'
|
|
'Standard_D48_v5'
|
|
'Standard_D64_v5'
|
|
'Standard_D96_v5'
|
|
'Standard_F2'
|
|
'Standard_F4'
|
|
'Standard_F8'
|
|
'Standard_F16'
|
|
'Standard_F32'
|
|
'Standard_F64'
|
|
'Standard_F72'
|
|
'Standard_F2s_v2'
|
|
'Standard_F4s_v2'
|
|
'Standard_F8s_v2'
|
|
'Standard_F16s_v2'
|
|
'Standard_F32s_v2'
|
|
'Standard_F64s_v2'
|
|
'Standard_F72s_v2'
|
|
'Standard_E2_v3'
|
|
'Standard_E4_v3'
|
|
'Standard_E8_v3'
|
|
'Standard_E16_v3'
|
|
'Standard_E32_v3'
|
|
'Standard_E48_v3'
|
|
'Standard_E64_v3'
|
|
'Standard_E96_v3'
|
|
'Standard_E2_v4'
|
|
'Standard_E4_v4'
|
|
'Standard_E8_v4'
|
|
'Standard_E16_v4'
|
|
'Standard_E32_v4'
|
|
'Standard_E48_v4'
|
|
'Standard_E64_v4'
|
|
'Standard_E2_v5'
|
|
'Standard_E4_v5'
|
|
'Standard_E8_v5'
|
|
'Standard_E16_v5'
|
|
'Standard_E32_v5'
|
|
'Standard_E48_v5'
|
|
'Standard_E64_v5'
|
|
'Standard_E96_v5'
|
|
'Standard_M64'
|
|
'Standard_M128'
|
|
'Standard_M208ms_v2'
|
|
'Standard_M416ms_v2'
|
|
'Standard_L4s_v2'
|
|
'Standard_L8s_v2'
|
|
'Standard_L16s_v2'
|
|
'Standard_L32s_v2'
|
|
'Standard_L64s_v2'
|
|
'Standard_L80s_v2'
|
|
'Standard_NC6'
|
|
'Standard_NC12'
|
|
'Standard_NC24'
|
|
'Standard_NC24r'
|
|
'Standard_ND6s'
|
|
'Standard_ND12s'
|
|
'Standard_ND24s'
|
|
'Standard_ND24rs'
|
|
'Standard_NV6'
|
|
'Standard_NV12'
|
|
'Standard_NV24'
|
|
'Standard_H8'
|
|
'Standard_H16'
|
|
'Standard_H16r'
|
|
'Standard_H16mr'
|
|
'Standard_HB120rs_v2'
|
|
'Standard_HC44rs'
|
|
'Standard_DC2s'
|
|
'Standard_DC4s'
|
|
'Standard_DC2s_v2'
|
|
'Standard_DC4s_v2'
|
|
'Standard_DC8s_v2'
|
|
'Standard_DC16s_v2'
|
|
'Standard_DC32s_v2'
|
|
'Standard_A1_v2'
|
|
'Standard_A2_v2'
|
|
'Standard_A4_v2'
|
|
'Standard_A8_v2'
|
|
'Standard_A2m_v2'
|
|
'Standard_A4m_v2'
|
|
'Standard_A8m_v2'
|
|
])
|
|
param mediaNodeInstanceType string = 'Standard_B2s'
|
|
|
|
@description('Username for the Virtual Machine.')
|
|
param adminUsername string
|
|
|
|
@description('SSH Key for the Virtual Machine.')
|
|
@secure()
|
|
param adminSshKey string
|
|
|
|
@description('Number of initial media nodes to deploy')
|
|
param initialNumberOfMediaNodes int = 1
|
|
|
|
@description('Minimum number of media nodes to deploy')
|
|
param minNumberOfMediaNodes int = 1
|
|
|
|
@description('Maximum number of media nodes to deploy')
|
|
param maxNumberOfMediaNodes int = 5
|
|
|
|
@description('Target CPU percentage to scale up or down')
|
|
param scaleTargetCPU int = 50
|
|
|
|
/*------------------------------------------- VARIABLES AND VALIDATIONS -------------------------------------------*/
|
|
|
|
var masterNodeVMSettings = {
|
|
osDiskType: 'StandardSSD_LRS'
|
|
osDiskSize: masterNodesDiskSize
|
|
ubuntuOSVersion: {
|
|
publisher: 'Canonical'
|
|
offer: '0001-com-ubuntu-server-jammy'
|
|
sku: '22_04-lts-gen2'
|
|
version: 'latest'
|
|
}
|
|
linuxConfiguration: {
|
|
disablePasswordAuthentication: true
|
|
ssh: {
|
|
publicKeys: [
|
|
{
|
|
path: '/home/${adminUsername}/.ssh/authorized_keys'
|
|
keyData: adminSshKey
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
|
|
var mediaNodeVMSettings = {
|
|
vmName: '${stackName}-VN-MediaNode'
|
|
osDiskType: 'StandardSSD_LRS'
|
|
ubuntuOSVersion: {
|
|
publisher: 'Canonical'
|
|
offer: '0001-com-ubuntu-server-jammy'
|
|
sku: '22_04-lts-gen2'
|
|
version: 'latest'
|
|
}
|
|
linuxConfiguration: {
|
|
disablePasswordAuthentication: true
|
|
ssh: {
|
|
publicKeys: [
|
|
{
|
|
path: '/home/${adminUsername}/.ssh/authorized_keys'
|
|
keyData: adminSshKey
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
|
|
var turnTLSIsEnabled = turnDomainName != ''
|
|
|
|
var fqdn = domainName
|
|
|
|
var keyVaultName = '${stackName}-keyvault'
|
|
|
|
var location = resourceGroup().location
|
|
|
|
var tenantId = subscription().tenantId
|
|
|
|
var deploymentUser = az.deployer().objectId
|
|
|
|
/*------------------------------------------- KEY VAULT -------------------------------------------*/
|
|
|
|
resource openviduSharedInfo 'Microsoft.KeyVault/vaults@2023-07-01' = {
|
|
name: keyVaultName
|
|
location: location
|
|
properties: {
|
|
enabledForDeployment: true
|
|
enabledForDiskEncryption: false
|
|
enabledForTemplateDeployment: true
|
|
tenantId: tenantId
|
|
enableSoftDelete: false
|
|
accessPolicies: [
|
|
{
|
|
objectId: openviduMasterNode1.identity.principalId
|
|
tenantId: tenantId
|
|
permissions: {
|
|
secrets: ['get', 'set', 'list']
|
|
}
|
|
}
|
|
{
|
|
objectId: openviduMasterNode2.identity.principalId
|
|
tenantId: tenantId
|
|
permissions: {
|
|
secrets: ['get', 'set', 'list']
|
|
}
|
|
}
|
|
{
|
|
objectId: openviduMasterNode3.identity.principalId
|
|
tenantId: tenantId
|
|
permissions: {
|
|
secrets: ['get', 'set', 'list']
|
|
}
|
|
}
|
|
{
|
|
objectId: openviduMasterNode4.identity.principalId
|
|
tenantId: tenantId
|
|
permissions: {
|
|
secrets: ['get', 'set', 'list']
|
|
}
|
|
}
|
|
{
|
|
objectId: openviduScaleSetMediaNode.identity.principalId
|
|
tenantId: tenantId
|
|
permissions: {
|
|
secrets: ['get']
|
|
}
|
|
}
|
|
{
|
|
objectId: deploymentUser
|
|
tenantId: tenantId
|
|
permissions: {
|
|
secrets: ['get', 'list', 'set', 'delete', 'recover', 'backup', 'restore']
|
|
}
|
|
}
|
|
]
|
|
sku: {
|
|
name: 'standard'
|
|
family: 'A'
|
|
}
|
|
networkAcls: {
|
|
defaultAction: 'Allow'
|
|
bypass: 'AzureServices'
|
|
}
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------- MASTER NODE -------------------------------------------*/
|
|
|
|
var stringInterpolationParamsMaster1 = {
|
|
domainName: domainName
|
|
turnDomainName: turnDomainName
|
|
certificateType: certificateType
|
|
letsEncryptEmail: letsEncryptEmail
|
|
ownPublicCertificate: ownPublicCertificate
|
|
ownPrivateCertificate: ownPrivateCertificate
|
|
turnOwnPublicCertificate: turnOwnPublicCertificate
|
|
turnOwnPrivateCertificate: turnOwnPrivateCertificate
|
|
fqdn: fqdn
|
|
openviduLicense: openviduLicense
|
|
rtcEngine: rtcEngine
|
|
keyVaultName: keyVaultName
|
|
masterNodeNum: '1'
|
|
}
|
|
|
|
var stringInterpolationParamsMaster2 = {
|
|
domainName: domainName
|
|
turnDomainName: turnDomainName
|
|
certificateType: certificateType
|
|
letsEncryptEmail: letsEncryptEmail
|
|
ownPublicCertificate: ownPublicCertificate
|
|
ownPrivateCertificate: ownPrivateCertificate
|
|
turnOwnPublicCertificate: turnOwnPublicCertificate
|
|
turnOwnPrivateCertificate: turnOwnPrivateCertificate
|
|
fqdn: fqdn
|
|
openviduLicense: openviduLicense
|
|
rtcEngine: rtcEngine
|
|
keyVaultName: keyVaultName
|
|
masterNodeNum: '2'
|
|
}
|
|
|
|
var stringInterpolationParamsMaster3 = {
|
|
domainName: domainName
|
|
turnDomainName: turnDomainName
|
|
certificateType: certificateType
|
|
letsEncryptEmail: letsEncryptEmail
|
|
ownPublicCertificate: ownPublicCertificate
|
|
ownPrivateCertificate: ownPrivateCertificate
|
|
turnOwnPublicCertificate: turnOwnPublicCertificate
|
|
turnOwnPrivateCertificate: turnOwnPrivateCertificate
|
|
fqdn: fqdn
|
|
openviduLicense: openviduLicense
|
|
rtcEngine: rtcEngine
|
|
keyVaultName: keyVaultName
|
|
masterNodeNum: '3'
|
|
}
|
|
|
|
var stringInterpolationParamsMaster4 = {
|
|
domainName: domainName
|
|
turnDomainName: turnDomainName
|
|
certificateType: certificateType
|
|
letsEncryptEmail: letsEncryptEmail
|
|
ownPublicCertificate: ownPublicCertificate
|
|
ownPrivateCertificate: ownPrivateCertificate
|
|
turnOwnPublicCertificate: turnOwnPublicCertificate
|
|
turnOwnPrivateCertificate: turnOwnPrivateCertificate
|
|
fqdn: fqdn
|
|
openviduLicense: openviduLicense
|
|
rtcEngine: rtcEngine
|
|
keyVaultName: keyVaultName
|
|
masterNodeNum: '4'
|
|
}
|
|
|
|
var installScriptTemplateMaster = '''
|
|
#!/bin/bash -x
|
|
set -e
|
|
OPENVIDU_VERSION=main
|
|
DOMAIN=
|
|
|
|
# Assume azure cli is installed
|
|
|
|
apt-get update && apt-get install -y \
|
|
curl \
|
|
unzip \
|
|
jq \
|
|
wget
|
|
|
|
# Configure Domain
|
|
if [[ "${domainName}" == '' ]]; then
|
|
DOMAIN=${fqdn}
|
|
else
|
|
DOMAIN=${domainName}
|
|
fi
|
|
|
|
# Wait for the keyvault availability
|
|
MAX_WAIT=100
|
|
WAIT_INTERVAL=1
|
|
ELAPSED_TIME=0
|
|
set +e
|
|
while true; do
|
|
# Check keyvault availability
|
|
az keyvault secret list --vault-name ${keyVaultName}
|
|
|
|
# If it is available, exit the loop
|
|
if [ $? -eq 0 ]; then
|
|
break
|
|
fi
|
|
|
|
# If not, wait and check again incrementing the time
|
|
ELAPSED_TIME=$((ELAPSED_TIME + WAIT_INTERVAL))
|
|
|
|
# If exceeded the maximum time, exit with error
|
|
if [ $ELAPSED_TIME -ge $MAX_WAIT ]; then
|
|
exit 1
|
|
fi
|
|
|
|
# Esperar antes de la próxima comprobación
|
|
sleep $WAIT_INTERVAL
|
|
done
|
|
set -e
|
|
|
|
MASTER_NODE_NUM=${masterNodeNum}
|
|
|
|
# Get own private IP
|
|
PRIVATE_IP=$(curl -H Metadata:true --noproxy "*" "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/privateIpAddress?api-version=2017-08-01&format=text")
|
|
|
|
# Store current private IP
|
|
PRIVATE_IP="$(/usr/local/bin/store_secret.sh save MASTER-NODE-${masterNodeNum}-PRIVATE-IP $PRIVATE_IP)"
|
|
|
|
|
|
if [[ $MASTER_NODE_NUM -eq 1 ]] && [[ "$ALL_SECRETS_GENERATED" == "" || "$ALL_SECRETS_GENERATED" == "false" ]]; then
|
|
DOMAIN="$(/usr/local/bin/store_secret.sh save DOMAIN-NAME "${domainName}")"
|
|
if [[ -n "${turnDomainName}" ]]; then
|
|
LIVEKIT_TURN_DOMAIN_NAME="$(/usr/local/bin/store_secret.sh save LIVEKIT-TURN-DOMAIN-NAME "${turnDomainName}")"
|
|
fi
|
|
if [[ "${certificateType}" == "letsencrypt" ]]; then
|
|
LETSENCRYPT_EMAIL=$(/usr/local/bin/store_secret.sh save LETSENCRYPT-EMAIL "${letsEncryptEmail}")
|
|
fi
|
|
|
|
# Store usernames and generate random passwords
|
|
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/store_secret.sh save OPENVIDU-PRO-LICENSE "${openviduLicense}")"
|
|
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/store_secret.sh save OPENVIDU-RTC-ENGINE "${rtcEngine}")"
|
|
REDIS_PASSWORD="$(/usr/local/bin/store_secret.sh generate REDIS-PASSWORD)"
|
|
MONGO_ADMIN_USERNAME="$(/usr/local/bin/store_secret.sh save MONGO-ADMIN-USERNAME "mongoadmin")"
|
|
MONGO_ADMIN_PASSWORD="$(/usr/local/bin/store_secret.sh generate MONGO-ADMIN-PASSWORD)"
|
|
MONGO_REPLICA_SET_KEY="$(/usr/local/bin/store_secret.sh generate MONGO-REPLICA-SET-KEY)"
|
|
MINIO_ACCESS_KEY="$(/usr/local/bin/store_secret.sh save MINIO-ACCESS-KEY "minioadmin")"
|
|
MINIO_SECRET_KEY="$(/usr/local/bin/store_secret.sh generate MINIO-SECRET-KEY)"
|
|
DASHBOARD_ADMIN_USERNAME="$(/usr/local/bin/store_secret.sh save DASHBOARD-ADMIN-USERNAME "dashboardadmin")"
|
|
DASHBOARD_ADMIN_PASSWORD="$(/usr/local/bin/store_secret.sh generate DASHBOARD-ADMIN-PASSWORD)"
|
|
GRAFANA_ADMIN_USERNAME="$(/usr/local/bin/store_secret.sh save GRAFANA-ADMIN-USERNAME "grafanaadmin")"
|
|
GRAFANA_ADMIN_PASSWORD="$(/usr/local/bin/store_secret.sh generate GRAFANA-ADMIN-PASSWORD)"
|
|
DEFAULT_APP_USERNAME="$(/usr/local/bin/store_secret.sh save DEFAULT-APP-USERNAME "calluser")"
|
|
DEFAULT_APP_PASSWORD="$(/usr/local/bin/store_secret.sh generate DEFAULT-APP-PASSWORD)"
|
|
DEFAULT_APP_ADMIN_USERNAME="$(/usr/local/bin/store_secret.sh save DEFAULT-APP-ADMIN-USERNAME "calladmin")"
|
|
DEFAULT_APP_ADMIN_PASSWORD="$(/usr/local/bin/store_secret.sh generate DEFAULT-APP-ADMIN-PASSWORD)"
|
|
LIVEKIT_API_KEY="$(/usr/local/bin/store_secret.sh generate LIVEKIT-API-KEY "API" 12)"
|
|
LIVEKIT_API_SECRET="$(/usr/local/bin/store_secret.sh generate LIVEKIT-API-SECRET)"
|
|
OPENVIDU_VERSION="$(/usr/local/bin/store_secret.sh save OPENVIDU-VERSION "${OPENVIDU_VERSION}")"
|
|
ENABLED_MODULES="$(/usr/local/bin/store_secret.sh save ENABLED-MODULES "observability,app")"
|
|
ALL_SECRETS_GENERATED="$(/usr/local/bin/store_secret.sh save ALL-SECRETS-GENERATED "true")"
|
|
fi
|
|
|
|
while true; do
|
|
MASTER_NODE_1_PRIVATE_IP=$(az keyvault secret show --vault-name ${keyVaultName} --name MASTER-NODE-1-PRIVATE-IP --query value -o tsv) || true
|
|
MASTER_NODE_2_PRIVATE_IP=$(az keyvault secret show --vault-name ${keyVaultName} --name MASTER-NODE-2-PRIVATE-IP --query value -o tsv) || true
|
|
MASTER_NODE_3_PRIVATE_IP=$(az keyvault secret show --vault-name ${keyVaultName} --name MASTER-NODE-3-PRIVATE-IP --query value -o tsv) || true
|
|
MASTER_NODE_4_PRIVATE_IP=$(az keyvault secret show --vault-name ${keyVaultName} --name MASTER-NODE-4-PRIVATE-IP --query value -o tsv) || true
|
|
# Check if all master nodes have stored their private IPs
|
|
if [[ "$MASTER_NODE_1_PRIVATE_IP" != "" ]] &&
|
|
[[ "$MASTER_NODE_2_PRIVATE_IP" != "" ]] &&
|
|
[[ "$MASTER_NODE_3_PRIVATE_IP" != "" ]] &&
|
|
[[ "$MASTER_NODE_4_PRIVATE_IP" != "" ]]; then
|
|
break
|
|
fi
|
|
sleep 5
|
|
done
|
|
|
|
|
|
# Fetch the values in the keyvault
|
|
MASTER_NODE_1_PRIVATE_IP=$(az keyvault secret show --vault-name ${keyVaultName} --name MASTER-NODE-1-PRIVATE-IP --query value -o tsv)
|
|
MASTER_NODE_2_PRIVATE_IP=$(az keyvault secret show --vault-name ${keyVaultName} --name MASTER-NODE-2-PRIVATE-IP --query value -o tsv)
|
|
MASTER_NODE_3_PRIVATE_IP=$(az keyvault secret show --vault-name ${keyVaultName} --name MASTER-NODE-3-PRIVATE-IP --query value -o tsv)
|
|
MASTER_NODE_4_PRIVATE_IP=$(az keyvault secret show --vault-name ${keyVaultName} --name MASTER-NODE-4-PRIVATE-IP --query value -o tsv)
|
|
MASTER_NODE_PRIVATE_IP_LIST="$MASTER_NODE_1_PRIVATE_IP,$MASTER_NODE_2_PRIVATE_IP,$MASTER_NODE_3_PRIVATE_IP,$MASTER_NODE_4_PRIVATE_IP"
|
|
|
|
DOMAIN=$(az keyvault secret show --vault-name ${keyVaultName} --name DOMAIN-NAME --query value -o tsv)
|
|
if [[ -n "${turnDomainName}" ]]; then
|
|
LIVEKIT_TURN_DOMAIN_NAME=$(az keyvault secret show --vault-name ${keyVaultName} --name LIVEKIT-TURN-DOMAIN-NAME --query value -o tsv)
|
|
fi
|
|
if [[ "${certificateType}" == "letsencrypt" ]]; then
|
|
LETSENCRYPT_EMAIL=$(az keyvault secret show --vault-name ${keyVaultName} --name LETSENCRYPT-EMAIL --query value -o tsv)
|
|
fi
|
|
OPENVIDU_RTC_ENGINE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --query value -o tsv)
|
|
OPENVIDU_PRO_LICENSE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-PRO-LICENSE --query value -o tsv)
|
|
REDIS_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name REDIS-PASSWORD --query value -o tsv)
|
|
MONGO_ADMIN_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --query value -o tsv)
|
|
MONGO_ADMIN_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name MONGO-ADMIN-PASSWORD --query value -o tsv)
|
|
MONGO_REPLICA_SET_KEY=$(az keyvault secret show --vault-name ${keyVaultName} --name MONGO-REPLICA-SET-KEY --query value -o tsv)
|
|
DASHBOARD_ADMIN_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name DASHBOARD-ADMIN-USERNAME --query value -o tsv)
|
|
DASHBOARD_ADMIN_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name DASHBOARD-ADMIN-PASSWORD --query value -o tsv)
|
|
MINIO_ACCESS_KEY=$(az keyvault secret show --vault-name ${keyVaultName} --name MINIO-ACCESS-KEY --query value -o tsv)
|
|
MINIO_SECRET_KEY=$(az keyvault secret show --vault-name ${keyVaultName} --name MINIO-SECRET-KEY --query value -o tsv)
|
|
GRAFANA_ADMIN_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name GRAFANA-ADMIN-USERNAME --query value -o tsv)
|
|
GRAFANA_ADMIN_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name GRAFANA-ADMIN-PASSWORD --query value -o tsv)
|
|
LIVEKIT_API_KEY=$(az keyvault secret show --vault-name ${keyVaultName} --name LIVEKIT-API-KEY --query value -o tsv)
|
|
LIVEKIT_API_SECRET=$(az keyvault secret show --vault-name ${keyVaultName} --name LIVEKIT-API-SECRET --query value -o tsv)
|
|
DEFAULT_APP_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name DEFAULT-APP-USERNAME --query value -o tsv)
|
|
DEFAULT_APP_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name DEFAULT-APP-PASSWORD --query value -o tsv)
|
|
DEFAULT_APP_ADMIN_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name DEFAULT-APP-ADMIN-USERNAME --query value -o tsv)
|
|
DEFAULT_APP_ADMIN_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name DEFAULT-APP-ADMIN-PASSWORD --query value -o tsv)
|
|
ENABLED_MODULES=$(az keyvault secret show --vault-name ${keyVaultName} --name ENABLED-MODULES --query value -o tsv)
|
|
|
|
|
|
# Base command
|
|
INSTALL_COMMAND="sh <(curl -fsSL http://get.openvidu.io/pro/ha/$OPENVIDU_VERSION/install_ov_master_node.sh)"
|
|
|
|
# Common arguments
|
|
COMMON_ARGS=(
|
|
"--no-tty"
|
|
"--install"
|
|
"--environment=azure"
|
|
"--deployment-type='ha'"
|
|
"--node-role='master-node'"
|
|
"--external-load-balancer"
|
|
"--internal-tls-termination"
|
|
"--master-node-private-ip-list='$MASTER_NODE_PRIVATE_IP_LIST'"
|
|
"--openvidu-pro-license='$OPENVIDU_PRO_LICENSE'"
|
|
"--domain-name='$DOMAIN'"
|
|
"--enabled-modules='$ENABLED_MODULES'"
|
|
"--rtc-engine=$OPENVIDU_RTC_ENGINE"
|
|
"--redis-password=$REDIS_PASSWORD"
|
|
"--mongo-admin-user=$MONGO_ADMIN_USERNAME"
|
|
"--mongo-admin-password=$MONGO_ADMIN_PASSWORD"
|
|
"--mongo-replica-set-key=$MONGO_REPLICA_SET_KEY"
|
|
"--minio-access-key=$MINIO_ACCESS_KEY"
|
|
"--minio-secret-key=$MINIO_SECRET_KEY"
|
|
"--dashboard-admin-user=$DASHBOARD_ADMIN_USERNAME"
|
|
"--dashboard-admin-password=$DASHBOARD_ADMIN_PASSWORD"
|
|
"--grafana-admin-user=$GRAFANA_ADMIN_USERNAME"
|
|
"--grafana-admin-password=$GRAFANA_ADMIN_PASSWORD"
|
|
"--default-app-user=$DEFAULT_APP_USERNAME"
|
|
"--default-app-password=$DEFAULT_APP_PASSWORD"
|
|
"--default-app-admin-user=$DEFAULT_APP_ADMIN_USERNAME"
|
|
"--default-app-admin-password=$DEFAULT_APP_ADMIN_PASSWORD"
|
|
"--livekit-api-key=$LIVEKIT_API_KEY"
|
|
"--livekit-api-secret=$LIVEKIT_API_SECRET"
|
|
)
|
|
|
|
if [[ $LIVEKIT_TURN_DOMAIN_NAME != "" ]]; then
|
|
COMMON_ARGS+=("--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME}")
|
|
fi
|
|
|
|
# Certificate arguments
|
|
if [[ "${certificateType}" == "selfsigned" ]]; then
|
|
CERT_ARGS=(
|
|
"--certificate-type=selfsigned"
|
|
)
|
|
elif [[ "${certificateType}" == "letsencrypt" ]]; then
|
|
CERT_ARGS=(
|
|
"--certificate-type=letsencrypt"
|
|
"--letsencrypt-email=$LETSENCRYPT_EMAIL"
|
|
)
|
|
else
|
|
# Download owncert files
|
|
mkdir -p /tmp/owncert
|
|
wget -O /tmp/owncert/fullchain.pem ${ownPublicCertificate}
|
|
wget -O /tmp/owncert/privkey.pem ${ownPrivateCertificate}
|
|
|
|
# Convert to base64
|
|
OWN_CERT_CRT=$(base64 -w 0 /tmp/owncert/fullchain.pem)
|
|
OWN_CERT_KEY=$(base64 -w 0 /tmp/owncert/privkey.pem)
|
|
|
|
CERT_ARGS=(
|
|
"--certificate-type=owncert"
|
|
"--owncert-public-key=$OWN_CERT_CRT"
|
|
"--owncert-private-key=$OWN_CERT_KEY"
|
|
)
|
|
|
|
# Turn with TLS and own certificate
|
|
if [[ "${turnDomainName}" != '' ]]; then
|
|
# Download owncert files
|
|
mkdir -p /tmp/owncert-turn
|
|
wget -O /tmp/owncert-turn/fullchain.pem ${turnOwnPublicCertificate}
|
|
wget -O /tmp/owncert-turn/privkey.pem ${turnOwnPrivateCertificate}
|
|
|
|
# Convert to base64
|
|
OWN_CERT_CRT_TURN=$(base64 -w 0 /tmp/owncert-turn/fullchain.pem)
|
|
OWN_CERT_KEY_TURN=$(base64 -w 0 /tmp/owncert-turn/privkey.pem)
|
|
|
|
CERT_ARGS+=(
|
|
"--turn-owncert-private-key=$OWN_CERT_KEY_TURN"
|
|
"--turn-owncert-public-key=$OWN_CERT_CRT_TURN"
|
|
)
|
|
fi
|
|
fi
|
|
|
|
# Construct the final command
|
|
FINAL_COMMAND="$INSTALL_COMMAND $(printf "%s " "${COMMON_ARGS[@]}") $(printf "%s " "${CERT_ARGS[@]}")"
|
|
|
|
# Install OpenVidu
|
|
exec bash -c "$FINAL_COMMAND"
|
|
'''
|
|
|
|
var after_installScriptTemplateMaster = '''
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
az login --identity --allow-no-subscriptions > /dev/null
|
|
|
|
# Generate URLs
|
|
DOMAIN=$(az keyvault secret show --vault-name ${keyVaultName} --name DOMAIN-NAME --query value -o tsv)
|
|
DASHBOARD_URL="https://${DOMAIN}/dashboard/"
|
|
GRAFANA_URL="https://${DOMAIN}/grafana/"
|
|
MINIO_URL="https://${DOMAIN}/minio-console/"
|
|
|
|
# Update shared secret
|
|
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN
|
|
az keyvault secret set --vault-name ${keyVaultName} --name DASHBOARD-URL --value $DASHBOARD_URL
|
|
az keyvault secret set --vault-name ${keyVaultName} --name GRAFANA-URL --value $GRAFANA_URL
|
|
az keyvault secret set --vault-name ${keyVaultName} --name MINIO-URL --value $MINIO_URL
|
|
|
|
az keyvault secret show --vault-name ${keyVaultName} --name MINIO-URL
|
|
|
|
if [[ $? -ne 0 ]]; then
|
|
echo "Error updating keyvault"
|
|
fi
|
|
'''
|
|
var update_config_from_secretScriptTemplateMaster = '''
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
az login --identity --allow-no-subscriptions > /dev/null
|
|
|
|
# Installation directory
|
|
INSTALL_DIR="/opt/openvidu"
|
|
CLUSTER_CONFIG_DIR="${INSTALL_DIR}/config/cluster"
|
|
MASTER_NODE_CONFIG_DIR="${INSTALL_DIR}/config/node"
|
|
|
|
# Replace DOMAIN_NAME
|
|
export DOMAIN=$(az keyvault secret show --vault-name ${keyVaultName} --name DOMAIN-NAME --query value -o tsv)
|
|
if [[ -n "$DOMAIN" ]]; then
|
|
sed -i "s/DOMAIN_NAME=.*/DOMAIN_NAME=$DOMAIN/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
else
|
|
exit 1
|
|
fi
|
|
|
|
# Replace LIVEKIT_TURN_DOMAIN_NAME
|
|
export LIVEKIT_TURN_DOMAIN_NAME=$(az keyvault secret show --vault-name ${keyVaultName} --name LIVEKIT-TURN-DOMAIN-NAME --query value -o tsv)
|
|
if [[ -n "$LIVEKIT_TURN_DOMAIN_NAME" ]]; then
|
|
sed -i "s/LIVEKIT_TURN_DOMAIN_NAME=.*/LIVEKIT_TURN_DOMAIN_NAME=$LIVEKIT_TURN_DOMAIN_NAME/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
fi
|
|
|
|
if [[ ${certificateType} == "letsencrypt" ]]; then
|
|
export LETSENCRYPT_EMAIL=$(az keyvault secret show --vault-name ${keyVaultName} --name LETSENCRYPT-EMAIL --query value -o tsv)
|
|
sed -i "s/LETSENCRYPT_EMAIL=.*/LETSENCRYPT_EMAIL=$LETSENCRYPT_EMAIL/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
fi
|
|
|
|
# Get the rest of the values
|
|
export REDIS_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name REDIS-PASSWORD --query value -o tsv)
|
|
export OPENVIDU_RTC_ENGINE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --query value -o tsv)
|
|
export OPENVIDU_PRO_LICENSE=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-PRO-LICENSE --query value -o tsv)
|
|
export MONGO_ADMIN_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --query value -o tsv)
|
|
export MONGO_ADMIN_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name MONGO-ADMIN-PASSWORD --query value -o tsv)
|
|
export MONGO_REPLICA_SET_KEY=$(az keyvault secret show --vault-name ${keyVaultName} --name MONGO-REPLICA-SET-KEY --query value -o tsv)
|
|
export DASHBOARD_ADMIN_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name DASHBOARD-ADMIN-USERNAME --query value -o tsv)
|
|
export DASHBOARD_ADMIN_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name DASHBOARD-ADMIN-PASSWORD --query value -o tsv)
|
|
export MINIO_ACCESS_KEY=$(az keyvault secret show --vault-name ${keyVaultName} --name MINIO-ACCESS-KEY --query value -o tsv)
|
|
export MINIO_SECRET_KEY=$(az keyvault secret show --vault-name ${keyVaultName} --name MINIO-SECRET-KEY --query value -o tsv)
|
|
export GRAFANA_ADMIN_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name GRAFANA-ADMIN-USERNAME --query value -o tsv)
|
|
export GRAFANA_ADMIN_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name GRAFANA-ADMIN-PASSWORD --query value -o tsv)
|
|
export LIVEKIT_API_KEY=$(az keyvault secret show --vault-name ${keyVaultName} --name LIVEKIT-API-KEY --query value -o tsv)
|
|
export LIVEKIT_API_SECRET=$(az keyvault secret show --vault-name ${keyVaultName} --name LIVEKIT-API-SECRET --query value -o tsv)
|
|
export DEFAULT_APP_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name DEFAULT-APP-USERNAME --query value -o tsv)
|
|
export DEFAULT_APP_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name DEFAULT-APP-PASSWORD --query value -o tsv)
|
|
export DEFAULT_APP_ADMIN_USERNAME=$(az keyvault secret show --vault-name ${keyVaultName} --name DEFAULT-APP-ADMIN-USERNAME --query value -o tsv)
|
|
export DEFAULT_APP_ADMIN_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name DEFAULT-APP-ADMIN-PASSWORD --query value -o tsv)
|
|
export ENABLED_MODULES=$(az keyvault secret show --vault-name ${keyVaultName} --name ENABLED-MODULES --query value -o tsv)
|
|
|
|
# Replace rest of the values
|
|
sed -i "s/REDIS_PASSWORD=.*/REDIS_PASSWORD=$REDIS_PASSWORD/" "${MASTER_NODE_CONFIG_DIR}/master_node.env"
|
|
sed -i "s/OPENVIDU_RTC_ENGINE=.*/OPENVIDU_RTC_ENGINE=$OPENVIDU_RTC_ENGINE/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
sed -i "s/OPENVIDU_PRO_LICENSE=.*/OPENVIDU_PRO_LICENSE=$OPENVIDU_PRO_LICENSE/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
sed -i "s/MONGO_ADMIN_USERNAME=.*/MONGO_ADMIN_USERNAME=$MONGO_ADMIN_USERNAME/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
sed -i "s/MONGO_ADMIN_PASSWORD=.*/MONGO_ADMIN_PASSWORD=$MONGO_ADMIN_PASSWORD/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
sed -i "s/MONGO_REPLICA_SET_KEY=.*/MONGO_REPLICA_SET_KEY=$MONGO_REPLICA_SET_KEY/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
sed -i "s/DASHBOARD_ADMIN_USERNAME=.*/DASHBOARD_ADMIN_USERNAME=$DASHBOARD_ADMIN_USERNAME/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
sed -i "s/DASHBOARD_ADMIN_PASSWORD=.*/DASHBOARD_ADMIN_PASSWORD=$DASHBOARD_ADMIN_PASSWORD/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
sed -i "s/MINIO_ACCESS_KEY=.*/MINIO_ACCESS_KEY=$MINIO_ACCESS_KEY/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
sed -i "s/MINIO_SECRET_KEY=.*/MINIO_SECRET_KEY=$MINIO_SECRET_KEY/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
sed -i "s/GRAFANA_ADMIN_USERNAME=.*/GRAFANA_ADMIN_USERNAME=$GRAFANA_ADMIN_USERNAME/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
sed -i "s/GRAFANA_ADMIN_PASSWORD=.*/GRAFANA_ADMIN_PASSWORD=$GRAFANA_ADMIN_PASSWORD/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
sed -i "s/LIVEKIT_API_KEY=.*/LIVEKIT_API_KEY=$LIVEKIT_API_KEY/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
sed -i "s/LIVEKIT_API_SECRET=.*/LIVEKIT_API_SECRET=$LIVEKIT_API_SECRET/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
sed -i "s/CALL_USER=.*/CALL_USER=$DEFAULT_APP_USERNAME/" "${CLUSTER_CONFIG_DIR}/master_node/app.env"
|
|
sed -i "s/CALL_SECRET=.*/CALL_SECRET=$DEFAULT_APP_PASSWORD/" "${CLUSTER_CONFIG_DIR}/master_node/app.env"
|
|
sed -i "s/CALL_ADMIN_USER=.*/CALL_ADMIN_USER=$DEFAULT_APP_ADMIN_USERNAME/" "${CLUSTER_CONFIG_DIR}/master_node/app.env"
|
|
sed -i "s/CALL_ADMIN_SECRET=.*/CALL_ADMIN_SECRET=$DEFAULT_APP_ADMIN_PASSWORD/" "${CLUSTER_CONFIG_DIR}/master_node/app.env"
|
|
sed -i "s/ENABLED_MODULES=.*/ENABLED_MODULES=$ENABLED_MODULES/" "${CLUSTER_CONFIG_DIR}/openvidu.env"
|
|
|
|
# Update URLs in secret
|
|
DASHBOARD_URL="https://${DOMAIN}/dashboard/"
|
|
GRAFANA_URL="https://${DOMAIN}/grafana/"
|
|
MINIO_URL="https://${DOMAIN}/minio-console/"
|
|
|
|
# Update shared secret
|
|
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN
|
|
az keyvault secret set --vault-name ${keyVaultName} --name DASHBOARD-URL --value $DASHBOARD_URL
|
|
az keyvault secret set --vault-name ${keyVaultName} --name GRAFANA-URL --value $GRAFANA_URL
|
|
az keyvault secret set --vault-name ${keyVaultName} --name MINIO-URL --value $MINIO_URL
|
|
'''
|
|
|
|
var update_secret_from_configScriptTemplateMaster = '''
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
az login --identity --allow-no-subscriptions > /dev/null
|
|
|
|
# Installation directory
|
|
INSTALL_DIR="/opt/openvidu"
|
|
CLUSTER_CONFIG_DIR="${INSTALL_DIR}/config/cluster"
|
|
MASTER_NODE_CONFIG_DIR="${INSTALL_DIR}/config/node"
|
|
|
|
if [[ ${certificateType} == "letsencrypt" ]]; then
|
|
LETSENCRYPT_EMAIL="$(/usr/local/bin/get_value_from_config.sh LETSENCRYPT_EMAIL "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
az keyvault secret set --vault-name ${keyVaultName} --name "LETSENCRYPT-EMAIL" --value $LETSENCRYPT_EMAIL
|
|
fi
|
|
|
|
# Get current values of the config
|
|
REDIS_PASSWORD="$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${MASTER_NODE_CONFIG_DIR}/master_node.env")"
|
|
DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
LIVEKIT_TURN_DOMAIN_NAME="$(/usr/local/bin/get_value_from_config.sh LIVEKIT_TURN_DOMAIN_NAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
OPENVIDU_RTC_ENGINE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_RTC_ENGINE "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
OPENVIDU_PRO_LICENSE="$(/usr/local/bin/get_value_from_config.sh OPENVIDU_PRO_LICENSE "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
MONGO_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_USERNAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
MONGO_ADMIN_PASSWORD="$(/usr/local/bin/get_value_from_config.sh MONGO_ADMIN_PASSWORD "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
MONGO_REPLICA_SET_KEY="$(/usr/local/bin/get_value_from_config.sh MONGO_REPLICA_SET_KEY "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
MINIO_ACCESS_KEY="$(/usr/local/bin/get_value_from_config.sh MINIO_ACCESS_KEY "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
MINIO_SECRET_KEY="$(/usr/local/bin/get_value_from_config.sh MINIO_SECRET_KEY "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
DASHBOARD_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh DASHBOARD_ADMIN_USERNAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
DASHBOARD_ADMIN_PASSWORD="$(/usr/local/bin/get_value_from_config.sh DASHBOARD_ADMIN_PASSWORD "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
GRAFANA_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh GRAFANA_ADMIN_USERNAME "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
GRAFANA_ADMIN_PASSWORD="$(/usr/local/bin/get_value_from_config.sh GRAFANA_ADMIN_PASSWORD "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
LIVEKIT_API_KEY="$(/usr/local/bin/get_value_from_config.sh LIVEKIT_API_KEY "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
LIVEKIT_API_SECRET="$(/usr/local/bin/get_value_from_config.sh LIVEKIT_API_SECRET "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
DEFAULT_APP_USERNAME="$(/usr/local/bin/get_value_from_config.sh CALL_USER "${CLUSTER_CONFIG_DIR}/master_node/app.env")"
|
|
DEFAULT_APP_PASSWORD="$(/usr/local/bin/get_value_from_config.sh CALL_SECRET "${CLUSTER_CONFIG_DIR}/master_node/app.env")"
|
|
DEFAULT_APP_ADMIN_USERNAME="$(/usr/local/bin/get_value_from_config.sh CALL_ADMIN_USER "${CLUSTER_CONFIG_DIR}/master_node/app.env")"
|
|
DEFAULT_APP_ADMIN_PASSWORD="$(/usr/local/bin/get_value_from_config.sh CALL_ADMIN_SECRET "${CLUSTER_CONFIG_DIR}/master_node/app.env")"
|
|
ENABLED_MODULES="$(/usr/local/bin/get_value_from_config.sh ENABLED_MODULES "${CLUSTER_CONFIG_DIR}/openvidu.env")"
|
|
|
|
# Update shared secret
|
|
az keyvault secret set --vault-name ${keyVaultName} --name REDIS-PASSWORD --value $REDIS_PASSWORD
|
|
az keyvault secret set --vault-name ${keyVaultName} --name DOMAIN-NAME --value $DOMAIN_NAME
|
|
az keyvault secret set --vault-name ${keyVaultName} --name LIVEKIT-TURN-DOMAIN-NAME --value $LIVEKIT_TURN_DOMAIN_NAME
|
|
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-RTC-ENGINE --value $OPENVIDU_RTC_ENGINE
|
|
az keyvault secret set --vault-name ${keyVaultName} --name OPENVIDU-PRO-LICENSE --value $OPENVIDU_PRO_LICENSE
|
|
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-ADMIN-USERNAME --value $MONGO_ADMIN_USERNAME
|
|
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-ADMIN-PASSWORD --value $MONGO_ADMIN_PASSWORD
|
|
az keyvault secret set --vault-name ${keyVaultName} --name MONGO-REPLICA-SET-KEY --value $MONGO_REPLICA_SET_KEY
|
|
az keyvault secret set --vault-name ${keyVaultName} --name MINIO-ACCESS-KEY --value $MINIO_ACCESS_KEY
|
|
az keyvault secret set --vault-name ${keyVaultName} --name MINIO-SECRET-KEY --value $MINIO_SECRET_KEY
|
|
az keyvault secret set --vault-name ${keyVaultName} --name DASHBOARD-ADMIN-USERNAME --value $DASHBOARD_ADMIN_USERNAME
|
|
az keyvault secret set --vault-name ${keyVaultName} --name DASHBOARD-ADMIN-PASSWORD --value $DASHBOARD_ADMIN_PASSWORD
|
|
az keyvault secret set --vault-name ${keyVaultName} --name GRAFANA-ADMIN-USERNAME --value $GRAFANA_ADMIN_USERNAME
|
|
az keyvault secret set --vault-name ${keyVaultName} --name GRAFANA-ADMIN-PASSWORD --value $GRAFANA_ADMIN_PASSWORD
|
|
az keyvault secret set --vault-name ${keyVaultName} --name LIVEKIT-API-KEY --value $LIVEKIT_API_KEY
|
|
az keyvault secret set --vault-name ${keyVaultName} --name LIVEKIT-API-SECRET --value $LIVEKIT_API_SECRET
|
|
az keyvault secret set --vault-name ${keyVaultName} --name DEFAULT-APP-USERNAME --value $DEFAULT_APP_USERNAME
|
|
az keyvault secret set --vault-name ${keyVaultName} --name DEFAULT-APP-PASSWORD --value $DEFAULT_APP_PASSWORD
|
|
az keyvault secret set --vault-name ${keyVaultName} --name DEFAULT-APP-ADMIN-USERNAME --value $DEFAULT_APP_ADMIN_USERNAME
|
|
az keyvault secret set --vault-name ${keyVaultName} --name DEFAULT-APP-ADMIN-PASSWORD --value $DEFAULT_APP_ADMIN_PASSWORD
|
|
az keyvault secret set --vault-name ${keyVaultName} --name ENABLED-MODULES --value $ENABLED_MODULES
|
|
'''
|
|
|
|
var get_value_from_configScriptMaster = '''
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
# Function to get the value of a given key from the environment file
|
|
get_value() {
|
|
local key="$1"
|
|
local file_path="$2"
|
|
|
|
# Use grep to find the line with the key, ignoring lines starting with #
|
|
# Use awk to split on '=' and print the second field, which is the value
|
|
local value=$(grep -E "^\s*$key\s*=" "$file_path" | awk -F= '{print $2}' | sed 's/#.*//; s/^\s*//; s/\s*$//')
|
|
|
|
# If the value is empty, return "none"
|
|
if [ -z "$value" ]; then
|
|
echo "none"
|
|
else
|
|
echo "$value"
|
|
fi
|
|
}
|
|
|
|
# Check if the correct number of arguments are supplied
|
|
if [ "$#" -ne 2 ]; then
|
|
echo "Usage: $0 <key> <file_path>"
|
|
exit 1
|
|
fi
|
|
|
|
# Get the key and file path from the arguments
|
|
key="$1"
|
|
file_path="$2"
|
|
|
|
# Get and print the value
|
|
get_value "$key" "$file_path"
|
|
'''
|
|
|
|
var store_secretScriptTemplateMaster = '''
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
az login --identity --allow-no-subscriptions > /dev/null
|
|
|
|
# Modes: save, generate
|
|
# save mode: save the secret in the secret manager
|
|
# generate mode: generate a random password and save it in the secret manager
|
|
MODE="$1"
|
|
|
|
if [[ "$MODE" == "generate" ]]; then
|
|
SECRET_KEY_NAME="$2"
|
|
PREFIX="${3:-}"
|
|
LENGTH="${4:-44}"
|
|
RANDOM_PASSWORD="$(openssl rand -base64 64 | tr -d '+/=\n' | cut -c -${LENGTH})"
|
|
RANDOM_PASSWORD="${PREFIX}${RANDOM_PASSWORD}"
|
|
az keyvault secret set --vault-name ${keyVaultName} --name $SECRET_KEY_NAME --value $RANDOM_PASSWORD > /dev/null
|
|
if [[ $? -ne 0 ]]; then
|
|
echo "Error generating secret"
|
|
fi
|
|
echo "$RANDOM_PASSWORD"
|
|
elif [[ "$MODE" == "save" ]]; then
|
|
SECRET_KEY_NAME="$2"
|
|
SECRET_VALUE="$3"
|
|
az keyvault secret set --vault-name ${keyVaultName} --name $SECRET_KEY_NAME --value $SECRET_VALUE > /dev/null
|
|
if [[ $? -ne 0 ]]; then
|
|
echo "Error generating secret"
|
|
fi
|
|
echo "$SECRET_VALUE"
|
|
else
|
|
exit 1
|
|
fi
|
|
'''
|
|
|
|
var check_app_readyScriptMaster = '''
|
|
#!/bin/bash
|
|
set -e
|
|
while true; do
|
|
HTTP_STATUS=$(curl -Ik http://localhost:7880/twirp/health | head -n1 | awk '{print $2}')
|
|
if [ $HTTP_STATUS == 200 ]; then
|
|
break
|
|
fi
|
|
sleep 5
|
|
done
|
|
'''
|
|
|
|
var restartScriptMaster = '''
|
|
#!/bin/bash
|
|
set -e
|
|
# Stop all services
|
|
systemctl stop openvidu
|
|
|
|
# Update config from secret
|
|
/usr/local/bin/update_config_from_secret.sh
|
|
|
|
# Start all services
|
|
systemctl start openvidu
|
|
'''
|
|
|
|
var installScriptMaster1 = reduce(
|
|
items(stringInterpolationParamsMaster1),
|
|
{ value: installScriptTemplateMaster },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
var installScriptMaster2 = reduce(
|
|
items(stringInterpolationParamsMaster2),
|
|
{ value: installScriptTemplateMaster },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
var installScriptMaster3 = reduce(
|
|
items(stringInterpolationParamsMaster3),
|
|
{ value: installScriptTemplateMaster },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
var installScriptMaster4 = reduce(
|
|
items(stringInterpolationParamsMaster4),
|
|
{ value: installScriptTemplateMaster },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
var after_installScriptMaster = reduce(
|
|
items(stringInterpolationParamsMaster1),
|
|
{ value: after_installScriptTemplateMaster },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
var update_config_from_secretScriptMaster = reduce(
|
|
items(stringInterpolationParamsMaster1),
|
|
{ value: update_config_from_secretScriptTemplateMaster },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
var update_secret_from_configScriptMaster = reduce(
|
|
items(stringInterpolationParamsMaster1),
|
|
{ value: update_secret_from_configScriptTemplateMaster },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
var store_secretScriptMaster = reduce(
|
|
items(stringInterpolationParamsMaster1),
|
|
{ value: store_secretScriptTemplateMaster },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
var base64installMaster1 = base64(installScriptMaster1)
|
|
var base64installMaster2 = base64(installScriptMaster2)
|
|
var base64installMaster3 = base64(installScriptMaster3)
|
|
var base64installMaster4 = base64(installScriptMaster4)
|
|
var base64after_installMaster = base64(after_installScriptMaster)
|
|
var base64update_config_from_secretMaster = base64(update_config_from_secretScriptMaster)
|
|
var base64update_secret_from_configMaster = base64(update_secret_from_configScriptMaster)
|
|
var base64get_value_from_configMaster = base64(get_value_from_configScriptMaster)
|
|
var base64store_secretMaster = base64(store_secretScriptMaster)
|
|
var base64check_app_readyMaster = base64(check_app_readyScriptMaster)
|
|
var base64restartMaster = base64(restartScriptMaster)
|
|
|
|
var userDataParamsMasterNode1 = {
|
|
base64install: base64installMaster1
|
|
base64after_install: base64after_installMaster
|
|
base64update_config_from_secret: base64update_config_from_secretMaster
|
|
base64update_secret_from_config: base64update_secret_from_configMaster
|
|
base64get_value_from_config: base64get_value_from_configMaster
|
|
base64store_secret: base64store_secretMaster
|
|
base64check_app_ready: base64check_app_readyMaster
|
|
base64restart: base64restartMaster
|
|
keyVaultName: keyVaultName
|
|
masterNodeNum: '1'
|
|
}
|
|
|
|
var userDataParamsMasterNode2 = {
|
|
base64install: base64installMaster2
|
|
base64after_install: base64after_installMaster
|
|
base64update_config_from_secret: base64update_config_from_secretMaster
|
|
base64update_secret_from_config: base64update_secret_from_configMaster
|
|
base64get_value_from_config: base64get_value_from_configMaster
|
|
base64store_secret: base64store_secretMaster
|
|
base64check_app_ready: base64check_app_readyMaster
|
|
base64restart: base64restartMaster
|
|
keyVaultName: keyVaultName
|
|
masterNodeNum: '2'
|
|
}
|
|
|
|
var userDataParamsMasterNode3 = {
|
|
base64install: base64installMaster3
|
|
base64after_install: base64after_installMaster
|
|
base64update_config_from_secret: base64update_config_from_secretMaster
|
|
base64update_secret_from_config: base64update_secret_from_configMaster
|
|
base64get_value_from_config: base64get_value_from_configMaster
|
|
base64store_secret: base64store_secretMaster
|
|
base64check_app_ready: base64check_app_readyMaster
|
|
base64restart: base64restartMaster
|
|
keyVaultName: keyVaultName
|
|
masterNodeNum: '3'
|
|
}
|
|
|
|
var userDataParamsMasterNode4 = {
|
|
base64install: base64installMaster4
|
|
base64after_install: base64after_installMaster
|
|
base64update_config_from_secret: base64update_config_from_secretMaster
|
|
base64update_secret_from_config: base64update_secret_from_configMaster
|
|
base64get_value_from_config: base64get_value_from_configMaster
|
|
base64store_secret: base64store_secretMaster
|
|
base64check_app_ready: base64check_app_readyMaster
|
|
base64restart: base64restartMaster
|
|
keyVaultName: keyVaultName
|
|
masterNodeNum: '4'
|
|
storageAccountName: storageAccount.name
|
|
}
|
|
|
|
var userDataTemplateMasterNode = '''
|
|
#!/bin/bash -x
|
|
set -eu -o pipefail
|
|
|
|
# Introduce the scripts in the instance
|
|
# install.sh
|
|
echo ${base64install} | base64 -d > /usr/local/bin/install.sh
|
|
chmod +x /usr/local/bin/install.sh
|
|
|
|
# after_install.sh
|
|
echo ${base64after_install} | base64 -d > /usr/local/bin/after_install.sh
|
|
chmod +x /usr/local/bin/after_install.sh
|
|
|
|
# update_config_from_secret.sh
|
|
echo ${base64update_config_from_secret} | base64 -d > /usr/local/bin/update_config_from_secret.sh
|
|
chmod +x /usr/local/bin/update_config_from_secret.sh
|
|
|
|
# update_secret_from_config.sh
|
|
echo ${base64update_secret_from_config} | base64 -d > /usr/local/bin/update_secret_from_config.sh
|
|
chmod +x /usr/local/bin/update_secret_from_config.sh
|
|
|
|
# get_value_from_config.sh
|
|
echo ${base64get_value_from_config} | base64 -d > /usr/local/bin/get_value_from_config.sh
|
|
chmod +x /usr/local/bin/get_value_from_config.sh
|
|
|
|
# store_secret.sh
|
|
echo ${base64store_secret} | base64 -d > /usr/local/bin/store_secret.sh
|
|
chmod +x /usr/local/bin/store_secret.sh
|
|
|
|
# check_app_ready.sh
|
|
echo ${base64check_app_ready} | base64 -d > /usr/local/bin/check_app_ready.sh
|
|
chmod +x /usr/local/bin/check_app_ready.sh
|
|
|
|
# restart.sh
|
|
echo ${base64restart} | base64 -d > /usr/local/bin/restart.sh
|
|
chmod +x /usr/local/bin/restart.sh
|
|
|
|
# Install azure cli
|
|
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
|
|
|
|
az login --identity --allow-no-subscriptions
|
|
|
|
apt-get update && apt-get install -y
|
|
|
|
export HOME="/root"
|
|
|
|
# Install OpenVidu
|
|
/usr/local/bin/install.sh || { echo "[OpenVidu] error installing OpenVidu"; exit 1; }
|
|
|
|
# Start OpenVidu
|
|
systemctl start openvidu || { echo "[OpenVidu] error starting OpenVidu"; exit 1; }
|
|
|
|
# Update shared secret
|
|
/usr/local/bin/after_install.sh || { echo "[OpenVidu] error updating shared secret"; exit 1; }
|
|
|
|
# Launch on reboot
|
|
echo "@reboot /usr/local/bin/restart.sh >> /var/log/openvidu-restart.log" 2>&1 | crontab
|
|
|
|
MASTER_NODE_NUM=${masterNodeNum}
|
|
if [[ $MASTER_NODE_NUM -eq 4 ]]; then
|
|
set +e
|
|
az storage blob upload --account-name ${storageAccountName} --container-name automation-locks --name lock.txt --file /dev/null --auth-mode key
|
|
set -e
|
|
az keyvault secret set --vault-name ${keyVaultName} --name FINISH-MASTER-NODE --value "true"
|
|
fi
|
|
|
|
# Wait for the app
|
|
sleep 150
|
|
/usr/local/bin/check_app_ready.sh
|
|
'''
|
|
|
|
var userDataMasterNode1 = reduce(
|
|
items(userDataParamsMasterNode1),
|
|
{ value: userDataTemplateMasterNode },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
var userDataMasterNode2 = reduce(
|
|
items(userDataParamsMasterNode2),
|
|
{ value: userDataTemplateMasterNode },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
var userDataMasterNode3 = reduce(
|
|
items(userDataParamsMasterNode3),
|
|
{ value: userDataTemplateMasterNode },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
var userDataMasterNode4 = reduce(
|
|
items(userDataParamsMasterNode4),
|
|
{ value: userDataTemplateMasterNode },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
resource openviduMasterNode1 'Microsoft.Compute/virtualMachines@2023-09-01' = {
|
|
name: '${stackName}-VM-MasterNode1'
|
|
location: location
|
|
identity: { type: 'SystemAssigned' }
|
|
properties: {
|
|
hardwareProfile: {
|
|
vmSize: masterNodeInstanceType
|
|
}
|
|
storageProfile: {
|
|
osDisk: {
|
|
createOption: 'FromImage'
|
|
managedDisk: {
|
|
storageAccountType: masterNodeVMSettings.osDiskType
|
|
}
|
|
diskSizeGB: masterNodeVMSettings.osDiskSize
|
|
}
|
|
imageReference: masterNodeVMSettings.ubuntuOSVersion
|
|
}
|
|
networkProfile: {
|
|
networkInterfaces: [
|
|
{
|
|
id: netInterfaceMasterNode1.id
|
|
}
|
|
]
|
|
}
|
|
osProfile: {
|
|
computerName: '${stackName}-VM-MasterNode1'
|
|
adminUsername: adminUsername
|
|
adminPassword: adminSshKey
|
|
linuxConfiguration: masterNodeVMSettings.linuxConfiguration
|
|
}
|
|
userData: base64(userDataMasterNode1)
|
|
}
|
|
}
|
|
|
|
resource openviduMasterNode2 'Microsoft.Compute/virtualMachines@2023-09-01' = {
|
|
name: '${stackName}-VM-MasterNode2'
|
|
location: location
|
|
identity: { type: 'SystemAssigned' }
|
|
properties: {
|
|
hardwareProfile: {
|
|
vmSize: masterNodeInstanceType
|
|
}
|
|
storageProfile: {
|
|
osDisk: {
|
|
createOption: 'FromImage'
|
|
managedDisk: {
|
|
storageAccountType: masterNodeVMSettings.osDiskType
|
|
}
|
|
diskSizeGB: masterNodeVMSettings.osDiskSize
|
|
}
|
|
imageReference: masterNodeVMSettings.ubuntuOSVersion
|
|
}
|
|
networkProfile: {
|
|
networkInterfaces: [
|
|
{
|
|
id: netInterfaceMasterNode2.id
|
|
}
|
|
]
|
|
}
|
|
osProfile: {
|
|
computerName: '${stackName}-VM-MasterNode2'
|
|
adminUsername: adminUsername
|
|
adminPassword: adminSshKey
|
|
linuxConfiguration: masterNodeVMSettings.linuxConfiguration
|
|
}
|
|
userData: base64(userDataMasterNode2)
|
|
}
|
|
dependsOn: [openviduMasterNode1]
|
|
}
|
|
|
|
resource openviduMasterNode3 'Microsoft.Compute/virtualMachines@2023-09-01' = {
|
|
name: '${stackName}-VM-MasterNode3'
|
|
location: location
|
|
identity: { type: 'SystemAssigned' }
|
|
properties: {
|
|
hardwareProfile: {
|
|
vmSize: masterNodeInstanceType
|
|
}
|
|
storageProfile: {
|
|
osDisk: {
|
|
createOption: 'FromImage'
|
|
managedDisk: {
|
|
storageAccountType: masterNodeVMSettings.osDiskType
|
|
}
|
|
diskSizeGB: masterNodeVMSettings.osDiskSize
|
|
}
|
|
imageReference: masterNodeVMSettings.ubuntuOSVersion
|
|
}
|
|
networkProfile: {
|
|
networkInterfaces: [
|
|
{
|
|
id: netInterfaceMasterNode3.id
|
|
}
|
|
]
|
|
}
|
|
osProfile: {
|
|
computerName: '${stackName}-VM-MasterNode3'
|
|
adminUsername: adminUsername
|
|
adminPassword: adminSshKey
|
|
linuxConfiguration: masterNodeVMSettings.linuxConfiguration
|
|
}
|
|
userData: base64(userDataMasterNode3)
|
|
}
|
|
dependsOn: [openviduMasterNode2]
|
|
}
|
|
|
|
resource openviduMasterNode4 'Microsoft.Compute/virtualMachines@2023-09-01' = {
|
|
name: '${stackName}-VM-MasterNode4'
|
|
location: location
|
|
identity: { type: 'SystemAssigned' }
|
|
properties: {
|
|
hardwareProfile: {
|
|
vmSize: masterNodeInstanceType
|
|
}
|
|
storageProfile: {
|
|
osDisk: {
|
|
createOption: 'FromImage'
|
|
managedDisk: {
|
|
storageAccountType: masterNodeVMSettings.osDiskType
|
|
}
|
|
diskSizeGB: masterNodeVMSettings.osDiskSize
|
|
}
|
|
imageReference: masterNodeVMSettings.ubuntuOSVersion
|
|
}
|
|
networkProfile: {
|
|
networkInterfaces: [
|
|
{
|
|
id: netInterfaceMasterNode4.id
|
|
}
|
|
]
|
|
}
|
|
osProfile: {
|
|
computerName: '${stackName}-VM-MasterNode4'
|
|
adminUsername: adminUsername
|
|
adminPassword: adminSshKey
|
|
linuxConfiguration: masterNodeVMSettings.linuxConfiguration
|
|
}
|
|
userData: base64(userDataMasterNode4)
|
|
}
|
|
dependsOn: [openviduMasterNode3]
|
|
}
|
|
|
|
/*------------------------------------------- MEDIA NODES -------------------------------------------*/
|
|
|
|
var privateIPMasterNode1 = netInterfaceMasterNode1.properties.ipConfigurations[0].properties.privateIPAddress
|
|
var privateIPMasterNode2 = netInterfaceMasterNode2.properties.ipConfigurations[0].properties.privateIPAddress
|
|
var privateIPMasterNode3 = netInterfaceMasterNode3.properties.ipConfigurations[0].properties.privateIPAddress
|
|
var privateIPMasterNode4 = netInterfaceMasterNode4.properties.ipConfigurations[0].properties.privateIPAddress
|
|
|
|
var stringInterpolationParamsMedia = {
|
|
privateIPMasterNode1: privateIPMasterNode1
|
|
privateIPMasterNode2: privateIPMasterNode2
|
|
privateIPMasterNode3: privateIPMasterNode3
|
|
privateIPMasterNode4: privateIPMasterNode4
|
|
keyVaultName: keyVaultName
|
|
}
|
|
|
|
var installScriptTemplateMedia = '''
|
|
#!/bin/bash -x
|
|
DOMAIN=
|
|
|
|
# Install dependencies
|
|
apt-get update && apt-get install -y \
|
|
curl \
|
|
unzip \
|
|
jq \
|
|
wget
|
|
|
|
# Get own private IP
|
|
PRIVATE_IP=$(curl -H Metadata:true --noproxy "*" "http://169.254.169.254/metadata/instance/network/interface/0/ipv4/ipAddress/0/privateIpAddress?api-version=2017-08-01&format=text")
|
|
|
|
WAIT_INTERVAL=1
|
|
MAX_WAIT=10000
|
|
ELAPSED_TIME=0
|
|
set +e
|
|
while true; do
|
|
# get secret value
|
|
FINISH_MASTER_NODE=$(az keyvault secret show --vault-name ${keyVaultName} --name FINISH-MASTER-NODE --query value -o tsv)
|
|
|
|
# Check if all master nodes finished
|
|
if [ "$FINISH_MASTER_NODE" == "true" ]; then
|
|
break
|
|
fi
|
|
|
|
ELAPSED_TIME=$((ELAPSED_TIME + WAIT_INTERVAL))
|
|
|
|
# Check if the maximum waiting time has been reached
|
|
if [ $ELAPSED_TIME -ge $MAX_WAIT ]; then
|
|
exit 1
|
|
fi
|
|
|
|
sleep $WAIT_INTERVAL
|
|
done
|
|
set -e
|
|
|
|
MASTER_NODE_1_PRIVATE_IP=$(az keyvault secret show --vault-name ${keyVaultName} --name MASTER-NODE-1-PRIVATE-IP --query value -o tsv)
|
|
MASTER_NODE_2_PRIVATE_IP=$(az keyvault secret show --vault-name ${keyVaultName} --name MASTER-NODE-2-PRIVATE-IP --query value -o tsv)
|
|
MASTER_NODE_3_PRIVATE_IP=$(az keyvault secret show --vault-name ${keyVaultName} --name MASTER-NODE-3-PRIVATE-IP --query value -o tsv)
|
|
MASTER_NODE_4_PRIVATE_IP=$(az keyvault secret show --vault-name ${keyVaultName} --name MASTER-NODE-4-PRIVATE-IP --query value -o tsv)
|
|
MASTER_NODE_PRIVATE_IP_LIST="$MASTER_NODE_1_PRIVATE_IP,$MASTER_NODE_2_PRIVATE_IP,$MASTER_NODE_3_PRIVATE_IP,$MASTER_NODE_4_PRIVATE_IP"
|
|
REDIS_PASSWORD=$(az keyvault secret show --vault-name ${keyVaultName} --name REDIS-PASSWORD --query value -o tsv)
|
|
ENABLED_MODULES=$(az keyvault secret show --vault-name ${keyVaultName} --name ENABLED-MODULES --query value -o tsv)
|
|
OPENVIDU_VERSION=$(az keyvault secret show --vault-name ${keyVaultName} --name OPENVIDU-VERSION --query value -o tsv)
|
|
|
|
# Base command
|
|
INSTALL_COMMAND="sh <(curl -fsSL http://get.openvidu.io/pro/ha/$OPENVIDU_VERSION/install_ov_media_node.sh)"
|
|
|
|
# Common arguments
|
|
COMMON_ARGS=(
|
|
"--no-tty"
|
|
"--install"
|
|
"--environment=azure"
|
|
"--deployment-type='ha'"
|
|
"--node-role='media-node'"
|
|
"--master-node-private-ip-list=$MASTER_NODE_PRIVATE_IP_LIST"
|
|
"--private-ip=$PRIVATE_IP"
|
|
"--enabled-modules='$ENABLED_MODULES'"
|
|
"--redis-password=$REDIS_PASSWORD"
|
|
)
|
|
|
|
# Construct the final command with all arguments
|
|
FINAL_COMMAND="$INSTALL_COMMAND $(printf "%s " "${COMMON_ARGS[@]}")"
|
|
|
|
# Install OpenVidu
|
|
exec bash -c "$FINAL_COMMAND"
|
|
'''
|
|
|
|
var stopMediaNodeParams = {
|
|
subscriptionId: subscription().subscriptionId
|
|
resourceGroupName: resourceGroup().name
|
|
vmScaleSetName: '${stackName}-mediaNodeScaleSet'
|
|
storageAccountName: storageAccount.name
|
|
}
|
|
|
|
var stop_media_nodesScriptMediaTemplate = '''
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
if ! (set -o noclobber ; echo > /tmp/global.lock) ; then
|
|
exit 1 # the global.lock already exists
|
|
fi
|
|
|
|
# Execute if docker is installed
|
|
if [ -x "$(command -v docker)" ]; then
|
|
|
|
echo "Stopping media node services and waiting for termination..."
|
|
docker container kill --signal=SIGINT openvidu || true
|
|
docker container kill --signal=SIGINT ingress || true
|
|
docker container kill --signal=SIGINT egress || true
|
|
|
|
# Wait for running containers to not be openvidu, ingress or egress
|
|
while [ $(docker inspect -f '{{.State.Running}}' openvidu 2>/dev/null) == "true" ] || \
|
|
[ $(docker inspect -f '{{.State.Running}}' ingress 2>/dev/null) == "true" ] || \
|
|
[ $(docker inspect -f '{{.State.Running}}' egress 2>/dev/null) == "true" ]; do
|
|
echo "Waiting for containers to stop..."
|
|
sleep 5
|
|
done
|
|
fi
|
|
|
|
az login --identity
|
|
|
|
RESOURCE_GROUP_NAME=${resourceGroupName}
|
|
VM_SCALE_SET_NAME=${vmScaleSetName}
|
|
SUBSCRIPTION_ID=${subscriptionId}
|
|
BEFORE_INSTANCE_ID=$(curl -H Metadata:true --noproxy "*" "http://169.254.169.254/metadata/instance?api-version=2021-02-01" | jq -r '.compute.resourceId')
|
|
INSTANCE_ID=$(echo $BEFORE_INSTANCE_ID | awk -F'/' '{print $NF}')
|
|
RESOURCE_ID=/subscriptions/$SUBSCRIPTION_ID/resourcegroups/$RESOURCE_GROUP_NAME/providers/Microsoft.Compute/virtualMachineScaleSets/$VM_SCALE_SET_NAME
|
|
|
|
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
az tag update --resource-id $RESOURCE_ID --operation replace --tags "STATUS"="HEALTHY" "InstanceDeleteTime"="$TIMESTAMP" "storageAccount"="${storageAccountName}"
|
|
|
|
az vmss delete-instances --resource-group $RESOURCE_GROUP_NAME --name $VM_SCALE_SET_NAME --instance-ids $INSTANCE_ID
|
|
'''
|
|
|
|
var userDataMediaNodeTemplate = '''
|
|
#!/bin/bash -x
|
|
set -eu -o pipefail
|
|
|
|
# Introduce the scripts in the instance
|
|
# install.sh
|
|
echo ${base64install} | base64 -d > /usr/local/bin/install.sh
|
|
chmod +x /usr/local/bin/install.sh
|
|
|
|
# stop_media_nodes.sh
|
|
echo ${base64stop} | base64 -d > /usr/local/bin/stop_media_node.sh
|
|
chmod +x /usr/local/bin/stop_media_node.sh
|
|
|
|
apt-get update && apt-get install -y
|
|
apt-get install -y jq
|
|
|
|
# Install azure cli
|
|
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
|
|
|
|
az login --identity
|
|
|
|
# Protect from scale in actions
|
|
RESOURCE_GROUP_NAME=${resourceGroupName}
|
|
VM_SCALE_SET_NAME=${vmScaleSetName}
|
|
BEFORE_INSTANCE_ID=$(curl -H Metadata:true --noproxy "*" "http://169.254.169.254/metadata/instance?api-version=2021-02-01" | jq -r '.compute.resourceId')
|
|
INSTANCE_ID=$(echo $BEFORE_INSTANCE_ID | awk -F'/' '{print $NF}')
|
|
az vmss update --resource-group $RESOURCE_GROUP_NAME --name $VM_SCALE_SET_NAME --instance-id $INSTANCE_ID --protect-from-scale-in true
|
|
|
|
export HOME="/root"
|
|
|
|
# Install OpenVidu
|
|
/usr/local/bin/install.sh || { echo "[OpenVidu] error installing OpenVidu"; exit 1; }
|
|
|
|
# Start OpenVidu
|
|
systemctl start openvidu || { echo "[OpenVidu] error starting OpenVidu"; exit 1; }
|
|
'''
|
|
|
|
var installScriptMedia = reduce(
|
|
items(stringInterpolationParamsMedia),
|
|
{ value: installScriptTemplateMedia },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
var stop_media_nodesScriptMedia = reduce(
|
|
items(stopMediaNodeParams),
|
|
{ value: stop_media_nodesScriptMediaTemplate },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
var base64installMedia = base64(installScriptMedia)
|
|
var base64stopMediaNode = base64(stop_media_nodesScriptMedia)
|
|
|
|
var userDataParamsMedia = {
|
|
base64install: base64installMedia
|
|
base64stop: base64stopMediaNode
|
|
}
|
|
|
|
var userDataMediaNode = reduce(
|
|
items(userDataParamsMedia),
|
|
{ value: userDataMediaNodeTemplate },
|
|
(curr, next) => { value: replace(curr.value, '\${${next.key}}', next.value) }
|
|
).value
|
|
|
|
var base64userDataMediaNode = base64(userDataMediaNode)
|
|
param datetime string = utcNow('u')
|
|
|
|
resource openviduScaleSetMediaNode 'Microsoft.Compute/virtualMachineScaleSets@2024-07-01' = {
|
|
name: '${stackName}-mediaNodeScaleSet'
|
|
location: location
|
|
tags: {
|
|
InstanceDeleteTime: datetime
|
|
storageAccount: storageAccount.name
|
|
}
|
|
identity: { type: 'SystemAssigned' }
|
|
sku: {
|
|
name: mediaNodeInstanceType
|
|
tier: 'Standard'
|
|
capacity: initialNumberOfMediaNodes
|
|
}
|
|
properties: {
|
|
overprovision: true
|
|
upgradePolicy: {
|
|
mode: 'Automatic'
|
|
}
|
|
singlePlacementGroup: true
|
|
platformFaultDomainCount: 1
|
|
virtualMachineProfile: {
|
|
storageProfile: {
|
|
osDisk: {
|
|
createOption: 'FromImage'
|
|
managedDisk: {
|
|
storageAccountType: mediaNodeVMSettings.osDiskType
|
|
}
|
|
diskSizeGB: 50
|
|
}
|
|
imageReference: mediaNodeVMSettings.ubuntuOSVersion
|
|
}
|
|
osProfile: {
|
|
computerNamePrefix: mediaNodeVMSettings.vmName
|
|
adminUsername: adminUsername
|
|
adminPassword: adminSshKey
|
|
linuxConfiguration: mediaNodeVMSettings.linuxConfiguration
|
|
}
|
|
networkProfile: {
|
|
networkInterfaceConfigurations: [
|
|
{
|
|
name: '${stackName}-mediaNodeNetInterface'
|
|
properties: {
|
|
primary: true
|
|
ipConfigurations: [
|
|
{
|
|
name: 'ipconfigMediaNode'
|
|
properties: {
|
|
subnet: {
|
|
id: vnet_OV.properties.subnets[0].id
|
|
}
|
|
applicationSecurityGroups: [
|
|
{
|
|
id: openviduMediaNodeASG.id
|
|
}
|
|
]
|
|
publicIPAddressConfiguration: {
|
|
name: 'publicIPAddressMediaNode'
|
|
properties: {
|
|
publicIPAddressVersion: 'IPv4'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
networkSecurityGroup: {
|
|
id: openviduMediaNodeNSG.id
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
userData: base64userDataMediaNode
|
|
}
|
|
}
|
|
}
|
|
|
|
resource openviduAutoScaleSettingsMediaNode 'Microsoft.Insights/autoscaleSettings@2022-10-01' = {
|
|
name: '${stackName}-autoscaleSettings'
|
|
location: resourceGroup().location
|
|
properties: {
|
|
profiles: [
|
|
{
|
|
name: 'openvidu-medianode-autoscale'
|
|
capacity: {
|
|
minimum: string(minNumberOfMediaNodes)
|
|
maximum: string(maxNumberOfMediaNodes)
|
|
default: string(initialNumberOfMediaNodes)
|
|
}
|
|
rules: [
|
|
{
|
|
metricTrigger: {
|
|
metricName: 'Percentage CPU'
|
|
metricNamespace: 'Microsoft.Compute/virtualMachineScaleSets'
|
|
metricResourceUri: openviduScaleSetMediaNode.id
|
|
statistic: 'Average'
|
|
operator: 'GreaterThan'
|
|
threshold: scaleTargetCPU
|
|
timeAggregation: 'Average'
|
|
timeWindow: 'PT5M'
|
|
timeGrain: 'PT1M'
|
|
}
|
|
scaleAction: {
|
|
direction: 'Increase'
|
|
type: 'ChangeCount'
|
|
value: '1'
|
|
cooldown: 'PT5M'
|
|
}
|
|
}
|
|
{
|
|
metricTrigger: {
|
|
metricName: 'Percentage CPU'
|
|
metricNamespace: 'Microsoft.Compute/virtualMachineScaleSets'
|
|
metricResourceUri: openviduScaleSetMediaNode.id
|
|
statistic: 'Average'
|
|
operator: 'LessThan'
|
|
threshold: scaleTargetCPU
|
|
timeAggregation: 'Average'
|
|
timeWindow: 'PT5M'
|
|
timeGrain: 'PT1M'
|
|
}
|
|
scaleAction: {
|
|
direction: 'Decrease'
|
|
type: 'ChangeCount'
|
|
value: '1'
|
|
cooldown: 'PT5M'
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
enabled: true
|
|
targetResourceUri: openviduScaleSetMediaNode.id
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------- SCALE IN ------------------------------------------*/
|
|
|
|
resource roleAssignmentMasterNode 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
|
|
name: guid('roleAssignmentForMasterNode${openviduMasterNode4.name}')
|
|
scope: resourceGroup()
|
|
properties: {
|
|
roleDefinitionId: subscriptionResourceId(
|
|
'Microsoft.Authorization/roleDefinitions',
|
|
'b24988ac-6180-42a0-ab88-20f7382dd24c'
|
|
)
|
|
principalId: openviduMasterNode4.identity.principalId
|
|
}
|
|
}
|
|
|
|
resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
|
|
name: guid('roleAssignmentForScaleSet${openviduScaleSetMediaNode.name}')
|
|
scope: resourceGroup()
|
|
properties: {
|
|
roleDefinitionId: subscriptionResourceId(
|
|
'Microsoft.Authorization/roleDefinitions',
|
|
'b24988ac-6180-42a0-ab88-20f7382dd24c'
|
|
)
|
|
principalId: openviduScaleSetMediaNode.identity.principalId
|
|
}
|
|
}
|
|
|
|
@description('Automation Account Name to create a runbook inside it for scale in')
|
|
param automationAccountName string
|
|
|
|
module webhookModule '../../shared/webhookdeployment.json' = {
|
|
params: {
|
|
automationAccountName: automationAccountName
|
|
runbookName: 'scaleInRunbook'
|
|
webhookName: 'webhookForScaleIn'
|
|
WebhookExpiryTime: '2035-03-30T00:00:00Z'
|
|
_artifactsLocation: 'https://raw.githubusercontent.com/OpenVidu/openvidu/refs/heads/master/openvidu-deployment/pro/shared/scaleInRunbook.ps1'
|
|
}
|
|
name: 'WebhookDeployment'
|
|
}
|
|
|
|
resource actionGroupScaleIn 'Microsoft.Insights/actionGroups@2023-01-01' = {
|
|
name: 'actiongrouptest'
|
|
location: 'global'
|
|
properties: {
|
|
groupShortName: 'scaleinag'
|
|
enabled: true
|
|
automationRunbookReceivers: [
|
|
{
|
|
name: 'scalein'
|
|
useCommonAlertSchema: false
|
|
automationAccountId: webhookModule.outputs.automationAccountId
|
|
runbookName: 'scaleInRunbook'
|
|
webhookResourceId: webhookModule.outputs.webhookId
|
|
isGlobalRunbook: false
|
|
serviceUri: webhookModule.outputs.webhookUri
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
resource scaleInActivityLogRule 'Microsoft.Insights/activityLogAlerts@2020-10-01' = {
|
|
name: 'ScaleInAlertRule'
|
|
location: 'global'
|
|
properties: {
|
|
scopes: [
|
|
openviduScaleSetMediaNode.id
|
|
]
|
|
condition: {
|
|
allOf: [
|
|
{
|
|
field: 'category'
|
|
equals: 'Administrative'
|
|
}
|
|
{
|
|
field: 'operationName'
|
|
equals: 'Microsoft.Compute/virtualMachineScaleSets/write'
|
|
}
|
|
{
|
|
field: 'level'
|
|
containsAny: [
|
|
'error'
|
|
]
|
|
}
|
|
{
|
|
field: 'status'
|
|
containsAny: [
|
|
'failed'
|
|
]
|
|
}
|
|
{
|
|
field: 'caller'
|
|
equals: '42628537-ebd8-40bf-941a-dddd338e1fe9'
|
|
}
|
|
]
|
|
}
|
|
actions: {
|
|
actionGroups: [
|
|
{
|
|
actionGroupId: actionGroupScaleIn.id
|
|
}
|
|
]
|
|
}
|
|
enabled: true
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------- NETWORK -------------------------------------------*/
|
|
|
|
var isEmptyIp = publicIpAddressResourceName == ''
|
|
var turnIsEmptyIp = turnPublicIpAddressResourceName == ''
|
|
var lbName = '${stackName}-loadBalancer'
|
|
var lbFrontEndName = 'LoadBalancerFrontEnd'
|
|
var lbBackendPoolNameMasterNode = 'LoadBalancerBackEndMasterNode'
|
|
|
|
resource publicIPAddressLoadBalancer 'Microsoft.Network/publicIPAddresses@2024-05-01' = if (isEmptyIp == true) {
|
|
name: '${stackName}-publicIPAddressLoadBalancer'
|
|
location: location
|
|
sku: {
|
|
name: 'Standard'
|
|
}
|
|
properties: {
|
|
publicIPAddressVersion: 'IPv4'
|
|
publicIPAllocationMethod: 'Static'
|
|
}
|
|
}
|
|
|
|
resource publicIP_LoadBalancer_ifNotEmpty 'Microsoft.Network/publicIPAddresses@2023-11-01' existing = if (!isEmptyIp == true) {
|
|
name: publicIpAddressResourceName
|
|
}
|
|
|
|
resource publicIPAddressTurnTLSLoadBalancer 'Microsoft.Network/publicIPAddresses@2024-05-01' = if (turnTLSIsEnabled == true) {
|
|
name: '${stackName}-publicIPAddressTurnTLSLoadBalancer'
|
|
location: location
|
|
sku: {
|
|
name: 'Standard'
|
|
}
|
|
properties: {
|
|
publicIPAddressVersion: 'IPv4'
|
|
publicIPAllocationMethod: 'Static'
|
|
}
|
|
}
|
|
|
|
resource publicIP_TurnTLSLoadBalancer_ifNotEmpty 'Microsoft.Network/publicIPAddresses@2023-11-01' existing = if (!turnIsEmptyIp && turnTLSIsEnabled == true) {
|
|
name: publicIpAddressResourceName
|
|
}
|
|
|
|
resource LoadBalancer 'Microsoft.Network/loadBalancers@2024-05-01' = {
|
|
name: lbName
|
|
location: location
|
|
sku: {
|
|
name: 'Standard'
|
|
}
|
|
properties: {
|
|
frontendIPConfigurations: [
|
|
{
|
|
name: lbFrontEndName
|
|
properties: {
|
|
publicIPAddress: {
|
|
id: isEmptyIp ? publicIPAddressLoadBalancer.id : publicIP_LoadBalancer_ifNotEmpty.id
|
|
}
|
|
}
|
|
}
|
|
]
|
|
backendAddressPools: [
|
|
{
|
|
name: lbBackendPoolNameMasterNode
|
|
}
|
|
]
|
|
loadBalancingRules: [
|
|
{
|
|
name: 'HTTPSRuleforMasterNode'
|
|
properties: {
|
|
frontendIPConfiguration: {
|
|
id: resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', lbName, lbFrontEndName)
|
|
}
|
|
backendAddressPool: {
|
|
id: resourceId('Microsoft.Network/loadBalancers/backendAddressPools', lbName, lbBackendPoolNameMasterNode)
|
|
}
|
|
frontendPort: 443
|
|
backendPort: 443
|
|
enableFloatingIP: false
|
|
protocol: 'Tcp'
|
|
enableTcpReset: true
|
|
loadDistribution: 'Default'
|
|
disableOutboundSnat: true
|
|
probe: {
|
|
id: resourceId('Microsoft.Network/loadBalancers/probes', lbName, 'probeForHTTPSRuleMasterNode')
|
|
}
|
|
}
|
|
}
|
|
{
|
|
name: 'RTMPRuleforMasterNode'
|
|
properties: {
|
|
frontendIPConfiguration: {
|
|
id: resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', lbName, lbFrontEndName)
|
|
}
|
|
backendAddressPool: {
|
|
id: resourceId('Microsoft.Network/loadBalancers/backendAddressPools', lbName, lbBackendPoolNameMasterNode)
|
|
}
|
|
frontendPort: 1935
|
|
backendPort: 1945
|
|
enableFloatingIP: false
|
|
protocol: 'Tcp'
|
|
enableTcpReset: true
|
|
loadDistribution: 'Default'
|
|
disableOutboundSnat: true
|
|
probe: {
|
|
id: resourceId('Microsoft.Network/loadBalancers/probes', lbName, 'probeForRTMPRuleMasterNode')
|
|
}
|
|
}
|
|
}
|
|
{
|
|
name: 'HTTPRuleforMasterNode'
|
|
properties: {
|
|
frontendIPConfiguration: {
|
|
id: resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', lbName, lbFrontEndName)
|
|
}
|
|
backendAddressPool: {
|
|
id: resourceId('Microsoft.Network/loadBalancers/backendAddressPools', lbName, lbBackendPoolNameMasterNode)
|
|
}
|
|
frontendPort: 80
|
|
backendPort: 80
|
|
enableFloatingIP: false
|
|
protocol: 'Tcp'
|
|
enableTcpReset: true
|
|
loadDistribution: 'Default'
|
|
disableOutboundSnat: true
|
|
probe: {
|
|
id: resourceId('Microsoft.Network/loadBalancers/probes', lbName, 'probeForHTTPSRuleMasterNode')
|
|
}
|
|
}
|
|
}
|
|
]
|
|
probes: [
|
|
{
|
|
name: 'probeForHTTPSRuleMasterNode'
|
|
properties: {
|
|
protocol: 'Http'
|
|
requestPath: '/health/caddy'
|
|
port: 7880
|
|
probeThreshold: 3
|
|
intervalInSeconds: 10
|
|
numberOfProbes: 5
|
|
}
|
|
}
|
|
{
|
|
name: 'probeForRTMPRuleMasterNode'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
port: 1945
|
|
intervalInSeconds: 5
|
|
numberOfProbes: 2
|
|
}
|
|
}
|
|
]
|
|
outboundRules: []
|
|
}
|
|
}
|
|
|
|
var tlbName = '${stackName}-loadBalancer'
|
|
var tlbFrontEndName = 'LoadBalancerFrontEnd'
|
|
|
|
resource TurnTLSLoadbalancer 'Microsoft.Network/loadBalancers@2024-05-01' = if (turnTLSIsEnabled == true) {
|
|
name: tlbName
|
|
location: location
|
|
sku: {
|
|
name: 'Standard'
|
|
}
|
|
properties: {
|
|
frontendIPConfigurations: [
|
|
{
|
|
name: tlbFrontEndName
|
|
properties: {
|
|
privateIPAllocationMethod: 'Dynamic'
|
|
privateIPAddressVersion: 'IPv4'
|
|
publicIPAddress: {
|
|
id: turnIsEmptyIp ? publicIPAddressLoadBalancer.id : publicIP_TurnTLSLoadBalancer_ifNotEmpty.id
|
|
}
|
|
}
|
|
}
|
|
]
|
|
backendAddressPools: [
|
|
{
|
|
name: lbBackendPoolNameMasterNode
|
|
}
|
|
]
|
|
loadBalancingRules: [
|
|
{
|
|
name: 'TURNTLSRuleforMasterNode'
|
|
properties: {
|
|
frontendIPConfiguration: {
|
|
id: resourceId('Microsoft.Network/loadBalancers/frontendIPConfigurations', tlbName, tlbFrontEndName)
|
|
}
|
|
backendAddressPool: {
|
|
id: resourceId('Microsoft.Network/loadBalancers/backendAddressPools', tlbName, lbBackendPoolNameMasterNode)
|
|
}
|
|
frontendPort: 443
|
|
backendPort: 443
|
|
enableFloatingIP: false
|
|
protocol: 'Tcp'
|
|
enableTcpReset: true
|
|
loadDistribution: 'Default'
|
|
disableOutboundSnat: true
|
|
probe: {
|
|
id: resourceId('Microsoft.Network/loadBalancers/probes', tlbName, 'probeForHTTPSRuleMasterNode')
|
|
}
|
|
}
|
|
}
|
|
]
|
|
probes: [
|
|
{
|
|
name: 'probeForTURNTLSRuleMasterNode'
|
|
properties: {
|
|
protocol: 'Http'
|
|
requestPath: '/'
|
|
port: 443
|
|
probeThreshold: 3
|
|
intervalInSeconds: 10
|
|
numberOfProbes: 5
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
resource natGateway 'Microsoft.Network/natGateways@2021-05-01' = {
|
|
name: '${stackName}-natGateway'
|
|
location: location
|
|
sku: {
|
|
name: 'Standard'
|
|
}
|
|
properties: {
|
|
idleTimeoutInMinutes: 4
|
|
publicIpAddresses: [
|
|
{
|
|
id: natGatewayPublicIPAddress.id
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
resource natGatewayPublicIPAddress 'Microsoft.Network/publicIPAddresses@2021-05-01' = {
|
|
name: '${stackName}-publicIPnatGateway'
|
|
location: location
|
|
sku: {
|
|
name: 'Standard'
|
|
}
|
|
properties: {
|
|
publicIPAddressVersion: 'IPv4'
|
|
publicIPAllocationMethod: 'Static'
|
|
idleTimeoutInMinutes: 4
|
|
}
|
|
}
|
|
|
|
var networkSettings = {
|
|
vNetAddressPrefix: '10.0.0.0/16'
|
|
subnetAddressPrefixMaster1: '10.0.1.0/24'
|
|
subnetAddressPrefixMaster2: '10.0.2.0/24'
|
|
subnetAddressPrefixMedia: '10.0.0.0/24'
|
|
vNetName: '${stackName}-virtualNetwork'
|
|
}
|
|
|
|
resource vnet_OV 'Microsoft.Network/virtualNetworks@2023-11-01' = {
|
|
name: networkSettings.vNetName
|
|
location: location
|
|
properties: {
|
|
addressSpace: {
|
|
addressPrefixes: [
|
|
networkSettings.vNetAddressPrefix
|
|
]
|
|
}
|
|
subnets: [
|
|
{
|
|
name: 'subnetForMediaNodes'
|
|
properties: {
|
|
addressPrefix: networkSettings.subnetAddressPrefixMedia
|
|
privateEndpointNetworkPolicies: 'Disabled'
|
|
privateLinkServiceNetworkPolicies: 'Enabled'
|
|
networkSecurityGroup: {
|
|
id: openviduMediaNodeNSG.id
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
resource subnetMasterNode1 'Microsoft.Network/virtualNetworks/subnets@2023-11-01' = {
|
|
parent: vnet_OV
|
|
name: 'firstSubnetForMasterNodes'
|
|
properties: {
|
|
addressPrefix: networkSettings.subnetAddressPrefixMaster1
|
|
privateEndpointNetworkPolicies: 'Disabled'
|
|
privateLinkServiceNetworkPolicies: 'Enabled'
|
|
natGateway: {
|
|
id: natGateway.id
|
|
}
|
|
}
|
|
}
|
|
|
|
resource subnetMasterNode2 'Microsoft.Network/virtualNetworks/subnets@2023-11-01' = {
|
|
parent: vnet_OV
|
|
name: 'secondSubnetForMasterNodes'
|
|
properties: {
|
|
addressPrefix: networkSettings.subnetAddressPrefixMaster2
|
|
privateEndpointNetworkPolicies: 'Disabled'
|
|
privateLinkServiceNetworkPolicies: 'Enabled'
|
|
natGateway: {
|
|
id: natGateway.id
|
|
}
|
|
}
|
|
}
|
|
|
|
resource netInterfaceMasterNode1 'Microsoft.Network/networkInterfaces@2023-11-01' = {
|
|
name: '${stackName}-masterNodeNetInterface1'
|
|
location: location
|
|
properties: {
|
|
ipConfigurations: [
|
|
{
|
|
name: 'primaryIPConfig'
|
|
properties: {
|
|
privateIPAllocationMethod: 'Dynamic'
|
|
subnet: {
|
|
id: subnetMasterNode1.id
|
|
}
|
|
applicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
loadBalancerBackendAddressPools: [
|
|
{
|
|
id: LoadBalancer.properties.backendAddressPools[0].id
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
networkSecurityGroup: {
|
|
id: openviduMasterNodeNSG.id
|
|
}
|
|
}
|
|
}
|
|
|
|
resource netInterfaceMasterNode2 'Microsoft.Network/networkInterfaces@2023-11-01' = {
|
|
name: '${stackName}-masterNodeNetInterface2'
|
|
location: location
|
|
properties: {
|
|
ipConfigurations: [
|
|
{
|
|
name: 'primaryIPConfig'
|
|
properties: {
|
|
privateIPAllocationMethod: 'Dynamic'
|
|
subnet: {
|
|
id: subnetMasterNode2.id
|
|
}
|
|
applicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
loadBalancerBackendAddressPools: [
|
|
{
|
|
id: LoadBalancer.properties.backendAddressPools[0].id
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
networkSecurityGroup: {
|
|
id: openviduMasterNodeNSG.id
|
|
}
|
|
}
|
|
}
|
|
|
|
resource netInterfaceMasterNode3 'Microsoft.Network/networkInterfaces@2023-11-01' = {
|
|
name: '${stackName}-masterNodeNetInterface3'
|
|
location: location
|
|
properties: {
|
|
ipConfigurations: [
|
|
{
|
|
name: 'primaryIPConfig'
|
|
properties: {
|
|
privateIPAllocationMethod: 'Dynamic'
|
|
subnet: {
|
|
id: subnetMasterNode1.id
|
|
}
|
|
applicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
loadBalancerBackendAddressPools: [
|
|
{
|
|
id: LoadBalancer.properties.backendAddressPools[0].id
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
networkSecurityGroup: {
|
|
id: openviduMasterNodeNSG.id
|
|
}
|
|
}
|
|
}
|
|
|
|
resource netInterfaceMasterNode4 'Microsoft.Network/networkInterfaces@2023-11-01' = {
|
|
name: '${stackName}-masterNodeNetInterface4'
|
|
location: location
|
|
properties: {
|
|
ipConfigurations: [
|
|
{
|
|
name: 'primaryIPConfig'
|
|
properties: {
|
|
privateIPAllocationMethod: 'Dynamic'
|
|
subnet: {
|
|
id: subnetMasterNode2.id
|
|
}
|
|
applicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
loadBalancerBackendAddressPools: [
|
|
{
|
|
id: LoadBalancer.properties.backendAddressPools[0].id
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
networkSecurityGroup: {
|
|
id: openviduMasterNodeNSG.id
|
|
}
|
|
}
|
|
}
|
|
|
|
resource openviduMasterNodeNSG 'Microsoft.Network/networkSecurityGroups@2023-11-01' = {
|
|
name: '${stackName}-masterNodeNSG'
|
|
location: location
|
|
properties: {
|
|
securityRules: [
|
|
{
|
|
name: 'SSH'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceAddressPrefix: '*'
|
|
sourcePortRange: '*'
|
|
destinationAddressPrefix: '*'
|
|
destinationPortRange: '22'
|
|
access: 'Allow'
|
|
priority: 100
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
{
|
|
name: 'ProbeAPI'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceAddressPrefix: 'AzureLoadBalancer'
|
|
sourcePortRange: '*'
|
|
destinationAddressPrefix: '*'
|
|
destinationPortRange: '7880'
|
|
access: 'Allow'
|
|
priority: 500
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
{
|
|
name: 'HTTP'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceAddressPrefix: '*'
|
|
sourcePortRange: '*'
|
|
destinationAddressPrefix: '*'
|
|
destinationPortRange: '80'
|
|
access: 'Allow'
|
|
priority: 510
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
resource openviduMasterNodeASG 'Microsoft.Network/applicationSecurityGroups@2024-03-01' = {
|
|
name: '${stackName}-masterNodeASG'
|
|
location: location
|
|
}
|
|
|
|
resource loadBalancerToMasterIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'loadBalancer_to_masterNode_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceAddressPrefix: '*'
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '443'
|
|
access: 'Allow'
|
|
priority: 110
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource masterToMasterRedisIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'masterNode_to_masterNode_REDIS_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '7000'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '7001'
|
|
access: 'Allow'
|
|
priority: 120
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource mediaToMasterRedisIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'mediaNode_to_masterNode_REDIS_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMediaNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '7000'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '7001'
|
|
access: 'Allow'
|
|
priority: 130
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource masterToMasterMinioIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'masterNode_to_masterNode_MINIO_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '9100'
|
|
access: 'Allow'
|
|
priority: 140
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource masterToMasterMinioConsoleIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'masterNode_to_masterNode_MINIO_CONSOLE_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '9101'
|
|
access: 'Allow'
|
|
priority: 150
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource mediaToMasterMinioIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'mediaNode_to_masterNode_MINIO_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMediaNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '9100'
|
|
access: 'Allow'
|
|
priority: 160
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource masterToMasterMongoIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'masterNode_to_masterNode_MONGO_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '20000'
|
|
access: 'Allow'
|
|
priority: 170
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource mediaToMasterMongoIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'mediaNode_to_masterNode_MONGO_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMediaNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '20000'
|
|
access: 'Allow'
|
|
priority: 180
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource masterToMasterMimirGrpcIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'masterNode_to_masterNode_MIMIRGRPC_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '9095'
|
|
access: 'Allow'
|
|
priority: 190
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource masterToMasterMimirGossipIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'masterNode_to_masterNode_MIMIRGOSSIP_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '7946'
|
|
access: 'Allow'
|
|
priority: 200
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource mediaToMasterMimirIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'mediaNode_to_masterNode_MIMIR_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMediaNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '9009'
|
|
access: 'Allow'
|
|
priority: 210
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource masterToMasterLokiGrpcIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'masterNode_to_masterNode_LOKIGRPC_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '9096'
|
|
access: 'Allow'
|
|
priority: 220
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource masterToMasterLokiGossipIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'masterNode_to_masterNode_LOKIGOSSIP_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '7947'
|
|
access: 'Allow'
|
|
priority: 230
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource masterToMasterDashboardIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'masterNode_to_masterNode_DASHBOARD_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '5000'
|
|
access: 'Allow'
|
|
priority: 240
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource masterToMasterGrafanaIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'masterNode_to_masterNode_GRAFANA_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '3000'
|
|
access: 'Allow'
|
|
priority: 250
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource mediaToMasterLokiIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'mediaNode_to_masterNode_LOKI_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMediaNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '3100'
|
|
access: 'Allow'
|
|
priority: 260
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource masterToMasterV2CompatibilityIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'masterNode_to_masterNode_V2COMPATIBILITY_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '4443'
|
|
access: 'Allow'
|
|
priority: 270
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource mediaToMasterV2CompatibilityWebhookIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'mediaNode_to_masterNode_V2COMPATIBILITY_WEBHOOK_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMediaNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '4443'
|
|
access: 'Allow'
|
|
priority: 280
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource masterToMasterDefaultApp 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'masterNode_to_masterNode_DEFAULTAPP_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '6080'
|
|
access: 'Allow'
|
|
priority: 290
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource mediaToMasterDefaultAppWebhookIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMasterNodeNSG
|
|
name: 'mediaNode_to_masterNode_DEFAULTAPP_WEBHOOK_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMediaNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '6080'
|
|
access: 'Allow'
|
|
priority: 300
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource openviduMediaNodeNSG 'Microsoft.Network/networkSecurityGroups@2023-11-01' = {
|
|
name: '${stackName}-mediaNodeNSG'
|
|
location: location
|
|
properties: {
|
|
securityRules: [
|
|
{
|
|
name: 'SSH'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceAddressPrefix: '*'
|
|
sourcePortRange: '*'
|
|
destinationAddressPrefix: '*'
|
|
destinationPortRange: '22'
|
|
access: 'Allow'
|
|
priority: 100
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
{
|
|
name: 'TURN'
|
|
properties: {
|
|
protocol: 'Udp'
|
|
sourceAddressPrefix: '*'
|
|
sourcePortRange: '*'
|
|
destinationAddressPrefix: '*'
|
|
destinationPortRange: '443'
|
|
access: 'Allow'
|
|
priority: 110
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
{
|
|
name: 'WebRTC_over_TCP'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceAddressPrefix: '*'
|
|
sourcePortRange: '*'
|
|
destinationAddressPrefix: '*'
|
|
destinationPortRange: '7881'
|
|
access: 'Allow'
|
|
priority: 120
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
{
|
|
name: 'WebRTC_using_WHIP'
|
|
properties: {
|
|
protocol: 'Udp'
|
|
sourceAddressPrefix: '*'
|
|
sourcePortRange: '*'
|
|
destinationAddressPrefix: '*'
|
|
destinationPortRange: '7885'
|
|
access: 'Allow'
|
|
priority: 130
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
{
|
|
name: 'WebRTC_traffic_UDP'
|
|
properties: {
|
|
protocol: 'Udp'
|
|
sourceAddressPrefix: '*'
|
|
sourcePortRange: '*'
|
|
destinationAddressPrefix: '*'
|
|
destinationPortRanges: [
|
|
'50000'
|
|
'60000'
|
|
]
|
|
access: 'Allow'
|
|
priority: 140
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
resource openviduMediaNodeASG 'Microsoft.Network/applicationSecurityGroups@2024-03-01' = {
|
|
name: '${stackName}-mediaNodeASG'
|
|
location: location
|
|
}
|
|
|
|
resource loadBalancerToMediaRtmpIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMediaNodeNSG
|
|
name: 'loadBalancer_to_mediaNode_RTMP_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceAddressPrefix: 'AzureLoadBalancer'
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMediaNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '1945'
|
|
access: 'Allow'
|
|
priority: 150
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource loadBalancerToMediaHealthcheckIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMediaNodeNSG
|
|
name: 'loadBalancer_to_mediaNode_HEALTHCHECK_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceAddressPrefix: 'AzureLoadBalancer'
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMediaNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '9092'
|
|
access: 'Allow'
|
|
priority: 160
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource loadBalancerToMediaTurnTlsIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = if (turnTLSIsEnabled == true) {
|
|
parent: openviduMediaNodeNSG
|
|
name: 'loadbalancer_to_mediaNode_TURN_TLS_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceAddressPrefix: 'AzureLoadBalancer'
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMediaNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '5349'
|
|
access: 'Allow'
|
|
priority: 170
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource loadBalancerToMediaTurnTlsHealthCheckIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = if (turnTLSIsEnabled == true) {
|
|
parent: openviduMediaNodeNSG
|
|
name: 'masterNode_to_mediaNode_TURN_TLSHEALTHCHECK_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceAddressPrefix: 'AzureLoadBalancer'
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMediaNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '7880'
|
|
access: 'Allow'
|
|
priority: 180
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource masterToMediaServerIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMediaNodeNSG
|
|
name: 'masterNode_to_mediaNode_SERVER_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMediaNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '7880'
|
|
access: 'Allow'
|
|
priority: 190
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
resource masterToMediaClientIngress 'Microsoft.Network/networkSecurityGroups/securityRules@2023-11-01' = {
|
|
parent: openviduMediaNodeNSG
|
|
name: 'masterNode_to_mediaNode_CLIENT_INGRESS'
|
|
properties: {
|
|
protocol: 'Tcp'
|
|
sourceApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMasterNodeASG.id
|
|
}
|
|
]
|
|
sourcePortRange: '*'
|
|
destinationApplicationSecurityGroups: [
|
|
{
|
|
id: openviduMediaNodeASG.id
|
|
}
|
|
]
|
|
destinationPortRange: '8080'
|
|
access: 'Allow'
|
|
priority: 200
|
|
direction: 'Inbound'
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------- STORAGE ACCOUNT ----------------------------------------*/
|
|
|
|
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
|
|
name: uniqueString(resourceGroup().id)
|
|
location: resourceGroup().location
|
|
sku: {
|
|
name: 'Standard_LRS'
|
|
}
|
|
kind: 'StorageV2'
|
|
properties: {
|
|
accessTier: 'Cool'
|
|
supportsHttpsTrafficOnly: true
|
|
}
|
|
}
|
|
|
|
resource blobContainerScaleIn 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-01-01' = {
|
|
name: '${storageAccount.name}/default/automation-locks'
|
|
properties: {
|
|
publicAccess: 'None'
|
|
}
|
|
}
|
|
|
|
@description('Name of the bucket where OpenVidu will store the recordings. If not specified, a default bucket will be created.')
|
|
param containerName string = ''
|
|
|
|
var isEmptyContainerName = containerName == ''
|
|
|
|
resource blobContainer 'Microsoft.Storage/storageAccounts/blobServices/containers@2023-01-01' = {
|
|
name: isEmptyContainerName
|
|
? '${storageAccount.name}/default/openvidu-appdata'
|
|
: '${storageAccount.name}/default/${containerName}'
|
|
properties: {
|
|
publicAccess: 'None'
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------- OUTPUTS -------------------------------------------*/
|