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:
- Log into the OCI Console or fire up the CLI
- Request a
VM.Standard.A1.Flexinstance - Get rejected because the availability domain is out of capacity
- Wait, then try again
- Get throttled by the API for retrying too quickly
- Finally succeed, only for the launch to fail at the primary VNIC step because your subnet doesn't allow public IPs
- 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+Cwithout 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
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"
Configure it with your tenancy, user, region, and API key:
oci setup config
Run the retry loop:
chmod +x retry.sh
DRY_RUN=true ./retry.sh
./retry.sh
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}"
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)
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}"
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.
Top comments (0)