Cara Men-deploy OpenClaw di Instance Cloud Run dengan Terraform

1. Pengantar

Ringkasan

Di lab ini, Anda akan men-deploy instance OpenClaw—framework agen AI open source—yang sepenuhnya persisten dan berstandar produksi ke Instance Cloud Run menggunakan Infrastructure as Code (Terraform) deklaratif. Anda akan menyediakan Instance Cloud Run menggunakan resource google_cloud_run_v2_instance dari penyedia google, memasang Google Cloud Storage melalui Cloud Storage FUSE untuk mempertahankan status ruang kerja agen, mengelola kredensial API dengan aman menggunakan Google Cloud Secret Manager, dan berinteraksi dengan agen AI Anda melalui UI Web bawaan OpenClaw menggunakan SSH native Instance Cloud Run untuk penyambungan perangkat yang aman.

Sebelum memulai, Anda dapat mempelajari Dokumentasi OpenClaw untuk memahami arsitektur, alat, dan alur kerja agen OpenClaw.

Yang akan Anda lakukan

  • Tentukan seluruh infrastruktur Anda secara deklaratif di Terraform (main.tf), termasuk API, akun layanan, binding IAM, secret, bucket penyimpanan, dan Instance Cloud Run.
  • Deploy OpenClaw 2.0+ (ghcr.io/openclaw/openclaw:latest) menggunakan google_cloud_run_v2_instance.
  • Membuat dan menyimpan kredensial gateway aman secara otomatis di Secret Manager.
  • Memasang bucket Cloud Storage melalui Cloud Storage FUSE dan menyinkronkan /home/node/.openclaw untuk status tahan lama, ruang kerja, dan persistensi SQLite.
  • Gunakan gcloud beta run instances ssh untuk mengautentikasi dan menyetujui permintaan penyambungan perangkat browser ke UI Web OpenClaw Control.
  • (Opsional) Konfigurasikan saluran pesan (Telegram atau WhatsApp).
  • (Opsional) Perluas kemampuan agen Anda dengan menambahkan Kemampuan kustom ke Cloud Storage.

Yang akan Anda pelajari

  • Cara mendeklarasikan dan men-deploy Instance Cloud Run menggunakan Terraform.
  • Cara mengonfigurasi pemasangan volume Cloud Storage FUSE di Terraform.
  • Cara memasukkan secret Secret Manager dengan aman sebagai variabel lingkungan ke dalam Instance Cloud Run.
  • Cara mengelola autentikasi perangkat OpenClaw 2.0 menggunakan SSH native Instance Cloud Run.
  • Cara menjalankan workload agen persisten yang berjalan lama di Instance Cloud Run.

2. Penyiapan dan Persyaratan

Penyiapan Project GCP

  1. Login ke Konsol Google Cloud.
  2. Membuat atau memilih Project Google Cloud.
  3. Pastikan penagihan diaktifkan untuk project Google Cloud Anda.

Buka Cloud Shell

Aktifkan Google Cloud Shell dari toolbar atas Konsol Cloud. Cloud Shell menyertakan Terraform dan Google Cloud SDK yang telah diinstal sebelumnya.

Menetapkan Project & Region

Tetapkan project ID dan region Anda sebagai variabel lingkungan dan konfigurasi gcloud:

export PROJECT_ID=<YOUR_PROJECT_ID>
export REGION=<YOUR_REGION>

gcloud config set project $PROJECT_ID
gcloud config get project

Menginstal Komponen gcloud beta

Pastikan komponen beta telah diinstal (diperlukan untuk SSH Instance Cloud Run dan streaming log):

gcloud components install beta --quiet
gcloud components update

Memverifikasi Terraform

Pastikan Terraform telah diinstal dan memenuhi persyaratan versi:

terraform version

Anda akan melihat Terraform v1.5.0 atau yang lebih tinggi.

3. (Opsional) Menyiapkan Integrasi Pesan (Telegram atau WhatsApp)

Anda dapat menghubungkan OpenClaw ke Telegram atau WhatsApp. Pilih Opsi A atau Opsi B di bawah.

Opsi A: Penyiapan Bot Telegram

  1. Buka Telegram dan telusuri @BotFather.
  2. Kirim perintah /newbot dan ikuti petunjuk untuk menentukan nama dan nama pengguna bot.
  3. Salin Token API HTTP yang dihasilkan (misalnya, 123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ).
  4. Telusuri @userinfobot di Telegram, kirim /start, dan salin ID Pengguna numerik Anda (misalnya, 8035936176).

Anda akan memberikan nilai ini sebagai variabel input Terraform dalam file terraform.tfvars.

