DEV Community

Garseta Yusuf
Garseta Yusuf

Posted on

Automating Oracle's Always-Free ARM Instance (So You Don't Have To Babysit It)

As a developer who likes free compute, I frequently found myself caught in a tedious cycle: trying to provision an Always-Free ARM instance on Oracle Cloud Infrastructure (OCI), watching it fail, and then trying again. And again. And again.

Capacity for the VM.Standard.A1.Flex shape is rarely available, the API throws rate-limit errors when you retry too fast, and sometimes the launch fails halfway through because the subnet you picked silently refuses a public IP. That's why I created oracle-instance, a small bash retry loop to automate this process and make provisioning seamless.

The Problem: The Manual Retry Loop

If you've ever tried to spin up an ARM instance on OCI's free tier, you might be familiar with this workflow:

  1. Log into the OCI Console or fire up the CLI
  2. Request a VM.Standard.A1.Flex instance
  3. Get rejected because the availability domain is out of capacity
  4. Wait, then try again
  5. Get throttled by the API for retrying too quickly
  6. Finally succeed, only for the launch to fail at the primary VNIC step because your subnet doesn't allow public IPs
  7. Repeat this process every single time capacity flickers back online

This manual loop becomes increasingly painful the more you need a fresh instance. With each attempt, you're forced to spend valuable time fighting the console instead of actually building things.

The Solution: oracle-instance

To address this challenge, I developed oracle-instance, a dependency-free bash script that automatically retries instance creation until it succeeds, and fixes the two most common OCI pitfalls on its own. Here's what it does:

  • Automatically retries instance creation with polite backoff (no more API throttling)
  • Picks a valid public subnet instead of blindly guessing the first one
  • Enforces the Always-Free cap (2 OCPUs / 12 GB) so a typo can't cost you money
  • Grabs the latest Ubuntu 22.04 ARM image automatically
  • Exits cleanly on Ctrl+C without leaving half-built instances behind

How It Works

The script integrates seamlessly with the OCI CLI. Here's a quick setup guide:

Install the OCI CLI (macOS with Homebrew):

brew update
brew install oci-cli
oci --version
Enter fullscreen mode Exit fullscreen mode

Or via Oracle's installer (Linux / macOS):

bash -c "$(curl -L https://raw.githubusercontent.com/oracle/oci-cli/master/scripts/install/install.sh)"
exec "$SHELL"
Enter fullscreen mode Exit fullscreen mode

Configure it with your tenancy, user, region, and API key:

oci setup config
Enter fullscreen mode Exit fullscreen mode

Run the retry loop:

chmod +x retry.sh
DRY_RUN=true ./retry.sh
./retry.sh
Enter fullscreen mode Exit fullscreen mode

Key Features

1. Hard Resource Cap

The script refuses to request more than the free-tier allowance, even via environment override. A typo can't blow past Always-Free:

MAX_OCPUS=2
MAX_MEMORY_GB=12
OCPUS="${OCPUS:-2}"
MEMORY="${MEMORY:-12}"
Enter fullscreen mode Exit fullscreen mode

2. Self-Correcting Subnet Selection

Instead of taking the first subnet (which might be private), it queries for one that can actually receive a public IP:

SUBNET_ID=$(oci_cli network subnet list \
  --compartment-id "$COMPARTMENT_ID" \
  --all \
  --query 'data[?prohibit-public-ip-on-vnic==false]|[0].id' \
  --raw-output)
Enter fullscreen mode Exit fullscreen mode

If you force a public IP on a private subnet, it fails fast with a clear message instead of dying mid-launch.

3. Polite Retries

The loop sleeps between attempts and backs off longer after a rate-limit hit:

SLEEP_SECONDS="${SLEEP_SECONDS:-120}"
RATE_LIMIT_SLEEP_SECONDS="${RATE_LIMIT_SLEEP_SECONDS:-300}"
Enter fullscreen mode Exit fullscreen mode

4. Real-World Impact

Since implementing this solution in my own workflow, I've noticed significant improvements:

  • Saved hours previously spent manually clicking and retrying in the console
  • Eliminated the subnet/VNIC launch failures that used to waste attempts
  • Got a working ARM box the moment capacity opened up, without watching the screen
  • Reduced friction for spinning up fresh test environments on demand

Looking Forward

The oracle-instance script is just the beginning. I'm actively working on additional features based on community feedback:

  • Multi-availability-domain round-robin (try ADs in sequence instead of just the first)
  • Slack or Telegram notify on success
  • Optional automatic post-provision setup (Docker, Tailscale, etc.)

If you've fought the same OCI capacity battle, give it a try, and pull requests are very welcome.

👉 https://github.com/garsetayusuf/oracle-instance

Top comments (0)