In my last post I briefly discussed Clawdbot, the virtual assistant from Peter Steinberger that has taken off as an open source alternative to something like Poke.
I wanted to host this 24/7 as cheap as possible, not on my laptop. Oracle Cloud's free-tier compute: 4 core & 24gb RAM VPS offering is more than sufficient to achieve this at no hosting cost.
I've published a repository to spin this up on Oracle Cloud, via Pulumi (infra-as-code) and GitHub Actions.
What you'll need to do is:
The rest of the article walks you through the above tasks.
Task List
What are we deploying
Infra
I'm detailing the infra using the Oracle terms and the AWS equivalent for familiarity:
- a 'VCN' (VPC): a virtual cloud network.
- internet gateway & route table to provide the compute instance with internet access
- a Ubuntu server with up to 4 cores, 24gb RAM; you could choose to tune this down as this is overkill for clawdbot alone, but perhaps not if you want it to control harness sessions, or browsers too.
- 'security list' (security group) defining allowed inbound/outbound port connectivity
- the compute is going into a public subnet to avoid the expense of a NAT gateway & load balancer.
Networking:
We allow inbound:
- TCP port 22 (SSH) but only with a public key, no password or root login, and the stack won't deploy without public/private key (encrypted) specified.
- UDP 41641 is open for Tailscale to avoid falling back to DERP relays adding latency if you want to use your devices as clients.
Fail2ban is configured in cloud-init to ban IPs making too many failed login attempts.
All outbound traffic is allowed.
For receiving data from third party services, Tailscale Funnel is natively integrated into Clawdbot, you will need to configure Clawdbot to use it (post-deploy).
What 'Funnel' will achieve: you'll be given a Tailscale URL which acts as your unique tunnel to Clawdbot's HTTP listener, with our Tailscale client on the VPS terminating TLS and passing data to Clawdbot. The Tailscale client maintains a persistent outbound connection to its DERP home region, which Funnel relay servers use to reach your node when requests arrive: meaning we don't need to expose inbound ports for Clawdbot.
A Word on Security
This article is aimed at an audience who want to experiment with a personal AI assistant, as cheaply as possible. You are responsible for what data you expose via your configuration of Clawdbot, especially in relation to your choice of LLM model provider.
If you put an absolute premium on information security, the approach in this article is not the correct one for you. I might write up a self-hosted LLM equivalent article if there's sufficient demand (subscribe and drop a note: author@abrown.blog).
My goal is to give you a secure infrastructure setup, from there you need to carefully consider what you choose to do.
Limitations
Regarding the IP limitations, as noted in the thread, a Tailscale exit node is a fairly easy solution here. This might compromise the goal of not running your own compute 24/7, but personally my GL.iNet GL-MT3000 router happily does this and is on 24/7 anyway.
There are possibly some further limitations if you actually need to access Apple ecosystem tools (as Armin pointed out later), but these can be solved by having your macbook function as a Node, though it would need to be on.
Before you deploy
You'll need accounts with a few services before we can deploy. All of these have free tiers that are sufficient for our purposes.
Oracle Cloud Account
Head to Oracle Cloud and sign up for a free account.
The compute resources we're deploying are within the always-free tier, however there is a small catch regarding provisioning the instance.
When I tried to provision the instance without signing up to pay-as-you-go, it would regularly fail (over 50 attempts). Once my plan was upgraded, again bearing in mind we're still operating in the always-free tier, the deployment succeeded on the first attempt.
You probably need to sign up to pay-as-you-go in order to acquire a free instance, but this deployment won't cost you anything as-is.
Now to the data you'll need from Oracle once signed up:
| Variable | How to Retrieve |
|---|---|
OCI_TENANCY_OCID | Profile (top-right corner) > Tenancy > OCID |
OCI_USER_OCID | Profile > your email > OCID |
OCI_FINGERPRINT | Profile > User Settings > Tokens and Keys > Create an API Key. Afterwards, the fingerprint will be visible. Make sure to download the private key if you have Oracle generate it. |
OCI_PRIVATE_KEY_FILE | Download it from the previous step, for simplicity, .gitignore a top-level folder and place it here. If deploying in CI/CD, we'll cover what to do in the Deploy chapter. |
OCI_REGION | Look this up as appropriate for you |
OCI_COMPARTMENT_ID | Just the tenancy OCID above. |
Tailscale
Sign up for a free Tailscale account. We'll use Tailscale to create secure networking for your VPS and enable Funnel for external webhooks.
| Variable | How to Retrieve |
|---|---|
TAILSCALE_CLIENT_ID | Admin Console > Settings > Settings > Trust Credentials. Add the Auth Keys write scope when creating it. |
TAILSCALE_CLIENT_SECRET | Generated alongside the Client ID in the previous step. Save it immediately as you won't be able to view it again. |
TAILSCALE_TAG | Admin Console > Access Controls > Tags tab > Create a tag (e.g., tag:clawdbot) with owner set to autogroup:admin. Then assign this tag to your OAuth client. |
TAILSCALE_TAILNET | Admin Console > DNS tab > Your tailnet DNS name |
Pulumi Cloud
Pulumi is an infrastructure-as-code tool that lets us define our cloud resources in TypeScript. Create a free account and generate an access token. The free tier includes 200 resources which is plenty for this deployment.
The reason we're troubling with this is that it lets us store our state file without needing paid cloud storage or keeping it in the repo and awkwardly re-committing it after deployment.
| Variable | How to Retrieve |
|---|---|
PULUMI_ACCESS_TOKEN | Profile (top-right) > Personal access tokens > Create new access token |
PULUMI_ORG | Your Pulumi organization name (visible in the URL after logging in) |
LLM Model
Clawdbot needs an LLM to function. I strongly recommend against any provider's API key pricing, better to obtain a subscription and cap your expenditure.
The most popular low-cost option among the Clawdbot community seems to be Minimax (starts $10 USD/month), this is a referral link for 10% off.
If you're planning to do a lot of coding via Clawdbot or even on your own machine, possibly a better option is z.ai's GLM 4.7, starting at a mere $3 USD/month (first month) and $6 thereafter. Here's a referral, but bear in mind Z.AI seems to emphasise use with coding agents only, they may crack down on this at some point.
Note: we don't configure the subscription key as an env variable, we provide it to Clawdbot after we SSH in.
Fork or Clone Repo
Simple option: If you just want to deploy locally, clone the repo and set your environment variables in a gitignore'd .env file.
Slightly more involved: If you want to run all of your changes to the infra through CI/CD (more involved), fork it, make it private and setup the appropriate secrets / variables in GitHub Actions.
Configure Repository Actions
Skip this if you opted to clone.
If you have a coding agent setup with access to your github account, I highly recommend having it set these up for you (reading from your .env file) instead of manually setting them up.
To do this manually, go to your forked repository in GitHub -> Settings -> Secrets and Variables -> Actions.
Set the below as Secrets (not variables):
| Secret Name |
|---|
OCI_TENANCY_OCID |
OCI_USER_OCID |
OCI_FINGERPRINT |
OCI_COMPARTMENT_ID |
OCI_PRIVATE_KEY |
PULUMI_ACCESS_TOKEN |
TAILSCALE_CLIENT_ID |
TAILSCALE_CLIENT_SECRET |
SSH_PUBLIC_KEY |
Set the below as Variables (not secrets):
| Variable Name |
|---|
TAILSCALE_HOSTNAME |
TAILSCALE_TAG |
TAILSCALE_TAILNET |
PULUMI_ORG |
PULUMI_STACK |
PULUMI_PROJECT |
OCI_REGION |
Note: PULUMI_PROJECT and PULUMI_STACK are the names you want these to have, it's not extremely important what these are.
I set project to 'clawdbot' and stack to 'oracle-vps'.
Deployment
Via CI/CD
Go to your Repo -> Actions and find the Pulumi Deploy workflow on the left hand side.
Click it, then 'Run Workflow' from the main branch, near the right hand side of the page.
Reminder: If you didn't set up pay-as-you-go in Oracle Cloud, there's a good chance you'll see a 'no instances available' error. Other errors are likely to do with your actions secrets/variables, check these closely and consider feeding the error to OpenCode with a free model to check the configuration for you.
If it was succesful, to test SSH:
Local Deployment
If you've chosen the local deployment, ensure your .env file contains the following variables:
| Variable | Description |
|---|---|
OCI_TENANCY_OCID | Your Oracle tenancy OCID |
OCI_USER_OCID | Your Oracle user OCID |
OCI_FINGERPRINT | Your API key fingerprint |
OCI_COMPARTMENT_ID | Your compartment ID (usually the tenancy OCID) |
OCI_PRIVATE_KEY_FILE | Path to your OCI private key file |
OCI_REGION | Your Oracle region (e.g., uk-london-1) |
PULUMI_ACCESS_TOKEN | Your Pulumi access token |
PULUMI_ORG | Your Pulumi organization name |
PULUMI_PROJECT | Your Pulumi project name (e.g., clawdbot) |
PULUMI_STACK | Your Pulumi stack name (e.g., oracle-vps) |
TAILSCALE_CLIENT_ID | Your Tailscale OAuth client ID |
TAILSCALE_CLIENT_SECRET | Your Tailscale OAuth client secret |
TAILSCALE_HOSTNAME | Hostname for your VPS in Tailscale (you can specify any arbitrary name for this) |
TAILSCALE_TAG | Tailscale tag (e.g., tag:clawdbot) |
TAILSCALE_TAILNET | Your Tailscale tailnet name |
SSH_PUBLIC_KEY | Your SSH public key for VPS access |
Then run $npm start up:localcopied. You should see it spit out your instanceId, public IP and tailscaleFqdn.
Reminder: If you didn't set up pay-as-you-go in Oracle Cloud, there's a good chance you'll see a 'no instances available' error. Other errors are likely to do with your .env, check these closely and consider feeding the error to OpenCode with a free model to check the configuration for you.
If it was succesful, to test SSH:
Post-Deployment
The first thing you'll want to do is tail the cloud-init output: $tail -f /var/log/cloud-init-output.logcopied Note that this will likely be in progress if you SSH straight after deployment, give it time if it appears stuck.
If everything went to plan, you should see a URL under some text reading:
"Funnel is enabled, but the list of allowed nodes in the tailnet policy file does not include the one you are using. To give access to this node you can edit the tailnet policy file, or visit:"
Click the link and approve your instance to use Funnel.
Once this is done, your cloud-init should complete and you can run $clawdbot onboardcopied to get started with Clawdbot.
If this wasn't half bad
Get notified about new posts.