Opsi B: Penyiapan WhatsApp

  1. Dapatkan nomor telepon WhatsApp pribadi Anda dalam format internasional tanpa spasi atau simbol (misalnya, +15551234567).
  2. OpenClaw terhubung melalui kebijakan daftar yang diizinkan untuk saluran WhatsApp.

4. Menentukan Infrastruktur di Terraform

Kita akan mendeklarasikan seluruh infrastruktur kita di Terraform. Hal ini mencakup mengaktifkan Google Cloud API yang diperlukan, membuat akun layanan khusus dan peran IAM, membuat dan menyimpan secret di Secret Manager, menyediakan bucket status Cloud Storage, membuat konfigurasi openclaw.json, dan men-deploy Instance Cloud Run.

1. Membuat Direktori Terraform

Di Cloud Shell, buat direktori untuk file Terraform Anda dan buka direktori tersebut:

mkdir openclaw-terraform && cd openclaw-terraform

2. Buat main.tf

Buat file bernama main.tf. Konfigurasi ini menggunakan penyedia Google untuk menentukan semua komponen infrastruktur:

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. Buat variables.tf

Buat file bernama variables.tf untuk menentukan variabel input:

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. Buat outputs.tf

Buat file bernama outputs.tf untuk mengekspos URL instance yang di-deploy, sandi gateway yang dihasilkan, dan nama bucket penyimpanan:

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. Buat terraform.tfvars

Untuk mendapatkan kunci Gemini API:

  1. Buka Google AI Studio dan login dengan Akun Google Anda.
  2. Klik Create API key dan pilih project Google Cloud Anda.
  3. Salin kunci API yang dibuat.

Buat file bernama terraform.tfvars dengan koordinat project Anda:

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. Men-deploy Infrastruktur dengan Terraform

1. Melakukan Inisialisasi dan Menerapkan

Lakukan inisialisasi direktori kerja Terraform dan download plugin penyedia:

terraform init

Deploy infrastruktur:

terraform apply

Saat diminta, tinjau resource yang direncanakan dan ketik yes untuk mengonfirmasi.

2. Mengekstrak Output Deployment

Ekspor URL instance dan sandi gateway yang dihasilkan dari status 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. Berinteraksi melalui UI Web & Melakukan Autentikasi melalui SSH Cloud Run

OpenClaw 2.0+ menerapkan autentikasi perangkat kriptografis. Saat terhubung dari browser baru, gateway akan membuat permintaan penyambungan yang Anda setujui langsung melalui SSH native Instance Cloud Run.

1. Membuka UI Kontrol OpenClaw

  1. Buka $INSTANCE_URL di browser web Anda.
  2. Saat diminta untuk melakukan autentikasi, masukkan sandi gateway Anda ($GATEWAY_PASSWORD).
  3. Karena ini adalah sesi browser baru, UI OpenClaw Control akan menampilkan perintah penyambungan perangkat yang tertunda dengan ID Permintaan (misalnya: b56143fc-1654-49da-a1d8-5d40479ddc66). Salin ID Permintaan ini.

2. SSH ke Instance Cloud Run

Di Cloud Shell, mulai shell interaktif yang aman ke instance yang sedang berjalan:

gcloud beta run instances ssh openclaw-instance --region=${REGION}

3. Menyetujui Penyambungan Perangkat

Di dalam sesi SSH, setujui permintaan browser Anda:

openclaw devices approve <REQUEST_ID> --password ${GATEWAY_PASSWORD}

4. Memberikan Perintah kepada Agen (Instance yang Beraksi)

Setelah disetujui, browser Anda akan langsung terhubung ke Dasbor Kontrol OpenClaw.

  1. Uji agen OpenClaw Anda dengan mengirimkan perintah di UI chat, seperti, "Hello".
  2. Untuk menguji siklus proses yang berjalan lama dan penyimpanan persisten instance Cloud Run, minta agen OpenClaw Anda untuk melakukan tugas terjadwal dan otonom. Misalnya, minta Gemini memantau repositori GitHub untuk rilis dan membuat draf ringkasan:
    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.
    
  3. Karena status OpenClaw, file ruang kerja, dan database SQLite dipertahankan langsung ke Cloud Storage melalui Cloud Storage FUSE, tugas terjadwal, histori percakapan, dan file ringkasan yang dihasilkan akan tetap ada meskipun instance dimulai ulang dan container diupgrade.

7. (Opsional) Memverifikasi Integrasi Saluran Pesan

