1. Introduction
Présentation
Dans cet atelier, vous allez déployer une instance de production entièrement persistante d'OpenClaw, un framework d'agent IA Open Source, sur des instances Cloud Run à l'aide d'une infrastructure as code déclarative (Terraform). Vous allez provisionner des instances Cloud Run à l'aide de la ressource google_cloud_run_v2_instance du fournisseur google, installer Google Cloud Storage via Cloud Storage FUSE pour conserver l'état de l'espace de travail de l'agent, gérer les identifiants d'API de manière sécurisée à l'aide de Google Cloud Secret Manager et interagir avec votre agent IA via l'interface utilisateur Web intégrée d'OpenClaw à l'aide de SSH natif des instances Cloud Run pour une association d'appareils sécurisée.
Avant de commencer, vous pouvez explorer la documentation OpenClaw pour vous familiariser avec l'architecture, les outils et les workflows d'agent d'OpenClaw.
Objectifs de l'atelier
- Définissez l'intégralité de votre infrastructure de manière déclarative dans Terraform (
main.tf), y compris les API, les comptes de service, les liaisons IAM, les secrets, les buckets de stockage et les instances Cloud Run. - Déployez OpenClaw 2.0 ou version ultérieure (
ghcr.io/openclaw/openclaw:latest) à l'aide degoogle_cloud_run_v2_instance. - Générez et stockez automatiquement des identifiants de passerelle sécurisée dans Secret Manager.
- Installez un bucket Cloud Storage via Cloud Storage FUSE et synchronisez
/home/node/.openclawpour l'état durable, l'espace de travail et la persistance SQLite. - Utilisez
gcloud beta run instances sshpour authentifier et approuver les demandes d'association d'appareils du navigateur dans l'interface utilisateur Web de contrôle OpenClaw. - (Facultatif) Configurez un canal de messagerie (Telegram ou WhatsApp).
- (Facultatif) Étendez les capacités de votre agent en ajoutant des compétences personnalisées à Cloud Storage.
Points abordés
- Déclarer et déployer des instances Cloud Run à l'aide de Terraform
- Découvrez comment configurer des montages de volume Cloud Storage FUSE dans Terraform.
- Injecter de manière sécurisée des secrets Secret Manager en tant que variables d'environnement dans des instances Cloud Run
- Gérer l'authentification des appareils OpenClaw 2.0 à l'aide de SSH natif pour les instances Cloud Run.
- Découvrez comment exécuter des charges de travail d'agent persistantes et de longue durée sur des instances Cloud Run.
2. Préparation
Configuration du projet GCP
- Connectez-vous à la console Google Cloud.
- Créez ou sélectionnez un projet Google Cloud.
- Assurez-vous que la facturation est activée pour votre projet Google Cloud.
Ouvrir Cloud Shell
Activez Google Cloud Shell dans la barre d'outils supérieure de la console Cloud. Terraform et le SDK Google Cloud sont préinstallés dans Cloud Shell.
Définir le projet et la région
Définissez l'ID de votre projet et votre région en tant que variables d'environnement, puis configurez gcloud :
export PROJECT_ID=<YOUR_PROJECT_ID>
export REGION=<YOUR_REGION>
gcloud config set project $PROJECT_ID
gcloud config get project
Installer les composants gcloud beta
Assurez-vous que le composant beta est installé (requis pour SSH et le flux de journaux des instances Cloud Run) :
gcloud components install beta --quiet
gcloud components update
Vérifier Terraform
Vérifiez que Terraform est installé et qu'il répond aux exigences de version :
terraform version
Vous devriez voir Terraform v1.5.0 ou une version ultérieure.
3. (Facultatif) Configurer les intégrations de messagerie (Telegram ou WhatsApp)
Vous pouvez connecter OpenClaw à Telegram ou WhatsApp. Choisissez l'option A ou l'option B ci-dessous.
Option A : Configurer un bot Telegram
- Ouvrez Telegram et recherchez
@BotFather. - Envoyez la commande
/newbotet suivez les instructions pour spécifier un nom de bot et un nom d'utilisateur. - Copiez le jeton d'API HTTP généré (par exemple,
123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ). - Recherchez
@userinfobotsur Telegram, envoyez/start, puis copiez votre ID utilisateur numérique (par exemple,8035936176).
Vous fournirez ces valeurs en tant que variables d'entrée Terraform dans votre fichier terraform.tfvars.
Option B : Configuration de WhatsApp
- Obtenez votre numéro de téléphone WhatsApp personnel au format international, sans espaces ni symboles (par exemple,
+15551234567). - OpenClaw se connecte via la règle de liste d'autorisation du canal WhatsApp.
4. Définir l'infrastructure dans Terraform
Nous allons déclarer l'intégralité de notre infrastructure dans Terraform. Cela inclut l'activation des API Google Cloud requises, la création du compte de service dédié et des rôles IAM, la génération et le stockage des secrets dans Secret Manager, le provisionnement du bucket d'état Cloud Storage, la génération de la configuration openclaw.json et le déploiement de l'instance Cloud Run.
1. Créer un répertoire Terraform
Dans Cloud Shell, créez un répertoire pour vos fichiers Terraform et accédez-y :
mkdir openclaw-terraform && cd openclaw-terraform
2. Créer main.tf
Créez un fichier nommé main.tf. Cette configuration utilise le fournisseur Google pour définir tous les composants d'infrastructure :
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. Créer variables.tf
Créez un fichier nommé variables.tf pour définir les variables d'entrée :
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. Créer outputs.tf
Créez un fichier nommé outputs.tf pour exposer l'URL de l'instance déployée, le mot de passe de la passerelle généré et le nom du bucket de stockage :
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. Créer terraform.tfvars
Pour obtenir une clé API Gemini :
- Accédez à Google AI Studio et connectez-vous avec votre compte Google.
- Cliquez sur Créer une clé API, puis sélectionnez votre projet Google Cloud.
- Copiez la clé API générée.
Créez un fichier nommé terraform.tfvars avec les coordonnées de votre projet :
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. Déployer une infrastructure avec Terraform
1. Initialiser et appliquer
Initialisez le répertoire de travail Terraform et téléchargez les plug-ins du fournisseur :
terraform init
Déployez l'infrastructure :
terraform apply
Lorsque vous y êtes invité, examinez les ressources planifiées et saisissez yes pour confirmer.
2. Extraire les sorties du déploiement
Exportez l'URL de l'instance et le mot de passe de la passerelle généré à partir de l'état 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. Interagir via l'UI Web et s'authentifier via Cloud Run SSH
OpenClaw 2.0 ou version ultérieure applique l'authentification cryptographique des appareils. Lors de la connexion à partir d'un nouveau navigateur, la passerelle génère une demande d'association que vous approuvez directement via le SSH natif des instances Cloud Run.
1. Ouvrir l'interface utilisateur de contrôle OpenClaw
- Ouvrez
$INSTANCE_URLdans votre navigateur Web. - Lorsque vous êtes invité à vous authentifier, saisissez le mot de passe de votre passerelle (
$GATEWAY_PASSWORD). - Comme il s'agit d'une nouvelle session de navigateur, l'interface utilisateur de contrôle OpenClaw affiche une invite d'association d'appareil en attente avec un ID de requête (par exemple :
b56143fc-1654-49da-a1d8-5d40479ddc66). Copiez cet ID de requête.
2. Se connecter en SSH à l'instance Cloud Run
Dans Cloud Shell, démarrez un shell interactif sécurisé dans votre instance en cours d'exécution :
gcloud beta run instances ssh openclaw-instance --region=${REGION}
3. Approuver l'association d'appareils
Dans la session SSH, approuvez la requête de votre navigateur :
openclaw devices approve <REQUEST_ID> --password ${GATEWAY_PASSWORD}
4. Envoyer un prompt à votre agent (instances en action)
Une fois la demande approuvée, votre navigateur se connecte immédiatement au tableau de bord de contrôle OpenClaw.
- Testez votre agent OpenClaw en envoyant une requête dans l'UI de chat, par exemple
"Hello". - Pour tester le cycle de vie de longue durée et le stockage persistant de l'instance Cloud Run, demandez à votre agent OpenClaw d'effectuer une tâche autonome planifiée. Par exemple, demandez-lui de surveiller un dépôt GitHub pour détecter les nouvelles versions et de rédiger un résumé :
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. - Comme l'état d'OpenClaw, les fichiers de l'espace de travail et les bases de données SQLite sont conservés directement dans Cloud Storage via Cloud Storage FUSE, la tâche planifiée, l'historique des conversations et les fichiers de résumé générés survivent aux redémarrages d'instance et aux mises à niveau de conteneur.
7. (Facultatif) Vérifier les intégrations de canaux de messagerie
Si vous avez configuré Telegram ou WhatsApp lors des étapes de configuration facultatives ci-dessus, vous pouvez vérifier la distribution des messages :
- Vérifiez les journaux de l'instance dans Cloud Shell :
gcloud beta run instances logs read openclaw-instance --region ${REGION} --limit 20 - Ouvrez Telegram (ou WhatsApp) et envoyez un message (par exemple,
/startouHello OpenClaw!). - Le bot authentifiera votre ID utilisateur par rapport à la liste d'autorisation dans
openclaw.jsonet répondra à l'aide de Gemini.
8. Surveiller et inspecter les journaux d'instance
Les instances Cloud Run capturent les flux stdout et stderr de votre conteneur et les transmettent directement à Google Cloud Logging. Vous pouvez utiliser Cloud Shell ou la console Cloud pour surveiller le trafic de la passerelle et inspecter les exécutions des outils de l'agent en temps réel.
1. Lire les journaux d'instance récents
Pour récupérer les entrées de journal récentes de l'instance dans Cloud Shell :
gcloud beta run instances logs read openclaw-instance \
--region ${REGION} \
--limit 50
2. Signatures de journaux clés à observer
Lorsque vous observez votre agent en cours d'exécution, recherchez les événements de journal d'exécution clés suivants :
[gateway] ready: confirme que la passerelle HTTP et WebSocket OpenClaw a été initialisée et qu'elle écoute sur le port 18789.[gateway] agent model: ...: affiche le modèle Gemini actif (par exemple,google/gemini-3.1-pro-previewougoogle/gemini-3.5-flash).[agents/tool-policy]: affiche les outils autorisés ou limités par votre règle.[agent/embedded]: trace l'exécution et l'appel d'outils par l'agent.
3. Inspecter les journaux dans la console Google Cloud
Vous pouvez également afficher et filtrer les journaux à l'aide de l'Explorateur de journaux dans la console Cloud :
resource.type="cloud_run_instance"
resource.labels.instance_name="openclaw-instance"
9. (Facultatif) Étendre votre agent avec des compétences
OpenClaw est compatible avec les compétences, des packages de fonctionnalités modulaires qui enseignent à votre agent des workflows spécifiques, des outils CLI spécialisés et des instructions spécifiques à un domaine.
Fonctionnement des compétences
Chaque compétence est un répertoire contenant un fichier SKILL.md. Il commence par un frontmatter YAML spécifiant les métadonnées (name et description), suivi d'instructions 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: identifiant de la compétence (également appelable directement en tant que commande à barre oblique, par exemple/summarize-logs).description: indique au modèle d'OpenClaw quand appeler automatiquement cette compétence dans une conversation naturelle.
Ajouter une compétence personnalisée à votre bucket Cloud Storage
Comme votre bucket Cloud Storage est installé sur /mnt/openclaw et configuré dans skills.load.extraDirs, les compétences placées sous gs://${BUCKET_NAME}/skills/ sont automatiquement chargées et conservées lors des redémarrages de l'instance :
- Récupérez le nom de votre bucket :
export BUCKET_NAME=$(terraform output -raw storage_bucket) - Créer un répertoire de compétences 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 - Importez la compétence dans Cloud Storage :
gcloud storage cp -r my-skill gs://${BUCKET_NAME}/skills/ - Utiliser la compétence dans Chat :
- Revenez à l'interface utilisateur Web OpenClaw Control.
- Vous pouvez désormais envoyer des requêtes à votre agent à l'aide de
/summarize-logsou poser des questions en langage naturel correspondant à la description de la compétence.
10. Effectuer un nettoyage
Pour éviter que les ressources utilisées dans cet atelier de programmation soient facturées en permanence sur votre compte Google Cloud, vous pouvez détruire toute l'infrastructure provisionnée en une seule étape à l'aide de Terraform :
- Assurez-vous d'être dans le répertoire
openclaw-terraform:cd openclaw-terraform - Détruisez toutes les ressources :
terraform destroy - Lorsque vous y êtes invité, examinez les ressources à supprimer et saisissez
yespour confirmer. Terraform supprimera proprement l'instance Cloud Run, les secrets Secret Manager, les liaisons de stratégie IAM, le compte de service et le bucket Cloud Storage.
11. Conclusion
Félicitations ! Vous avez déployé une instance OpenClaw sécurisée et entièrement persistante sur des instances Cloud Run à l'aide de Terraform déclaratif, avec la persistance d'état Cloud Storage, la sécurité des identifiants Secret Manager et le SSH natif des instances Cloud Run pour une authentification sécurisée des appareils.