On AWS
Deploy the app and gateway Workers on Cloudflare, and create each organization's Computer VM on EC2 yourself
On AWS the gateway runs with COMPUTER_VMS set to self-managed: it creates no VMs. You create one EC2 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
export AWS_REGION=us-east-1
export BUCKET=<globally unique>
aws s3 mb "s3://$BUCKET" --region "$AWS_REGION"
aws s3 cp /tmp/calvin.bundle "s3://$BUCKET/calvin.bundle"The bundle holds the Computer source and the model proxy built for Linux amd64. The bucket stays private; step 7 gives the VM a URL that is valid for one hour.
6. 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 EBS volume for /data. It needs outbound internet access and no inbound access: a new security group has no inbound rules.
Make a download URL for the release, then 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 and runs its boot script:
export BUNDLE_URL="$(aws s3 presign "s3://$BUCKET/calvin.bundle" --expires-in 3600 --region "$AWS_REGION")"
(umask 077; GATEWAY_HOST=gateway.example.com \
computer/deploy/vm/self-managed-user-data.sh > computer-user-data.sh)Create the security group and the instance in the default VPC:
AMI="$(aws ssm get-parameter --region "$AWS_REGION" --query Parameter.Value --output text \
--name /aws/service/canonical/ubuntu/server/24.04/stable/current/amd64/hvm/ebs-gp3/ami-id)"
SG="$(aws ec2 create-security-group --region "$AWS_REGION" --group-name computer \
--description 'Computer VMs: no inbound' --query GroupId --output text)"
aws ec2 run-instances --region "$AWS_REGION" \
--image-id "$AMI" --instance-type m7i.large \
--security-group-ids "$SG" \
--block-device-mappings \
'DeviceName=/dev/sda1,Ebs={VolumeSize=64,VolumeType=gp3}' \
'DeviceName=/dev/sdf,Ebs={VolumeSize=128,VolumeType=gp3,DeleteOnTermination=false}' \
--metadata-options HttpTokens=required \
--tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=computer},{Key=organization,Value=$ORG_ID}]" \
--user-data file://computer-user-data.sh \
--query 'Instances[0].InstanceId' --output textThe first boot installs the toolchains, formats the blank volume, mounts it at /data and starts the host. It takes about five minutes. The boot script formats a volume only when it is blank.
The token stays in the instance’s user data. On the VM only root can read it; in AWS, anyone allowed to call ec2:DescribeInstanceAttribute 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.
Stop, start and resize
Stop the instance with aws ec2 stop-instances; the Computer shows Offline and Slack messages wait. Start it with aws ec2 start-instances; the host reconnects and the workspace is still on /data. To resize, stop the instance, change its type with aws ec2 modify-instance-attribute, and start it.
Terminating the instance does not delete the data volume.
Check a VM
The VM has no SSH access. The boot log is /var/log/calvin-boot.log, and the two services are slack-presence-host and oc-modelproxy. From a root shell on the VM, for example through AWS Systems Manager Session Manager (the instance then needs an instance profile with the AmazonSSMManagedInstanceCore policy):
systemctl is-active slack-presence-host.service oc-modelproxy.service
tail -50 /var/log/calvin-boot.logUpdate 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