Jika Anda mengonfigurasi Telegram atau WhatsApp dalam langkah-langkah penyiapan opsional di atas, Anda dapat memverifikasi pengiriman pesan:

  1. Periksa log instance di Cloud Shell:
    gcloud beta run instances logs read openclaw-instance --region ${REGION} --limit 20
    
  2. Buka Telegram (atau WhatsApp) dan kirim pesan (misalnya, /start atau Hello OpenClaw!).
  3. Bot akan mengautentikasi ID pengguna Anda berdasarkan daftar yang diizinkan di openclaw.json dan merespons menggunakan Gemini.

8. Memantau dan Memeriksa Log Instance

Instance Cloud Run menangkap stdout dan stderr dari container Anda dan mengalirkannya langsung ke Google Cloud Logging. Anda dapat menggunakan Cloud Shell atau Konsol Cloud untuk memantau traffic gateway dan memeriksa eksekusi alat agen secara real time.

1. Membaca Log Instance Terbaru

Untuk mengambil entri log terbaru dari instance di Cloud Shell:

gcloud beta run instances logs read openclaw-instance \
  --region ${REGION} \
  --limit 50

2. Tanda Tangan Log Utama yang Perlu Diamati

Saat mengamati agen yang sedang berjalan, cari peristiwa log runtime utama berikut:

  • [gateway] ready: Mengonfirmasi bahwa gateway HTTP dan WebSocket OpenClaw telah diinisialisasi dan memproses port 18789.
  • [gateway] agent model: ...: Menampilkan model Gemini yang aktif (misalnya, google/gemini-3.1-pro-preview atau google/gemini-3.5-flash).
  • [agents/tool-policy]: Menampilkan alat yang diizinkan atau dibatasi berdasarkan kebijakan Anda.
  • [agent/embedded]: Melacak eksekusi dan pemanggilan alat oleh agen.

3. Memeriksa Log di Konsol Google Cloud

Anda juga dapat melihat dan memfilter log menggunakan Logs Explorer di Konsol Cloud:

resource.type="cloud_run_instance"
resource.labels.instance_name="openclaw-instance"

9. (Opsional) Memperluas Agen Anda dengan Keahlian

OpenClaw mendukung Keahlian—paket kemampuan modular yang mengajarkan alur kerja tertentu, alat CLI khusus, dan petunjuk khusus domain kepada agen Anda.

Cara Kerja Keahlian

Setiap keahlian adalah direktori yang berisi file SKILL.md. File ini dimulai dengan frontmatter YAML yang menentukan metadata (name dan description), diikuti dengan petunjuk 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: ID keterampilan (juga dapat dipanggil langsung sebagai perintah garis miring, misalnya /summarize-logs).
  • description: Memberi tahu model OpenClaw kapan harus otomatis memanggil keahlian ini dalam percakapan alami.

Menambahkan Keahlian Kustom ke Bucket Cloud Storage Anda

Karena bucket Cloud Storage Anda dipasang di /mnt/openclaw dan dikonfigurasi di skills.load.extraDirs, skill yang ditempatkan di gs://${BUCKET_NAME}/skills/ akan otomatis dimuat dan dipertahankan di seluruh mulai ulang instance:

  1. Mengambil Nama Bucket Anda:
    export BUCKET_NAME=$(terraform output -raw storage_bucket)
    
  2. Membuat Direktori Keahlian Lokal:
    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
    
  3. Mengupload Skill ke Cloud Storage:
    gcloud storage cp -r my-skill gs://${BUCKET_NAME}/skills/
    
  4. Menggunakan Skill di Chat:
    • Kembali ke UI Web OpenClaw Control.
    • Anda kini dapat memasukkan perintah ke agen menggunakan /summarize-logs atau mengajukan pertanyaan dalam bahasa alami yang sesuai dengan deskripsi keterampilan.

10. Pembersihan

Agar tidak menimbulkan biaya berkelanjutan pada akun Google Cloud Anda untuk resource yang digunakan dalam codelab ini, Anda dapat menghancurkan semua infrastruktur yang disediakan dalam satu langkah menggunakan Terraform:

  1. Pastikan Anda berada di direktori openclaw-terraform:
    cd openclaw-terraform
    
  2. Hancurkan semua resource:
    terraform destroy
    
  3. Saat diminta, tinjau resource yang akan dihapus dan ketik yes untuk mengonfirmasi. Terraform akan menghapus Instance Cloud Run, secret Secret Manager, binding kebijakan IAM, akun layanan, dan bucket Cloud Storage dengan bersih.

11. Kesimpulan

Selamat! Anda telah berhasil men-deploy instance OpenClaw yang aman dan sepenuhnya persisten di Instance Cloud Run menggunakan Terraform deklaratif, yang didukung oleh persistensi status Cloud Storage, keamanan kredensial Secret Manager, dan SSH native Instance Cloud Run untuk autentikasi perangkat yang aman.