mirror of https://github.com/OpenVidu/openvidu.git
460 lines
15 KiB
HCL
460 lines
15 KiB
HCL
# Enable APIs the deployment needs
|
|
resource "google_project_service" "compute_api" { service = "compute.googleapis.com" }
|
|
resource "google_project_service" "secretmanager_api" { service = "secretmanager.googleapis.com" }
|
|
resource "google_project_service" "storage_api" { service = "storage.googleapis.com" }
|
|
|
|
resource "random_id" "bucket_suffix" { byte_length = 3 }
|
|
|
|
# GCS bucket (conditional)
|
|
resource "google_storage_bucket" "bucket" {
|
|
count = 1
|
|
name = local.isEmpty ? "openvidu-appdata" : var.bucketName
|
|
location = var.region
|
|
force_destroy = false
|
|
uniform_bucket_level_access = true
|
|
}
|
|
|
|
# Secret Manager secret that stores deployment info and seed secrets
|
|
resource "google_secret_manager_secret" "openvidu_secret_manager" {
|
|
secret_id = "openvidu-${var.region}-${var.stackName}"
|
|
replication {
|
|
auto {}
|
|
}
|
|
}
|
|
|
|
resource "google_secret_manager_secret_version" "openvidu_version" {
|
|
secret = google_secret_manager_secret.openvidu.id
|
|
secret_data = jsonencode({
|
|
DOMAIN_NAME = "none",
|
|
LIVEKIT_TURN_DOMAIN_NAME = "none",
|
|
LETSENCRYPT_EMAIL = "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_ADMIN_USER = "none",
|
|
MEET_ADMIN_SECRET = "none",
|
|
MEET_API_KEY = "none",
|
|
ENABLED_MODULES = "none"
|
|
})
|
|
}
|
|
|
|
# Service account for the instance
|
|
resource "google_service_account" "openvidu_sa" {
|
|
account_id = lower("openvidu-sa-${substr(var.stackName, 0, 12)}")
|
|
display_name = "OpenVidu instance service account"
|
|
}
|
|
|
|
# IAM bindings for the service account so the instance can access Secret Manager and GCS
|
|
resource "google_project_iam_member" "sa_secret_accessor" {
|
|
project = var.projectId
|
|
role = "roles/secretmanager.secretAccessor"
|
|
member = "serviceAccount:${google_service_account.openvidu_sa.email}"
|
|
}
|
|
|
|
resource "google_project_iam_member" "sa_storage_object_admin" {
|
|
project = var.projectId
|
|
role = "roles/storage.objectAdmin"
|
|
member = "serviceAccount:${google_service_account.openvidu_sa.email}"
|
|
}
|
|
|
|
# Firewall (similar ports to your AWS SG)
|
|
resource "google_compute_firewall" "openvidu_fw" {
|
|
name = lower("openvidu-fw-${var.stackName}")
|
|
network = "default"
|
|
|
|
allow {
|
|
protocol = "tcp"
|
|
ports = ["22", "80", "443", "1935", "7881"]
|
|
}
|
|
allow {
|
|
protocol = "udp"
|
|
ports = ["443", "7885", "50000-60000"]
|
|
}
|
|
|
|
source_ranges = ["0.0.0.0/0"]
|
|
target_tags = ["openvidu-server-${var.stackName}"]
|
|
}
|
|
|
|
# Static external IP (optional)
|
|
resource "google_compute_address" "openvidu_ip" {
|
|
count = var.publicStaticIp == "" ? 0 : 1
|
|
name = "openvidu-eip-${var.stackName}"
|
|
address = var.publicStaticIp
|
|
}
|
|
|
|
# Compute instance for OpenVidu
|
|
resource "google_compute_instance" "openvidu" {
|
|
name = "openvidu-${var.stackName}"
|
|
machine_type = var.instanceType
|
|
zone = var.zone
|
|
|
|
tags = ["openvidu-server-${var.stackName}"]
|
|
|
|
boot_disk {
|
|
initialize_params {
|
|
image = "projects/ubuntu-os-cloud/global/images/family/ubuntu-2204-lts"
|
|
size = 200
|
|
type = "pd-standard"
|
|
}
|
|
}
|
|
|
|
network_interface {
|
|
network = "default"
|
|
access_config {
|
|
nat_ip = length(google_compute_address.openvidu_ip) > 0 ? google_compute_address.openvidu_ip[0].address : null
|
|
}
|
|
}
|
|
|
|
metadata = {
|
|
# metadata values are accessible from the instance
|
|
# secret_name = google_secret_manager_secret.openvidu.secret_id
|
|
region = var.region
|
|
stackName = var.stackName
|
|
certificateType = var.certificateType
|
|
domainName = var.domainName
|
|
letsEncryptEmail = var.letsEncryptEmail
|
|
ownPublicCertificate = var.ownPublicCertificate
|
|
ownPrivateCertificate = var.ownPrivateCertificate
|
|
additional_install_flags = var.additional_install_flags
|
|
turnDomainName = var.turnDomainName
|
|
turnOwnPublicCertificate = var.turnOwnPublicCertificate
|
|
turnOwnPrivateCertificate = var.turnOwnPrivateCertificate
|
|
s3_bucket_name = var.bucketName == "" ? "openvidu-appdata" : var.bucketName
|
|
}
|
|
|
|
service_account {
|
|
email = google_service_account.openvidu_sa.email
|
|
scopes = ["https://www.googleapis.com/auth/cloud-platform"]
|
|
}
|
|
|
|
metadata_startup_script = local.user_data
|
|
|
|
labels = {
|
|
stack = var.stackName
|
|
}
|
|
}
|
|
|
|
# ------------------------- local values -------------------------
|
|
|
|
locals {
|
|
isEmpty = var.bucketName == ""
|
|
install_script = <<-EOF
|
|
#!/bin/bash -x
|
|
OPENVIDU_VERSION=3.3.0 #CHANGE
|
|
DOMAIN=
|
|
YQ_VERSION=v4.44.5
|
|
|
|
apt-get update && apt-get install -y \
|
|
curl \
|
|
unzip \
|
|
jq \
|
|
wget \
|
|
ca-certificates \
|
|
gnupg \
|
|
lsb-release \
|
|
openssl
|
|
|
|
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
|
|
|
|
# Configure domain
|
|
if [[ -z "${var.domainName}" || "${var.domainName}" == "none" ]]; then
|
|
# Use external IP
|
|
EXTERNAL_IP=$(curl -s ifconfig.co || true)
|
|
DOMAIN="$$EXTERNAL_IP"
|
|
else
|
|
DOMAIN="${var.domainName}"
|
|
fi
|
|
|
|
DOMAIN="$(/usr/local/bin/store_secret.sh save DOMAIN_NAME "$$DOMAIN")"
|
|
|
|
# Store usernames and generate random passwords
|
|
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)"
|
|
MEET_ADMIN_USER="$(/usr/local/bin/store_secret.sh save MEET_ADMIN_USER "meetadmin")"
|
|
MEET_ADMIN_SECRET="$(/usr/local/bin/store_secret.sh generate MEET_ADMIN_SECRET)"
|
|
MEET_API_KEY="$(/usr/local/bin/store_secret.sh generate MEET_API_KEY)"
|
|
ENABLED_MODULES="$(/usr/local/bin/store_secret.sh save ENABLED_MODULES "observability,openviduMeet")"
|
|
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)"
|
|
|
|
# Build install command and args
|
|
INSTALL_COMMAND="sh <(curl -fsSL http://get.openvidu.io/community/singlenode/$$OPENVIDU_VERSION/install.sh)"
|
|
|
|
# Common arguments
|
|
COMMON_ARGS=(
|
|
"--no-tty"
|
|
"--install"
|
|
"--environment=gcp"
|
|
"--deployment-type=single_node"
|
|
"--domain-name=$$DOMAIN"
|
|
"--enabled-modules='$$ENABLED_MODULES'"
|
|
"--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"
|
|
"--meet-admin-user=$$MEET_ADMIN_USER"
|
|
"--meet-admin-password=$$MEET_ADMIN_SECRET"
|
|
"--meet-api-key=$$MEET_API_KEY"
|
|
"--livekit-api-key=$$LIVEKIT_API_KEY"
|
|
"--livekit-api-secret=$$LIVEKIT_API_SECRET"
|
|
)
|
|
|
|
# Include additional installer flags (trimmed)
|
|
if [[ "${var.additionalInstallFlags}" != "" ]]; then
|
|
IFS=',' read -ra EXTRA_FLAGS <<< "${var.additionalInstallFlags}"
|
|
for extra_flag in "$${EXTRA_FLAGS[@]}"; do
|
|
# Trim whitespace around each flag
|
|
extra_flag="$(echo -e "$${extra_flag}" | sed -e 's/^[ \t]*//' -e 's/[ \t]*$//')"
|
|
if [[ "$$extra_flag" != "" ]]; then
|
|
COMMON_ARGS+=("$$extra_flag")
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Turn with TLS
|
|
if [[ "${var.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"
|
|
)
|
|
fi
|
|
|
|
# Certificate arguments
|
|
if [[ "${var.certificateType}" == "selfsigned" ]]; then
|
|
CERT_ARGS=(
|
|
"--certificate-type=selfsigned"
|
|
)
|
|
elif [[ "${var.certificateType}" == "letsencrypt" ]]; then
|
|
LETSENCRYPT_EMAIL=$(/usr/local/bin/store_secret.sh save LETSENCRYPT_EMAIL "${var.letsEncryptEmail}")
|
|
CERT_ARGS=(
|
|
"--certificate-type=letsencrypt"
|
|
"--letsencrypt-email=${var.letsEncryptEmail}"
|
|
)
|
|
else
|
|
# Download owncert files
|
|
mkdir -p /tmp/owncert
|
|
wget -O /tmp/owncert/fullchain.pem ${var.ownPublicCertificate}
|
|
wget -O /tmp/owncert/privkey.pem ${var.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 [[ "${var.turnDomainName}" != '' ]]; then
|
|
# Download owncert files
|
|
mkdir -p /tmp/owncert-turn
|
|
wget -O /tmp/owncert-turn/fullchain.pem ${var.turnOwnPublicCertificate}
|
|
wget -O /tmp/owncert-turn/privkey.pem ${var.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
|
|
|
|
# Final command
|
|
FINAL_COMMAND="$INSTALL_COMMAND $(printf "%s " "$${COMMON_ARGS[@]}") $(printf "%s " "$${CERT_ARGS[@]}")"
|
|
|
|
# Execute installation
|
|
exec bash -c "$FINAL_COMMAND"
|
|
EOF
|
|
|
|
after_install_script = <<-EOF
|
|
EOF
|
|
|
|
update_config_from_secret_script = <<-EOF
|
|
EOF
|
|
|
|
update_secret_from_config_script = <<-EOF
|
|
EOF
|
|
|
|
get_value_from_config_script = <<-EOF
|
|
EOF
|
|
|
|
store_secret_script = <<-EOF
|
|
#!/bin/bash
|
|
set -e
|
|
|
|
# Authenticate using instance service account
|
|
gcloud auth activate-service-account --key-file=/dev/null 2>/dev/null || true
|
|
|
|
# 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}"
|
|
gcloud secrets versions add $SECRET_KEY_NAME --data-file=<(echo -n "$RANDOM_PASSWORD") 2>/dev/null || echo "$RANDOM_PASSWORD" | gcloud secrets versions add $SECRET_KEY_NAME --data-file=-
|
|
if [[ $? -ne 0 ]]; then
|
|
echo "Error generating secret"
|
|
fi
|
|
echo "$RANDOM_PASSWORD"
|
|
elif [[ "$MODE" == "save" ]]; then
|
|
SECRET_KEY_NAME="$2"
|
|
SECRET_VALUE="$3"
|
|
gcloud secrets versions add $SECRET_KEY_NAME --data-file=<(echo -n "$SECRET_VALUE") 2>/dev/null || echo "$SECRET_VALUE" | gcloud secrets versions add $SECRET_KEY_NAME --data-file=-
|
|
if [[ $? -ne 0 ]]; then
|
|
echo "Error generating secret"
|
|
fi
|
|
echo "$SECRET_VALUE"
|
|
else
|
|
exit 1
|
|
fi
|
|
EOF
|
|
|
|
check_app_ready_script = <<-EOF
|
|
#!/bin/bash
|
|
while true; do
|
|
HTTP_STATUS=$(curl -Ik http://localhost:7880 | head -n1 | awk '{print $2}')
|
|
if [ $HTTP_STATUS == 200 ]; then
|
|
break
|
|
fi
|
|
sleep 5
|
|
done
|
|
EOF
|
|
|
|
restart_script = <<-EOF
|
|
#!/bin/bash -x
|
|
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
|
|
EOF
|
|
|
|
user_data = <<-EOF
|
|
#!/bin/bash -x
|
|
set -eu -o pipefail
|
|
|
|
# install.sh
|
|
cat > /usr/local/bin/install.sh << 'INSTALL_EOF'
|
|
${local.install_script}
|
|
INSTALL_EOF
|
|
chmod +x /usr/local/bin/install.sh
|
|
|
|
# after_install.sh
|
|
cat > /usr/local/bin/after_install.sh << 'AFTER_INSTALL_EOF'
|
|
${local.after_install_script}
|
|
AFTER_INSTALL_EOF
|
|
chmod +x /usr/local/bin/after_install.sh
|
|
|
|
# update_config_from_secret.sh
|
|
cat > /usr/local/bin/update_config_from_secret.sh << 'UPDATE_CONFIG_EOF'
|
|
${local.update_config_from_secret_script}
|
|
UPDATE_CONFIG_EOF
|
|
chmod +x /usr/local/bin/update_config_from_secret.sh
|
|
|
|
# update_secret_from_config.sh
|
|
cat > /usr/local/bin/update_secret_from_config.sh << 'UPDATE_SECRET_EOF'
|
|
${local.update_secret_from_config_script}
|
|
UPDATE_SECRET_EOF
|
|
chmod +x /usr/local/bin/update_secret_from_config.sh
|
|
|
|
# get_value_from_config.sh
|
|
cat > /usr/local/bin/get_value_from_config.sh << 'GET_VALUE_EOF'
|
|
${local.get_value_from_config_script}
|
|
GET_VALUE_EOF
|
|
chmod +x /usr/local/bin/get_value_from_config.sh
|
|
|
|
# store_secret.sh
|
|
cat > /usr/local/bin/store_secret.sh << 'STORE_SECRET_EOF'
|
|
${local.store_secret_script}
|
|
STORE_SECRET_EOF
|
|
chmod +x /usr/local/bin/store_secret.sh
|
|
|
|
# check_app_ready.sh
|
|
cat > /usr/local/bin/check_app_ready.sh << 'CHECK_APP_EOF'
|
|
${local.check_app_ready_script}
|
|
CHECK_APP_EOF
|
|
chmod +x /usr/local/bin/check_app_ready.sh
|
|
|
|
# restart.sh
|
|
cat > /usr/local/bin/restart.sh << 'RESTART_EOF'
|
|
${local.restart_script}
|
|
RESTART_EOF
|
|
chmod +x /usr/local/bin/restart.sh
|
|
|
|
apt-get update && apt-get install -y
|
|
|
|
# Install google cli
|
|
if ! command -v gcloud >/dev/null 2>&1; then
|
|
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
|
|
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
|
|
apt-get update && apt-get install -y google-cloud-cli
|
|
fi
|
|
|
|
# Authenticate with gcloud using instance service account
|
|
gcloud auth activate-service-account --key-file=/dev/null 2>/dev/null || true
|
|
gcloud config set account $(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email" -H "Metadata-Flavor: Google")
|
|
|
|
export HOME="/root"
|
|
|
|
# Install OpenVidu
|
|
/usr/local/bin/install.sh || { echo "[OpenVidu] error installing OpenVidu"; exit 1; }
|
|
|
|
#Config blob storage
|
|
# /usr/local/bin/config_blobStorage.sh || { echo "[OpenVidu] error configuring Blob Storage"; 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
|
|
|
|
# Wait for the app
|
|
/usr/local/bin/check_app_ready.sh
|
|
EOF
|
|
|
|
}
|