1. Introducción
Descripción general
En este lab, implementarás una instancia completamente persistente y de nivel de producción de OpenClaw, un framework de agentes de IA de código abierto, en instancias de Cloud Run con infraestructura como código declarativa (Terraform). Aprovisionarás instancias de Cloud Run con el recurso google_cloud_run_v2_instance del proveedor google, activarás Google Cloud Storage a través de Cloud Storage FUSE para conservar el estado del espacio de trabajo del agente, administrarás las credenciales de la API de forma segura con Google Cloud Secret Manager y, además, interactuarás con tu agente de IA a través de la IU web integrada de OpenClaw con SSH nativo de instancias de Cloud Run para vincular dispositivos de forma segura.
Antes de comenzar, puedes explorar la documentación de OpenClaw para familiarizarte con la arquitectura, las herramientas y los flujos de trabajo de los agentes de OpenClaw.
Actividades
- Define toda tu infraestructura de forma declarativa en Terraform (
main.tf), incluidas las APIs, las cuentas de servicio, las vinculaciones de IAM, los secretos, los buckets de almacenamiento y las instancias de Cloud Run. - Implementa OpenClaw 2.0 o una versión posterior (
ghcr.io/openclaw/openclaw:latest) congoogle_cloud_run_v2_instance. - Genera y almacena automáticamente credenciales de puerta de enlace segura en Secret Manager.
- Activa un bucket de Cloud Storage a través de Cloud Storage FUSE y sincroniza
/home/node/.openclawpara obtener un estado duradero, un espacio de trabajo y persistencia de SQLite. - Usa
gcloud beta run instances sshpara autenticar y aprobar las solicitudes de vinculación de dispositivos del navegador en la IU web de OpenClaw Control. - (Opcional) Configura un canal de mensajería (Telegram o WhatsApp).
- (Opcional) Amplía las capacidades de tu agente agregando habilidades personalizadas a Cloud Storage.
Qué aprenderás
- Cómo declarar e implementar instancias de Cloud Run con Terraform
- Cómo configurar activaciones de volúmenes de Cloud Storage FUSE en Terraform.
- Cómo insertar de forma segura secretos de Secret Manager como variables de entorno en instancias de Cloud Run
- Cómo administrar la autenticación de dispositivos de OpenClaw 2.0 con SSH nativo de instancias de Cloud Run.
- Cómo ejecutar cargas de trabajo de agentes persistentes y de larga duración en instancias de Cloud Run
2. Configuración y requisitos
Configuración del proyecto de Google Cloud
- Accede a la consola de Google Cloud.
- Crea o selecciona un proyecto de Google Cloud.
- Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.
Abre Cloud Shell
Activa Google Cloud Shell desde la barra de herramientas superior de la consola de Cloud. Cloud Shell incluye Terraform y el SDK de Google Cloud preinstalados.
Configura el proyecto y la región
Establece el ID del proyecto y la región como variables de entorno, y configura gcloud:
export PROJECT_ID=<YOUR_PROJECT_ID>
export REGION=<YOUR_REGION>
gcloud config set project $PROJECT_ID
gcloud config get project
Instala los componentes beta de gcloud
Asegúrate de que el componente beta esté instalado (obligatorio para SSH y transmisión de registros de instancias de Cloud Run):
gcloud components install beta --quiet
gcloud components update
Verifica Terraform
Confirma que Terraform esté instalado y cumpla con los requisitos de versión:
terraform version
Deberías ver Terraform v1.5.0 o una versión posterior.
3. Configura integraciones de mensajería (Telegram o WhatsApp) (opcional)
Puedes conectar OpenClaw a Telegram o WhatsApp. Elige la opción A o la opción B a continuación.
Opción A: Configuración del bot de Telegram
- Abre Telegram y busca
@BotFather. - Envía el comando
/newboty sigue las instrucciones para especificar un nombre y un nombre de usuario para el bot. - Copia el token de la API de HTTP generado (p.ej.,
123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ). - Busca
@userinfoboten Telegram, envía/starty copia tu ID de usuario numérico (p.ej.,8035936176).
Proporcionarás estos valores como variables de entrada de Terraform en tu archivo terraform.tfvars.
Opción B: Configuración de WhatsApp
- Obtén tu número de teléfono personal de WhatsApp en formato internacional sin espacios ni símbolos (p.ej.,
+15551234567). - OpenClaw se conecta a través de la política de lista de entidades permitidas del canal de WhatsApp.
4. Define la infraestructura en Terraform
Declararemos toda nuestra infraestructura en Terraform. Esto incluye habilitar las APIs de Google Cloud necesarias, crear la cuenta de servicio dedicada y los roles de IAM, generar y almacenar secretos en Secret Manager, aprovisionar el bucket de estado de Cloud Storage, generar la configuración de openclaw.json y, luego, implementar la instancia de Cloud Run.
1. Crea un directorio de Terraform
En Cloud Shell, crea un directorio para tus archivos de Terraform y navega hasta él:
mkdir openclaw-terraform && cd openclaw-terraform
2. Crear main.tf
Crea un archivo llamado main.tf. Esta configuración usa el proveedor de Google para definir todos los componentes de la infraestructura:
terraform {
required_version = ">= 1.5.0"
required_providers {
google = {
source = "hashicorp/google"
version = ">= 8.8.0"
}
random = {
source = "hashicorp/random"
version = ">= 3.5.0"
}
}
}
provider "google" {
project = var.project_id
region = var.region
}
# 1. Enable Required APIs
resource "google_project_service" "services" {
for_each = toset([
"run.googleapis.com",
"secretmanager.googleapis.com",
"storage.googleapis.com",
"generativelanguage.googleapis.com",
"compute.googleapis.com"
])
project = var.project_id
service = each.key
disable_on_destroy = false
}
# 2. Dedicated Service Account
resource "google_service_account" "openclaw_sa" {
account_id = "openclaw-sa"
display_name = "OpenClaw Service Account"
depends_on = [google_project_service.services]
}
# 3. Secret Manager: Gateway Password
resource "random_password" "gateway_password" {
length = 32
special = false
}
resource "google_secret_manager_secret" "gateway_password" {
secret_id = "openclaw-gateway-password"
replication {
auto {}
}
depends_on = [google_project_service.services]
}
resource "google_secret_manager_secret_version" "gateway_password" {
secret = google_secret_manager_secret.gateway_password.id
secret_data = random_password.gateway_password.result
}
resource "google_secret_manager_secret_iam_member" "sa_gateway_password" {
secret_id = google_secret_manager_secret.gateway_password.id
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_service_account.openclaw_sa.email}"
}
# 4. Secret Manager: Gemini API Key
resource "google_secret_manager_secret" "gemini_api_key" {
secret_id = "gemini-api-key"
replication {
auto {}
}
depends_on = [google_project_service.services]
}
resource "google_secret_manager_secret_version" "gemini_api_key" {
secret = google_secret_manager_secret.gemini_api_key.id
secret_data = var.gemini_api_key
}
resource "google_secret_manager_secret_iam_member" "sa_gemini_api_key" {
secret_id = google_secret_manager_secret.gemini_api_key.id
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_service_account.openclaw_sa.email}"
}
# 5. Optional Secret Manager: Telegram Bot Token
resource "google_secret_manager_secret" "telegram_bot_token" {
count = var.telegram_bot_token != "" ? 1 : 0
secret_id = "telegram-bot-token"
replication {
auto {}
}
depends_on = [google_project_service.services]
}
resource "google_secret_manager_secret_version" "telegram_bot_token" {
count = var.telegram_bot_token != "" ? 1 : 0
secret = google_secret_manager_secret.telegram_bot_token[0].id
secret_data = var.telegram_bot_token
}
resource "google_secret_manager_secret_iam_member" "sa_telegram_bot_token" {
count = var.telegram_bot_token != "" ? 1 : 0
secret_id = google_secret_manager_secret.telegram_bot_token[0].id
role = "roles/secretmanager.secretAccessor"
member = "serviceAccount:${google_service_account.openclaw_sa.email}"
}
# 6. Cloud Storage Bucket for State Persistence
resource "google_storage_bucket" "openclaw_state" {
name = "openclaw-state-${var.project_id}"
location = var.region
uniform_bucket_level_access = true
force_destroy = true
depends_on = [google_project_service.services]
}
resource "google_storage_bucket_iam_member" "sa_storage" {
bucket = google_storage_bucket.openclaw_state.name
role = "roles/storage.objectUser"
member = "serviceAccount:${google_service_account.openclaw_sa.email}"
}
# 7. Upload openclaw.json to Cloud Storage Root
resource "google_storage_bucket_object" "openclaw_config" {
name = "openclaw.json"
bucket = google_storage_bucket.openclaw_state.name
content = jsonencode({
gateway = {
mode = "local"
port = 18789
trustedProxies = ["127.0.0.1", "::1", "169.254.0.0/16", "10.0.0.0/8"]
bind = "lan"
auth = {
password = "$${OPENCLAW_GATEWAY_PASSWORD}"
}
controlUi = {
allowedOrigins = ["*"]
enabled = true
}
}
memory = {
search = {
provider = "gemini"
}
}
agents = {
defaults = {
model = {
primary = "google/gemini-3.1-pro-preview"
}
sandbox = {
mode = "off"
}
}
}
skills = {
load = {
extraDirs = ["/mnt/openclaw/skills"]
}
}
channels = {
telegram = {
enabled = var.telegram_bot_token != ""
defaultAccount = "default"
accounts = {
default = {
enabled = var.telegram_bot_token != ""
dmPolicy = "allowlist"
allowFrom = var.telegram_user_id != "" ? [var.telegram_user_id] : []
}
}
}
}
plugins = {
entries = {
google = { enabled = true }
telegram = { enabled = var.telegram_bot_token != "" }
}
}
})
}
# 8. Cloud Run Instance
resource "google_cloud_run_v2_instance" "openclaw" {
name = "openclaw-instance"
location = var.region
ingress = "INGRESS_TRAFFIC_ALL"
invoker_iam_disabled = true
restart_policy = "ON_FAILURE"
service_account = google_service_account.openclaw_sa.email
containers {
image = "ghcr.io/openclaw/openclaw:latest"
args = [
"/bin/sh",
"-c",
"cp /mnt/openclaw/openclaw.json /home/node/.openclaw/ && exec node /app/openclaw.mjs gateway"
]
ports {
container_port = 18789
}
resources {
limits = {
cpu = "4"
memory = "4Gi"
}
}
env {
name = "GEMINI_API_KEY"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.gemini_api_key.secret_id
version = "latest"
}
}
}
env {
name = "OPENCLAW_GATEWAY_PASSWORD"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.gateway_password.secret_id
version = "latest"
}
}
}
dynamic "env" {
for_each = toset(var.telegram_bot_token != "" ? ["telegram"] : [])
content {
name = "TELEGRAM_BOT_TOKEN"
value_source {
secret_key_ref {
secret = google_secret_manager_secret.telegram_bot_token[0].secret_id
version = "latest"
}
}
}
}
volume_mounts {
name = "openclaw-storage"
mount_path = "/mnt/openclaw"
}
}
volumes {
name = "openclaw-storage"
gcs {
bucket = google_storage_bucket.openclaw_state.name
read_only = false
mount_options = ["uid=1000", "gid=1000", "file-mode=0700", "dir-mode=0700"]
}
}
depends_on = [
google_project_service.services,
google_storage_bucket_object.openclaw_config,
google_secret_manager_secret_version.gateway_password,
google_secret_manager_secret_version.gemini_api_key,
google_secret_manager_secret_iam_member.sa_gateway_password,
google_secret_manager_secret_iam_member.sa_gemini_api_key,
google_storage_bucket_iam_member.sa_storage
]
}
3. Crear variables.tf
Crea un archivo llamado variables.tf para definir las variables de entrada:
variable "project_id" {
type = string
description = "Google Cloud Project ID"
}
variable "region" {
type = string
default = "us-west1"
description = "Google Cloud Region for Cloud Run and Storage"
}
variable "gemini_api_key" {
type = string
sensitive = true
description = "Gemini API Key from Google AI Studio"
}
variable "telegram_bot_token" {
type = string
default = ""
sensitive = true
description = "(Optional) Telegram Bot HTTP API Token"
}
variable "telegram_user_id" {
type = string
default = ""
description = "(Optional) Telegram User ID for allowlist policy"
}
4. Crear outputs.tf
Crea un archivo llamado outputs.tf para exponer la URL de la instancia implementada, la contraseña de la puerta de enlace generada y el nombre del bucket de almacenamiento:
output "instance_url" {
description = "Public URL for OpenClaw Cloud Run Instance"
value = google_cloud_run_v2_instance.openclaw.urls[0]
}
output "gateway_password" {
description = "Generated OpenClaw Gateway Password"
value = random_password.gateway_password.result
sensitive = true
}
output "storage_bucket" {
description = "Cloud Storage bucket persisting OpenClaw state"
value = google_storage_bucket.openclaw_state.name
}
5. Crear terraform.tfvars
Para obtener una clave de API de Gemini, haz lo siguiente:
- Visita Google AI Studio y accede con tu Cuenta de Google.
- Haz clic en Crear clave de API y selecciona tu proyecto de Google Cloud.
- Copia la clave de API generada.
Crea un archivo llamado terraform.tfvars con las coordenadas de tu proyecto:
project_id = "YOUR_PROJECT_ID"
region = "YOUR_REGION"
gemini_api_key = "YOUR_GEMINI_API_KEY"
# Optional: Uncomment if configuring Telegram
# telegram_bot_token = "YOUR_TELEGRAM_BOT_TOKEN"
# telegram_user_id = "YOUR_TELEGRAM_USER_ID"
5. Implementa infraestructura con Terraform
1. Inicializa y aplica
Inicializa el directorio de trabajo de Terraform y descarga los complementos del proveedor:
terraform init
Implementa la infraestructura:
terraform apply
Cuando se te solicite, revisa los recursos planificados y escribe yes para confirmar.
2. Extrae los resultados de la implementación
Exporta la URL de la instancia y la contraseña de la puerta de enlace generada desde el estado de Terraform:
export INSTANCE_URL=$(terraform output -raw instance_url)
export GATEWAY_PASSWORD=$(terraform output -raw gateway_password)
echo "Instance URL: ${INSTANCE_URL}"
echo "Gateway Password: ${GATEWAY_PASSWORD}"
6. Interactúa a través de la IU web y autentícate con SSH para Cloud Run
OpenClaw 2.0 y versiones posteriores aplican la autenticación criptográfica de dispositivos. Cuando te conectas desde un navegador nuevo, la puerta de enlace genera una solicitud de vinculación que apruebas directamente a través de SSH nativo de las instancias de Cloud Run.
1. Abre la IU de control de OpenClaw
- Abre la
$INSTANCE_URLen tu navegador web. - Cuando se te solicite la autenticación, ingresa la contraseña de la puerta de enlace (
$GATEWAY_PASSWORD). - Como esta es una sesión nueva del navegador, la IU de OpenClaw Control muestra un mensaje de vinculación de dispositivos pendiente con un ID de solicitud (por ejemplo:
b56143fc-1654-49da-a1d8-5d40479ddc66). Copia este ID de solicitud.
2. Establece una conexión SSH a la instancia de Cloud Run
En Cloud Shell, inicia una shell interactiva segura en tu instancia en ejecución:
gcloud beta run instances ssh openclaw-instance --region=${REGION}
3. Aprobar la vinculación de dispositivos
Dentro de la sesión de SSH, aprueba la solicitud de tu navegador:
openclaw devices approve <REQUEST_ID> --password ${GATEWAY_PASSWORD}
4. Envía instrucciones a tu agente (instancias en acción)
Una vez que se apruebe, tu navegador se conectará de inmediato al panel de control de OpenClaw.
- Para probar tu agente de OpenClaw, envía una instrucción en la IU de chat, como
"Hello". - Para probar el ciclo de vida de larga duración y el almacenamiento persistente de la instancia de Cloud Run, pídele a tu agente de OpenClaw que realice una tarea autónoma programada. Por ejemplo, pídele que supervise un repositorio de GitHub en busca de versiones y que redacte un resumen:
Check the GitHub repository openclaw/openclaw every hour for the next 24 hours. Track any new releases, merged pull requests, and breaking changes. Save a structured markdown digest titled `daily-release-digest.md` to your workspace, and notify me in this chat with a summary whenever a new release is detected. - Debido a que el estado de OpenClaw, los archivos del espacio de trabajo y las bases de datos de SQLite se conservan directamente en Cloud Storage a través de Cloud Storage FUSE, la tarea programada, el historial de conversaciones y los archivos de resumen generados sobreviven a los reinicios de instancias y las actualizaciones de contenedores.
7. Verifica las integraciones de canales de mensajería (opcional)
Si configuraste Telegram o WhatsApp en los pasos de configuración opcionales anteriores, puedes verificar la entrega de mensajes:
- Verifica los registros de la instancia en Cloud Shell:
gcloud beta run instances logs read openclaw-instance --region ${REGION} --limit 20 - Abre Telegram (o WhatsApp) y envía un mensaje (p.ej.,
/startoHello OpenClaw!). - El bot autenticará tu ID de usuario con la lista de entidades permitidas en
openclaw.jsony responderá con Gemini.
8. Supervisa e inspecciona los registros de instancias
Las instancias de Cloud Run capturan stdout y stderr de tu contenedor y las transmiten directamente a Google Cloud Logging. Puedes usar Cloud Shell o la consola de Cloud para supervisar el tráfico de la puerta de enlace y, además, inspeccionar las ejecuciones de las herramientas del agente en tiempo real.
1. Lee los registros de instancias recientes
Para recuperar las entradas de registro recientes de la instancia en Cloud Shell, haz lo siguiente:
gcloud beta run instances logs read openclaw-instance \
--region ${REGION} \
--limit 50
2. Firmas de registro clave que se deben observar
Cuando observes tu agente en ejecución, busca los siguientes eventos clave de registro del entorno de ejecución:
[gateway] ready: Confirma que la puerta de enlace HTTP y WebSocket de OpenClaw se inicializó y está escuchando en el puerto 18789.[gateway] agent model: ...: Muestra el modelo de Gemini activo (p.ej.,google/gemini-3.1-pro-previewogoogle/gemini-3.5-flash).[agents/tool-policy]: Muestra las herramientas permitidas o restringidas según tu política.[agent/embedded]: Realiza un seguimiento de la ejecución y la invocación de herramientas por parte del agente.
3. Inspecciona los registros en la consola de Google Cloud
También puedes ver y filtrar los registros con el Explorador de registros en la consola de Cloud:
resource.type="cloud_run_instance"
resource.labels.instance_name="openclaw-instance"
9. Extiende tu agente con habilidades (opcional)
OpenClaw admite habilidades, que son paquetes de capacidades modulares que enseñan a tu agente flujos de trabajo específicos, herramientas de CLI especializadas e instrucciones específicas del dominio.
Cómo funcionan las habilidades
Cada habilidad es un directorio que contiene un archivo SKILL.md. Comienza con metadatos iniciales en formato YAML que especifican los metadatos (name y description), seguidos de instrucciones en Markdown:
---
name: summarize-logs
description: Summarize Cloud Run error logs into actionable bullet points.
---
# Log Summarizer Skill
When asked to analyze or summarize logs:
1. Parse error stack traces and group similar errors by frequency.
2. Identify root causes such as memory limits, timeouts, or permission errors.
3. Propose concrete remediation steps.
name: Es el identificador de la habilidad (también se puede llamar directamente como un comando de barra, por ejemplo,/summarize-logs).description: Le indica al modelo de OpenClaw cuándo debe invocar automáticamente esta habilidad en una conversación natural.
Agrega una habilidad personalizada a tu bucket de Cloud Storage
Como tu bucket de Cloud Storage está activado en /mnt/openclaw y configurado en skills.load.extraDirs, las habilidades que se colocan en gs://${BUCKET_NAME}/skills/ se cargan y se conservan automáticamente en los reinicios de la instancia:
- Recupera el nombre de tu bucket:
export BUCKET_NAME=$(terraform output -raw storage_bucket) - Crea un directorio de habilidades local:
mkdir -p my-skill cat << 'EOF' > my-skill/SKILL.md --- name: summarize-logs description: Summarize Cloud Run error logs into actionable bullet points. --- # Log Summarizer Skill When asked to analyze or summarize logs, group errors by frequency and suggest actionable fixes. EOF - Sube la habilidad a Cloud Storage:
gcloud storage cp -r my-skill gs://${BUCKET_NAME}/skills/ - Usa la habilidad en Chat:
- Regresa a la IU web de OpenClaw Control.
- Ahora puedes enviar instrucciones a tu agente con
/summarize-logso hacer preguntas en lenguaje natural que coincidan con la descripción de la habilidad.
10. Limpieza
Para evitar que se apliquen cargos continuos a tu cuenta de Google Cloud por los recursos que usaste en este codelab, puedes destruir toda la infraestructura aprovisionada en un solo paso con Terraform:
- Asegúrate de estar en el directorio
openclaw-terraform:cd openclaw-terraform - Destruye todos los recursos:
terraform destroy - Cuando se te solicite, revisa los recursos que se quitarán y escribe
yespara confirmar. Terraform borrará de forma limpia la instancia de Cloud Run, los secretos de Secret Manager, las vinculaciones de políticas de IAM, la cuenta de servicio y el bucket de Cloud Storage.
11. Conclusión
¡Felicitaciones! Implementaste correctamente una instancia segura y completamente persistente de OpenClaw en instancias de Cloud Run con Terraform declarativo, respaldada por la persistencia de estado de Cloud Storage, la seguridad de credenciales de Secret Manager y el SSH nativo de instancias de Cloud Run para la autenticación segura de dispositivos.