On Google Cloud
Deploy the app and gateway Workers on Cloudflare, and create each organization's Computer VM on Compute Engine yourself
On Google Cloud the gateway runs with COMPUTER_VMS set to self-managed: it creates no VMs. You create one Compute Engine instance per organization, and the instance connects out to the gateway with that organization’s host token.
| The gateway | You |
|---|---|
Shows the Computer as Online while its VM is connected and Offline otherwise | Create, size, stop, start and delete the VM |
| Holds a Slack message that arrives while the VM is offline, says so once in the thread, and runs it when the VM connects | Start the VM again |
The examples use app.example.com and gateway.example.com, as in On Azure.
1. Get the code
git clone https://github.com/diggerhq/opencomputer.git
cd opencomputer
(cd services/managed-agents && npm ci)
(cd cloudflare-workers/api-edge && npm ci)
(cd web && npm ci)2. Create the Cloudflare resources and the apps
Follow two steps of the Azure guide unchanged:
3. Deploy the gateway Worker
Follow Deploy the gateway Worker unchanged. Keep the value of COMPUTER_HOST_TOKEN_KEY at hand: step 6 derives each organization’s host token from it.
4. Deploy the app Worker
Follow Deploy the app Worker unchanged.
5. Build and upload the Computer release
From the repository root:
computer/deploy/bundle.sh /tmp/calvin.bundle
gcloud config set project '<PROJECT_ID>'
export PROJECT="$(gcloud config get-value project)"
export REGION=us-central1
export ZONE=us-central1-a
export BUCKET=<globally unique>
gcloud storage buckets create "gs://$BUCKET" --location="$REGION" --uniform-bucket-level-access
gcloud storage cp /tmp/calvin.bundle "gs://$BUCKET/calvin.bundle"The bundle holds the Computer source and the model proxy built for Linux amd64. The bucket stays private. Create a service account for the VMs that can only read the bucket:
gcloud iam service-accounts create computer-vm --display-name='Computer VMs'
export SA="computer-vm@$PROJECT.iam.gserviceaccount.com"
gcloud storage buckets add-iam-policy-binding "gs://$BUCKET" \
--member="serviceAccount:$SA" --role=roles/storage.objectViewer6. Get the organization ID and make the host token
- Open
https://app.example.comand sign in. - Open Settings and copy the Organization ID.
- Derive the organization’s host token from
COMPUTER_HOST_TOKEN_KEY:
export ORG_ID='<ORGANIZATION_ID>'
export COMPUTER_HOST_TOKEN_KEY='<the gateway secret>'
export TOKEN="sph_$(printf 'calvin-host:%s' "$ORG_ID" \
| openssl dgst -sha256 -hmac "$COMPUTER_HOST_TOKEN_KEY" -binary \
| base64 | tr '+/' '-_' | tr -d '=')"The token is valid for that organization only, and for as long as the key does not change.
7. Create the VM
The VM is Ubuntu 24.04 on amd64 with a second, blank disk for /data. It needs outbound internet access and no inbound access: a new VPC network has no firewall rule that allows inbound traffic.
Write the VM’s first-boot script with self-managed-user-data.sh. The script it prints stores the gateway URL and the token in a root-only file on the VM, downloads the release with the VM’s service account and runs its boot script:
(umask 077; GATEWAY_HOST=gateway.example.com BUNDLE_URL="gs://$BUCKET/calvin.bundle" \
computer/deploy/vm/self-managed-user-data.sh > computer-user-data.sh)Create the network and the instance. cloud-init runs the script in the user-data metadata key once, on the first boot:
gcloud compute networks create computer --subnet-mode=auto
gcloud compute instances create computer-1 --zone="$ZONE" \
--machine-type=e2-standard-2 \
--network=computer \
--image-family=ubuntu-2404-lts-amd64 --image-project=ubuntu-os-cloud \
--boot-disk-size=64GB \
--create-disk=name=computer-1-data,size=128GB,type=pd-balanced,auto-delete=no \
--service-account="$SA" --scopes=storage-ro \
--metadata-from-file=user-data=computer-user-data.shThe first boot installs the toolchains, formats the blank disk, mounts it at /data and starts the host. It takes about five minutes. The boot script formats a disk only when it is blank.
The token stays in the instance’s metadata. On the VM only root can read it; in Google Cloud, anyone allowed to read the instance (compute.instances.get) can.
8. Add the Slack app and connect GitHub
- Open
https://app.example.com. The Computer showsOnlineonce the VM has connected. - Click Add to Slack and approve.
- Connect GitHub and choose the repositories.
- Mention
@computerin a channel.
Repeat steps 6 and 7 for each further organization, with another instance and disk name.
Stop, start and resize
Stop the instance with gcloud compute instances stop; the Computer shows Offline and Slack messages wait. Start it with gcloud compute instances start; the host reconnects and the workspace is still on /data. To resize, stop the instance, change its type with gcloud compute instances set-machine-type, and start it.
Deleting the instance does not delete the data disk.
Check a VM
The boot log is /var/log/calvin-boot.log, and the two services are slack-presence-host and oc-modelproxy. No firewall rule allows SSH. To get a shell, allow SSH from Identity-Aware Proxy only, then connect through it:
gcloud compute firewall-rules create computer-iap-ssh --network=computer \
--allow=tcp:22 --source-ranges=35.235.240.0/20
gcloud compute ssh computer-1 --zone="$ZONE" --tunnel-through-iap --command \
'sudo systemctl is-active slack-presence-host.service oc-modelproxy.service; sudo tail -50 /var/log/calvin-boot.log'Update a VM
A self-managed VM does not update itself. Build and upload a new bundle (step 5), download it to /opt/bootstrap/calvin.bundle on the VM, and run as root:
git -C /opt/bootstrap/calvin-src fetch -q /opt/bootstrap/calvin.bundle main
git -C /opt/bootstrap/calvin-src checkout -q -f --detach FETCH_HEAD
CODE_ONLY=1 BOOTSTRAP_FETCH=0 bash /opt/bootstrap/calvin-src/deploy/vm/azure-computer-boot.sh