Oracle Free ARM VM Capacity Error Fix
Full Code :
name: Oracle ARM Instance Creator
on:
# schedule:
# - cron: '*/30 * * * *'
workflow_dispatch:
env:
SUPPRESS_LABEL_WARNING: "True"
OCI_CLI_SUPPRESS_FILE_PERMISSIONS_WARNING: "True"
jobs:
create-vm:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
vm:
- name: vm-prod
steps:
- name: Install OCI CLI
run: pip install oci-cli
- name: Configure OCI CLI
env:
OCI_PRIVATE_KEY: ${{ secrets.OCI_PRIVATE_KEY }}
OCI_USER: ${{ secrets.OCI_USER_OCID }}
OCI_FP: ${{ secrets.OCI_FINGERPRINT }}
OCI_TEN: ${{ secrets.OCI_TENANCY_OCID }}
OCI_REG: ${{ secrets.OCI_REGION }}
run: |
mkdir -p ~/.oci
printf '%s\n' "$OCI_PRIVATE_KEY" > ~/.oci/oci_api_key.pem
chmod 600 ~/.oci/oci_api_key.pem
printf '[DEFAULT]\nuser=%s\nfingerprint=%s\ntenancy=%s\nregion=%s\nkey_file=/home/runner/.oci/oci_api_key.pem\n' \
"$OCI_USER" "$OCI_FP" "$OCI_TEN" "$OCI_REG" > ~/.oci/config
chmod 600 ~/.oci/config
- name: Verify authentication
run: |
if ! oci iam region list --output table > /dev/null 2>&1; then
echo "OCI auth failed:"
oci iam region list 2>&1 || true
exit 1
fi
echo "Authentication OK"
- name: Check if ${{ matrix.vm.name }} already exists
id: check
run: |
echo "Querying for ${{ matrix.vm.name }}..."
RESULT=$(oci compute instance list \
--compartment-id "${{ secrets.OCI_COMPARTMENT_ID }}" \
--display-name "${{ matrix.vm.name }}" \
2>/dev/null || echo '{"data":[]}')
COUNT=$(echo "$RESULT" | python3 -c "import sys,json; d=json.loads(sys.stdin.read()); active=[i for i in d.get('data',[]) if i.get('display-name')=='${{ matrix.vm.name }}' and i.get('lifecycle-state') not in ('TERMINATED','TERMINATING')]; print(len(active))" 2>/dev/null || echo "0")
echo "Active instance count: $COUNT"
echo "count=$COUNT" >> $GITHUB_OUTPUT
[ "$COUNT" != "0" ] && echo "${{ matrix.vm.name }} already exists — skipping." || echo "${{ matrix.vm.name }} not found — will attempt creation."
- name: Get availability domains
if: steps.check.outputs.count == '0'
id: ads
run: |
ADS=$(oci iam availability-domain list \
--compartment-id "${{ secrets.OCI_COMPARTMENT_ID }}" \
--query 'data[*].name' \
--raw-output 2>/dev/null \
| python3 -c "import sys,json; print(' '.join(json.load(sys.stdin)))")
if [ -z "$ADS" ]; then
echo "Failed to fetch availability domains"
exit 1
fi
echo "list=$ADS" >> $GITHUB_OUTPUT
echo "ADs found: $ADS"
- name: Try to create ${{ matrix.vm.name }}
if: steps.check.outputs.count == '0'
id: create
run: |
echo "${{ secrets.SSH_PUBLIC_KEY }}" > /tmp/ssh.pub
CREATED=false
for AD in ${{ steps.ads.outputs.list }}; do
echo "--- [${{ matrix.vm.name }}] Trying $AD ---"
if oci compute instance launch \
--availability-domain "$AD" \
--compartment-id "${{ secrets.OCI_COMPARTMENT_ID }}" \
--shape "VM.Standard.A1.Flex" \
--shape-config '{"ocpus": 2, "memoryInGBs": 12}' \
--image-id "${{ secrets.OCI_IMAGE_ID }}" \
--subnet-id "${{ secrets.OCI_SUBNET_ID }}" \
--assign-public-ip true \
--ssh-authorized-keys-file /tmp/ssh.pub \
--display-name "${{ matrix.vm.name }}" \
--boot-volume-size-in-gbs 100 \
> /tmp/result.json 2>&1; then
echo "[${{ matrix.vm.name }}] SUCCESS in $AD"
cat /tmp/result.json
CREATED=true
break
else
ERROR=$(cat /tmp/result.json)
if echo "$ERROR" | grep -qi "capacity"; then
echo "[${{ matrix.vm.name }}] No capacity in $AD — trying next."
else
echo "[${{ matrix.vm.name }}] Unexpected error in $AD: $ERROR"
fi
fi
done
echo "created=$CREATED" >> $GITHUB_OUTPUT
[ "$CREATED" = false ] && echo "[${{ matrix.vm.name }}] No capacity in any AD. Waiting for next scheduled attempt."
This controls the VM hardware allocation and is not fixed. Modify it according to the resources you want.
--shape-config '{"ocpus": 2, "memoryInGBs": 12}'
For a smaller instance:
--shape-config '{"ocpus": 1, "memoryInGBs": 6}'
Create a GitHub repository and place the workflow inside:
.github/workflows/oracle-vm.yml
Paste the YAML workflow exactly as provided.
Enable periodic execution by uncommenting:
if you are on github actions free tier Keep the schedule section commented:
# schedule:
# - cron: '*/30 * * * *'
GitHub Actions on free accounts does support scheduled workflows, but execution timing is not guaranteed. Scheduled jobs can be delayed, skipped, or throttled under platform load, especially for repositories with low activity. For an Oracle capacity hunting workflow this matters because available ARM capacity may only exist for a short window.
Instead of relying entirely on GitHub's scheduler, keep workflow_dispatch enabled and trigger the workflow externally using:
cron-job.org
This approach makes the schedule independent from GitHub's internal cron behavior:
cron-job.org
↓
GitHub workflow_dispatch API
↓
Oracle API
↓
ARM instance creation attempt
Configure cron-job.org to call the GitHub workflow every 15–30 minutes. This provides more predictable execution timing while GitHub still performs the actual workflow execution.
Keep only:
workflow_dispatch:
inside the workflow.
Create a cron-job.org task that calls GitHub's workflow dispatch endpoint every 15–30 minutes.
GitHub API endpoint:
https://api.github.com/repos/USERNAME/REPOSITORY/actions/workflows/oracle-vm.yml/dispatches
Request method:
POST
Headers:
Authorization: Bearer YOUR_GITHUB_TOKEN
Accept: application/vnd.github+json
Content-Type: application/json
Body:
{
"ref":"main"
}
Create a GitHub token:
GitHub
→ Settings
→ Developer settings
→ Personal access tokens
Enable:
Actions: write
If limits are reached, additional GitHub accounts can run the same repository.
Go to GitHub:
Repository
→ Settings
→ Secrets and Variables
→ Actions
Create these secrets.
OCI_PRIVATE_KEY
Open Oracle:
Profile icon
→ My Profile
→ API Keys
→ Add API Key
Generate a key.
Copy the complete private key (needs to be on terminal):
commande : cat filename
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
Paste the full content as the secret value.
OCI_USER_OCID
Profile icon
→ My Profile : User OCID
OCI_FINGERPRINT
Profile icon
→ My Profile
→ API Keys : Fingerprint
OCI_TENANCY_OCID
Profile icon
→ Tenancy : Tenancy OCID
OCI_REGION
Top-right region selector
eu-frankfurt-1
uk-london-1
us-ashburn-1
OCI_COMPARTMENT_ID
Identity
→ Compartments
Copy compartment OCID.
Most users use the root compartment.
OCI_IMAGE_ID
Compute
→ Create Instance
→ Image and Shape
Image OCID
OCI_SUBNET_ID
Networking
→ Virtual Cloud Networks
→ VCN
→ Subnets
Public Subnet OCID
SSH_PUBLIC_KEY
Generate SSH keys on your terminal : ssh-keygen -t ed25519
Files created:
id_ed25519
id_ed25519.pub
copy id_ed25519.pub content to SSH_PUBLIC_KEY
Run the workflow manually once:
Repository
→ Actions
→ Oracle ARM Instance Creator
→ Run workflow
Then leave it running until Oracle eventually exposes available capacity.
Frequently Asked Questions
Why does Oracle show "Out of Capacity" when creating a free VM?+
Oracle Free Tier ARM instances use shared infrastructure with limited available resources per region and Availability Domain. When many users attempt to create free instances at the same time, Oracle temporarily rejects new requests even if your account is valid and your configuration is correct.
Does changing regions solve Oracle capacity issues?+
Sometimes. Some regions have lower demand and become available faster, but highly requested regions can remain saturated for long periods. Availability changes continuously, which is why automated retries are more reliable than manual attempts.
How long does it take for Oracle free VM capacity to become available?+
There is no fixed time. Capacity may become available within minutes, several hours, or after multiple days. Automated retries remove the need to manually refresh the Oracle Console repeatedly.
Why use GitHub Actions instead of creating a VPS for retries?+
GitHub Actions can execute workflows automatically without requiring a permanently running server. This allows the retry logic to run continuously without maintaining additional infrastructure.
Why use cron-job.org if GitHub Actions already supports schedules?+
GitHub scheduled workflows on free accounts may experience delays or inconsistent execution timing. External scheduling through cron-job.org provides more predictable triggering and reduces dependency on GitHub's scheduling behavior.
What Oracle information is required before running the automation?+
The workflow requires Oracle API credentials and identifiers including User OCID, Tenancy OCID, Fingerprint, Private Key, Compartment OCID, Image OCID, Subnet OCID, Region information, and an SSH public key.
Can multiple virtual machines be created automatically?+
Yes. Multiple VM definitions can be added to the workflow matrix. The automation will attempt instance creation separately for each configured virtual machine.
Will the workflow keep creating duplicate VMs?+
No. The workflow first checks whether an active instance with the specified name already exists. If a matching VM is found, creation is skipped.
