From 1efc9850a5a76ae70ef056ec259f9eb4632c4555 Mon Sep 17 00:00:00 2001 From: cruizba Date: Sat, 6 Sep 2025 20:39:44 +0200 Subject: [PATCH] openvidu-deployment: Elastic - Remove letsencrypt email and use sslip.io if domain is not defined. --- .../pro/elastic/aws/cf-openvidu-elastic.yaml | 131 +++++++++++------- 1 file changed, 81 insertions(+), 50 deletions(-) diff --git a/openvidu-deployment/pro/elastic/aws/cf-openvidu-elastic.yaml b/openvidu-deployment/pro/elastic/aws/cf-openvidu-elastic.yaml index d99ca5ab..064dae2a 100644 --- a/openvidu-deployment/pro/elastic/aws/cf-openvidu-elastic.yaml +++ b/openvidu-deployment/pro/elastic/aws/cf-openvidu-elastic.yaml @@ -5,17 +5,17 @@ Parameters: CertificateType: 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) + [selfsigned] Not recommended for production use. Just for testing purposes or development environments. + [owncert] Valid for productions environments. If you don't have a FQDN, sslip.io will be used. 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. Type: String AllowedValues: - selfsigned - - owncert - letsencrypt - Default: selfsigned + - owncert + Default: letsencrypt PublicElasticIP: Type: String @@ -37,10 +37,6 @@ Parameters: Description: "If certificate type is 'owncert', this parameter will be used to specify the private certificate" Type: String - LetsEncryptEmail: - Description: "If certificate type is 'letsencrypt', this email will be used for Let's Encrypt notifications" - Type: String - AdditionalInstallFlags: Description: Additional optional flags to pass to the OpenVidu installer (comma-separated, e.g., "--flag1=value, --flag2"). Type: String @@ -386,6 +382,15 @@ Parameters: Metadata: 'AWS::CloudFormation::Interface': ParameterGroups: + - Label: + default: SSH Access configuration + Parameters: + - KeyName + - Label: + default: OpenVidu Elastic configuration + Parameters: + - OpenViduLicense + - RTCEngine - Label: default: Domain and SSL certificate configuration Parameters: @@ -394,18 +399,11 @@ Metadata: - DomainName - OwnPublicCertificate - OwnPrivateCertificate - - LetsEncryptEmail - - Label: - default: OpenVidu Elastic configuration - Parameters: - - OpenViduLicense - - RTCEngine - Label: default: EC2 Instance configuration Parameters: - MasterNodeInstanceType - MediaNodeInstanceType - - KeyName - AmiId - Label: default: Media Nodes Autoscaling Group configuration @@ -437,7 +435,7 @@ Metadata: Conditions: PublicElasticIPPresent: !Not [ !Equals [!Ref PublicElasticIP, ""] ] - TurnTLSIsEnabled: !Not [!Equals [!Ref TurnDomainName, ""] ] + PublicElasticIPAbsent: !Equals [!Ref PublicElasticIP, ""] CreateRecordingsBucket: !Equals [!Ref S3AppDataBucketName, ""] Resources: @@ -452,32 +450,33 @@ Resources: # All the values are initialized by the master node SecretString: | { - "ALL_SECRETS_GENERATED": "false", + "OPENVIDU_URL": "none", + "MEET_INITIAL_ADMIN_USER": "none", + "MEET_INITIAL_ADMIN_PASSWORD": "none", + "MEET_INITIAL_API_KEY": "none", + "LIVEKIT_URL": "none", + "LIVEKIT_API_KEY": "none", + "LIVEKIT_API_SECRET": "none", + "DASHBOARD_URL": "none", + "GRAFANA_URL": "none", + "MINIO_URL": "none", "DOMAIN_NAME": "none", "LIVEKIT_TURN_DOMAIN_NAME": "none", - "LETSENCRYPT_EMAIL": "none", "OPENVIDU_PRO_LICENSE": "none", "OPENVIDU_RTC_ENGINE": "none", "REDIS_PASSWORD": "none", "MONGO_ADMIN_USERNAME": "none", "MONGO_ADMIN_PASSWORD": "none", "MONGO_REPLICA_SET_KEY": "none", - "MINIO_URL": "none", "MINIO_ACCESS_KEY": "none", "MINIO_SECRET_KEY": "none", - "DASHBOARD_URL": "none", "DASHBOARD_ADMIN_USERNAME": "none", "DASHBOARD_ADMIN_PASSWORD": "none", - "GRAFANA_URL": "none", "GRAFANA_ADMIN_USERNAME": "none", "GRAFANA_ADMIN_PASSWORD": "none", - "LIVEKIT_API_KEY": "none", - "LIVEKIT_API_SECRET": "none", - "MEET_INITIAL_ADMIN_USER": "none", - "MEET_INITIAL_ADMIN_PASSWORD": "none", - "MEET_INITIAL_API_KEY": "none", "OPENVIDU_VERSION": "none", - "ENABLED_MODULES": "none" + "ENABLED_MODULES": "none", + "ALL_SECRETS_GENERATED": "false" } S3AppDataBucketResource: @@ -633,6 +632,12 @@ Resources: - !Ref OpenViduMediaNodeRole InstanceProfileName: !Sub openvidu-elastic-media-instance-profile-${AWS::Region}-${AWS::StackName} + NewEIP: + Type: 'AWS::EC2::EIP' + Condition: PublicElasticIPAbsent + Properties: + InstanceId: !Ref OpenViduMasterNode + IMDSv2LaunchTemplateMasterNode: Type: AWS::EC2::LaunchTemplate Properties: @@ -671,11 +676,11 @@ Resources: unzip \ jq \ wget - wget https://github.com/mikefarah/yq/releases/download/${!YQ_VERSION}/yq_linux_amd64.tar.gz -O - |\ - tar xz && mv yq_linux_amd64 /usr/bin/yq + wget https://github.com/mikefarah/yq/releases/download/${!YQ_VERSION}/yq_linux_$(dpkg --print-architecture).tar.gz -O - |\ + tar xz && mv yq_linux_$(dpkg --print-architecture) /usr/bin/yq # Install aws-cli - curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" + curl "https://awscli.amazonaws.com/awscli-exe-linux-$(uname -m).zip" -o "awscliv2.zip" unzip -qq awscliv2.zip ./aws/install rm -rf awscliv2.zip aws @@ -685,8 +690,12 @@ Resources: # Configure Domain and other parameters if [[ "${DomainName}" == '' ]]; then + [ ! -d "/usr/share/openvidu" ] && mkdir -p /usr/share/openvidu PublicHostname=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-hostname) - DOMAIN=$PublicHostname + RANDOM_DOMAIN_STRING=$(tr -dc 'a-z' < /dev/urandom | head -c 8) + DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PublicHostname" | cut -d'.' -f1 | sed 's/^ec2-//').sslip.io + TURN_DOMAIN_NAME_SSLIP_IO="turn-$RANDOM_DOMAIN_STRING-$(echo "$PublicHostname" | cut -d'.' -f1 | sed 's/^ec2-//').sslip.io" + echo $RANDOM_DOMAIN_STRING > /usr/share/openvidu/random-domain-string else DOMAIN=${DomainName} fi @@ -786,7 +795,12 @@ Resources: fi # Turn with TLS - if [[ "${TurnDomainName}" != '' ]]; then + if [[ "${!TURN_DOMAIN_NAME_SSLIP_IO}" != '' ]]; then + LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "${!TURN_DOMAIN_NAME_SSLIP_IO}") + COMMON_ARGS+=( + "--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME" + ) + elif [[ "${TurnDomainName}" != '' ]]; then LIVEKIT_TURN_DOMAIN_NAME=$(/usr/local/bin/store_secret.sh save LIVEKIT_TURN_DOMAIN_NAME "${TurnDomainName}") COMMON_ARGS+=( "--turn-domain-name=$LIVEKIT_TURN_DOMAIN_NAME" @@ -799,10 +813,8 @@ Resources: "--certificate-type=selfsigned" ) elif [[ "${CertificateType}" == "letsencrypt" ]]; then - LETSENCRYPT_EMAIL=$(/usr/local/bin/store_secret.sh save LETSENCRYPT_EMAIL "${LetsEncryptEmail}") CERT_ARGS=( "--certificate-type=letsencrypt" - "--letsencrypt-email=$LETSENCRYPT_EMAIL" ) else # Download owncert files @@ -888,17 +900,22 @@ Resources: if [[ "${DomainName}" == '' ]]; then PublicHostname=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-hostname) - DOMAIN=$PublicHostname + RANDOM_DOMAIN_STRING=$(cat /usr/share/openvidu/random-domain-string) + DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PublicHostname" | cut -d'.' -f1 | sed 's/^ec2-//').sslip.io else DOMAIN=${DomainName} fi # Generate URLs + OPENVIDU_URL="https://${!DOMAIN}/" + LIVEKIT_URL="wss://${!DOMAIN}/" DASHBOARD_URL="https://${!DOMAIN}/dashboard/" GRAFANA_URL="https://${!DOMAIN}/grafana/" MINIO_URL="https://${!DOMAIN}/minio-console/" # Update shared secret + SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"OPENVIDU_URL": "'"$OPENVIDU_URL"'" }')" + SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"LIVEKIT_URL": "'"$LIVEKIT_URL"'" }')" SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"DOMAIN_NAME": "'"$DOMAIN"'"}')" SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"DASHBOARD_URL": "'"$DASHBOARD_URL"'" }')" SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"GRAFANA_URL": "'"$GRAFANA_URL"'" }')" @@ -931,9 +948,10 @@ Resources: # Replace DOMAIN_NAME export DOMAIN=$(echo $SHARED_SECRET | jq -r .DOMAIN_NAME) - if [[ $DOMAIN == *"compute.amazonaws.com"* ]] || [[ -z $DOMAIN ]]; then + if [[ $DOMAIN == *"sslip.io"* ]] || [[ -z $DOMAIN ]]; then PublicHostname=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-hostname) - DOMAIN=$PublicHostname + RANDOM_DOMAIN_STRING=$(cat /usr/share/openvidu/random-domain-string) + DOMAIN=openvidu-$RANDOM_DOMAIN_STRING-$(echo "$PublicHostname" | cut -d'.' -f1 | sed 's/^ec2-//').sslip.io fi if [[ -n "$DOMAIN" ]]; then sed -i "s/DOMAIN_NAME=.*/DOMAIN_NAME=$DOMAIN/" "${!CLUSTER_CONFIG_DIR}/openvidu.env" @@ -943,15 +961,15 @@ Resources: # Replace LIVEKIT_TURN_DOMAIN_NAME export LIVEKIT_TURN_DOMAIN_NAME=$(echo $SHARED_SECRET | jq -r .LIVEKIT_TURN_DOMAIN_NAME) + if [[ $LIVEKIT_TURN_DOMAIN_NAME == *"sslip.io"* ]] || [[ -z $LIVEKIT_TURN_DOMAIN_NAME ]]; then + PublicHostname=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/public-hostname) + RANDOM_DOMAIN_STRING=$(cat /usr/share/openvidu/random-domain-string) + LIVEKIT_TURN_DOMAIN_NAME="turn-$RANDOM_DOMAIN_STRING-$(echo "$PublicHostname" | cut -d'.' -f1 | sed 's/^ec2-//').sslip.io" + fi 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=$(echo $SHARED_SECRET | jq -r .LETSENCRYPT_EMAIL) - sed -i "s/LETSENCRYPT_EMAIL=.*/LETSENCRYPT_EMAIL=$LETSENCRYPT_EMAIL/" "${!CLUSTER_CONFIG_DIR}/openvidu.env" - fi - # Replace rest of the values sed -i "s/REDIS_PASSWORD=.*/REDIS_PASSWORD=$(echo $SHARED_SECRET | jq -r .REDIS_PASSWORD)/" "${!MASTER_NODE_CONFIG_DIR}/master_node.env" sed -i "s/OPENVIDU_RTC_ENGINE=.*/OPENVIDU_RTC_ENGINE=$(echo $SHARED_SECRET | jq -r .OPENVIDU_RTC_ENGINE)/" "${!CLUSTER_CONFIG_DIR}/openvidu.env" @@ -973,9 +991,13 @@ Resources: sed -i "s/ENABLED_MODULES=.*/ENABLED_MODULES=$(echo $SHARED_SECRET | jq -r .ENABLED_MODULES)/" "${!CLUSTER_CONFIG_DIR}/openvidu.env" # Update URLs in secret + OPENVIDU_URL="https://${!DOMAIN}/" + LIVEKIT_URL="wss://${!DOMAIN}/" DASHBOARD_URL="https://${!DOMAIN}/dashboard/" GRAFANA_URL="https://${!DOMAIN}/grafana/" MINIO_URL="https://${!DOMAIN}/minio-console/" + SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"OPENVIDU_URL": "'"$OPENVIDU_URL"'" }')" + SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"LIVEKIT_URL": "'"$LIVEKIT_URL"'" }')" SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"DOMAIN_NAME": "'"$DOMAIN"'" }')" SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"DASHBOARD_URL": "'"$DASHBOARD_URL"'" }')" SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"GRAFANA_URL": "'"$GRAFANA_URL"'" }')" @@ -1003,11 +1025,6 @@ Resources: CLUSTER_CONFIG_DIR="${!INSTALL_DIR}/config/cluster" MASTER_NODE_CONFIG_DIR="${!INSTALL_DIR}/config/node" - - if [[ ${CertificateType} == "letsencrypt" ]]; then - SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"LETSENCRYPT_EMAIL": "'"$(/usr/local/bin/get_value_from_config.sh LETSENCRYPT_EMAIL "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')" - fi - # Update shared secret SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"REDIS_PASSWORD": "'"$(/usr/local/bin/get_value_from_config.sh REDIS_PASSWORD "${!MASTER_NODE_CONFIG_DIR}/master_node.env")"'"}')" SHARED_SECRET="$(echo "$SHARED_SECRET" | jq '. + {"DOMAIN_NAME": "'"$(/usr/local/bin/get_value_from_config.sh DOMAIN_NAME "${!CLUSTER_CONFIG_DIR}/openvidu.env")"'"}')" @@ -1167,7 +1184,14 @@ Resources: apt-get update && apt-get install -y \ python3-pip \ ec2-instance-connect - pip3 install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz + + # Detect Ubuntu version and install cfn-bootstrap accordingly + UBUNTU_VERSION=$(lsb_release -rs | cut -d. -f1) + if [ "$UBUNTU_VERSION" -ge 24 ]; then + python3 -m pip install --break-system-packages https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz + else + python3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz + fi cfn-init --region ${AWS::Region} --stack ${AWS::StackId} --resource OpenViduMasterNode @@ -1193,7 +1217,7 @@ Resources: /usr/local/bin/check_app_ready.sh # sending the finish call - /usr/local/bin/cfn-signal -e $? --stack ${AWS::StackId} --resource WaitCondition --region ${AWS::Region} + cfn-signal -e $? --stack ${AWS::StackId} --resource WaitCondition --region ${AWS::Region} BlockDeviceMappings: - DeviceName: /dev/sda1 @@ -1397,7 +1421,14 @@ Resources: apt-get update && apt-get install -y \ python3-pip \ ec2-instance-connect - pip3 install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz + + # Detect Ubuntu version and install cfn-bootstrap accordingly + UBUNTU_VERSION=$(lsb_release -rs | cut -d. -f1) + if [ "$UBUNTU_VERSION" -ge 24 ]; then + python3 -m pip install --break-system-packages https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz + else + python3 -m pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-py3-latest.tar.gz + fi cfn-init --region ${AWS::Region} --stack ${AWS::StackId} --resource OpenViduMediaNodeLaunchTemplate