FreeTurtle runs great on Oracle Cloud's free ARM instance: 2 CPUs, 12 GB RAM, always free.
Tip: If you're not comfortable with cloud setup, paste this entire guide into ChatGPT, Claude, or any AI chat and ask it to walk you through step by step. It can answer questions as you go — screenshots help too.
- Sign up at cloud.oracle.com (credit card required, $1 auth hold)
- Your region is locked at signup (e.g. US-Ashburn)
- Upgrade to Pay-As-You-Go — this is required to reliably create the ARM instance
Why Pay-As-You-Go? The free tier alone often shows "Out of capacity" when creating ARM instances. Upgrading to PAYG dramatically improves availability. There's a $100 authorization hold that is NOT charged — as long as you follow this guide and select the free-tier-eligible shape, you will not be billed. This confuses people but it's how Oracle works.
Do this first — the instance creation form's inline networking option does NOT properly set up a public subnet.
- Go to Networking > Virtual Cloud Networks
- Click Create VCN
- Name: whatever you want (e.g.
my-vcn,prod-network) - IPv4 CIDR block:
10.0.0.0/16 - DNS hostnames: enabled
- Skip IPv6
- Inside your VCN, go to Resources > Internet Gateways
- Create an Internet Gateway — name it anything (e.g.
my-gateway,internet-gw)
- Inside your VCN, go to Resources > Routing > Default Route Table
- Click Add Route Rules
- Target Type: Internet Gateway
- Destination CIDR:
0.0.0.0/0 - Target: your gateway
If the UI gives an error about "Rules in the route table must use private IP as a target" — this is a known Oracle Console bug. Try:
- Refresh the page and re-enter the rule
- Use a different browser or incognito window
- If the UI keeps failing, use OCI Cloud Shell (terminal icon, top-right of console):
oci network route-table update \
--rt-id <ROUTE_TABLE_OCID> \
--route-rules '[{"destination":"0.0.0.0/0","destinationType":"CIDR_BLOCK","networkEntityId":"<INTERNET_GATEWAY_OCID>"}]'Get the OCIDs from the Route Table and Internet Gateway detail pages.
- Inside your VCN, go to Resources > Subnets > Create Subnet
- Name: anything (e.g.
public-subnet,main-subnet) - Subnet Type: Regional
- CIDR:
10.0.0.0/24 - Subnet Access: Public Subnet
- DNS Resolution: leave Use DNS hostnames in this Subnet checked (default)
Go to Compute > Instances > Create Instance.
- Availability Domain: Use the default (if you get "Out of capacity", try a different one)
- Capacity Type: On-demand capacity (NOT preemptible)
- Leave fault domain and cluster placement as defaults
- Operating System: Canonical Ubuntu 24.04 (latest build)
- Click the Ampere tab
- Shape: VM.Standard.A1.Flex (ARM)
- OCPUs: 2
- Memory: 12 GB
- This is the free tier ARM shape. Do NOT select VM.Standard.E2.1.Micro (1 CPU / 1 GB RAM — too small)
- Shielded instance: Off
- Confidential computing: Off
- Primary network: Select existing virtual cloud network > your VCN
- Subnet: Select existing subnet > your public subnet
- VNIC name: anything you want — just a label (e.g.
primary,main) - Private IPv4: Automatically assign
- Public IPv4: Toggle ON
- Select Generate a key pair for me
- Download both private key and public key BEFORE creating the instance
- You cannot retrieve the private key later
- Leave defaults (46.6 GB, no custom size)
- Use in-transit encryption: On (default)
- Don't check "Encrypt this volume with a key that you manage"
If you get "Out of capacity":
- Try a different Availability Domain
- Make sure your account is upgraded to Pay-As-You-Go
- Try again later — ARM capacity fluctuates
Once your instance is running, you need to connect to it from your computer's terminal (Terminal on Mac, PowerShell on Windows).
1. Find your key files. When you created the instance, you downloaded a .key file (and a .pub file). Find them — probably in your Downloads folder.
2. Create a connection folder. Keep your key and a connect script together somewhere easy to find — like a folder on your Desktop or in your projects directory:
mkdir -p ~/Desktop/my-server-ssh
mv ~/Downloads/ssh-key-*.key ~/Desktop/my-server-ssh/
mv ~/Downloads/ssh-key-*.pub ~/Desktop/my-server-ssh/3. Lock down permissions. SSH refuses to use a key file that other users can read:
chmod 400 ~/Desktop/my-server-ssh/ssh-key-*.key4. Find your server's public IP. Go to Compute > Instances in the Oracle console, click your instance, and copy the Public IP address.
5. Create a connect script. This saves you from remembering the full command every time:
cat > ~/Desktop/my-server-ssh/connect.sh << 'EOF'
#!/bin/bash
ssh -i "$(dirname "$0")"/ssh-key-*.key ubuntu@<PASTE_YOUR_PUBLIC_IP>
EOF
chmod +x ~/Desktop/my-server-ssh/connect.shReplace <PASTE_YOUR_PUBLIC_IP> with your actual IP address.
6. Connect:
~/Desktop/my-server-ssh/connect.shType yes when asked about the fingerprint. You're now on your server. From now on, just run connect.sh to reconnect.
Your folder should look like this:
my-server-ssh/
├── connect.sh
├── ssh-key-2026-02-16.key
└── ssh-key-2026-02-16.key.pub
Never share your private key file — not in AI chats, not in screenshots, not in git. If someone has your key, they have full access to your server.
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get install -y nodejssudo npm install -g pnpmsudo pnpm install -g freeturtlefreeturtle initThis walks you through naming your AI CEO, connecting Farcaster, Telegram, GitHub, etc.
freeturtle startThis keeps FreeTurtle running after you disconnect and auto-restarts on reboot:
freeturtle install-serviceThen verify:
systemctl --user status freeturtleTo survive logouts:
sudo loginctl enable-linger $(whoami)journalctl --user -u freeturtle -fOr check the log file:
cat /tmp/freeturtle/freeturtle.logNeynar webhooks require an HTTPS URL. The easiest setup is a free subdomain + Caddy (auto-HTTPS reverse proxy).
If you don't have a domain, use DuckDNS (free):
- Sign in with Google/GitHub
- Create a subdomain (e.g.
myturtle.duckdns.org) - Set it to your server's public IP (find it:
curl ifconfig.meon the server)
If you already have a domain, add an A record pointing a subdomain to your server IP.
Oracle has two firewalls — both need ports open.
Cloud Security List:
- Networking > VCN > your VCN > your subnet > Default Security List
- Add two Ingress Rules:
- Rule 1: Source CIDR
0.0.0.0/0, TCP, Destination Port Range80 - Rule 2: Source CIDR
0.0.0.0/0, TCP, Destination Port Range443
- Rule 1: Source CIDR
OS-level firewall:
sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -I INPUT -p tcp --dport 443 -j ACCEPTsudo apt install -y caddyReplace yourname.duckdns.org with your actual domain:
sudo tee /etc/caddy/Caddyfile <<EOF
yourname.duckdns.org {
reverse_proxy localhost:3456
}
EOF
sudo systemctl restart caddyCaddy automatically provisions and renews HTTPS certificates — no certbot or manual config needed.
freeturtle webhooksWhen prompted for the webhook URL, enter: https://yourname.duckdns.org/webhook
curl https://yourname.duckdns.org/webhookIf Caddy is working, you should get a response (even if FreeTurtle isn't running yet — Caddy will return a 502).
Oracle has two firewalls — the cloud security list AND the OS-level firewall.
If you need to open a port:
Cloud Security List:
- Networking > VCN > your VCN > your subnet > Default Security List
- Add Ingress Rule: Source CIDR
0.0.0.0/0, TCP, Destination Port Range: your port
OS-level firewall:
sudo iptables -I INPUT -p tcp --dport <PORT> -j ACCEPTSSH (port 22) is open by default.
- Oracle may send warnings about idle free tier instances — upgrading to PAYG prevents most issues
- Treat the server as disposable — keep your
~/.freeturtle/config backed up or in git - If the instance is lost, a full rebuild takes ~15 minutes on any new server
- The ARM instance is always free as long as you stay within the free tier limits (4 OCPUs / 24 GB total across all A1 instances — using 2/12 leaves room for a second instance if needed)