JDS5 No-BS AI

Your first cloud VM, step by step — on the free tier that stays free

By Daniel S. · September 1, 2026

Setting up a cloud VM is the same six moves everywhere: make an SSH key, create the instance, narrow the firewall, connect, harden, and don't lock yourself out. Learn them once and every provider afterward is just different menus. This guide walks all six on Oracle Cloud's Always Free tier, because it has a property no other major provider's free tier has: on an un-upgraded account, your card cannot be charged. Oracle's own docs say it in one sentence: "Your credit card will not be charged unless you upgrade your account" ⏱️ verified 2026-09-01. That makes it the safest possible place to make beginner mistakes, which is exactly what a first VM is for.

TL;DR

What you actually get (as of September 2026)

On 15 June 2026, Oracle cut the Always Free ARM allowance in half, from 4 OCPUs / 24 GB down to 2 OCPUs / 12 GB, with no blog post, no email, no announcement. The docs page was quietly edited, and people found out when their instances stopped (InfoQ covered it, ⏱️ verified 2026-09-01). Any tutorial dated before mid-2026 will walk you straight past the free line.

And going past the line doesn't bill you; it's worse in a different way. Oracle's wording: if you have more Ampere A1 compute provisioned than an Always Free tenancy allows, all existing A1 instances are disabled, then deleted after 30 days, unless you upgrade to a paid account. It doesn't charge the card; it takes the machine.

The current allowance, from Oracle's Always Free resources page (⏱️ all figures verified 2026-09-01):

Resource Always Free allowance Watch for
ARM compute (VM.Standard.A1.Flex) 2 OCPUs + 12 GB RAM Tenancy-wide pool, not per instance
AMD compute (VM.Standard.E2.1.Micro) 2 × (1/8 OCPU, 1 GB) Tiny, but never capacity-blocked
Block + boot storage 200 GB total Boot volumes count against this
Boot volume default 50 GB Four default instances = the whole pool
Outbound transfer 10 TB / month Generous; won't bite a beginner
Load balancer 1 × 10 Mbps flexible A second one isn't free

The one real decision: guaranteed $0, or guaranteed uptime

You can't have both, and no honest guide pretends otherwise. Oracle reclaims idle Always Free compute. The only escape from reclamation is upgrading to Pay As You Go, which is also the only way your card can ever be charged.

"Idle" has a precise definition. An instance is reclaimable only when all three of these hold across a 7-day window: CPU utilization (95th percentile) under 20%, network utilization under 20%, and (on ARM shapes only) memory utilization under 20%. Because every condition must be true at once, a machine doing genuine work is safe. A machine you spin up and forget is not.

My call for a first VM: stay Always Free and accept the reclamation risk. That converts "I hope I configured this right" into "Oracle cannot bill this account," which is a much stronger guarantee than any amount of careful clicking. If the box gets reclaimed, you rebuild it, and since you'll have the commands below saved, that's minutes, not an afternoon. Upgrade to Pay As You Go only if uptime later matters more than the hard $0 ceiling; that's a deliberate trade, not a default.

One thing not to do: you'll find advice to run a CPU-burner script to defeat the idle check. It works and it's a bad idea: you'd be burning real electricity to hold a seat you're not using, plainly against the intent of the policy. If the box needs to stay up, the sanctioned answer is upgrading.

Step 0 — a budget alarm, and know which account you're on

If your account is new, you start in a 30-day trial with promotional credits. When it ends, the account converts to Always Free on its own; it does not auto-upgrade to paid. The trap: anything you built with trial headroom that exceeds Always Free limits gets reclaimed after the trial. Build to Always Free size from day one and the transition is a non-event. Check which state you're in via the banner on the console dashboard or the top-right avatar → Tenancy.

Then set a tripwire: Billing & Cost Management → Budgets → Create Budget. Scope Tenancy, amount $1, monthly, alert at 100% of actual spend to your email.

Know what this does and doesn't do: a budget is a detector, not a brake. It's evaluated roughly every 24 hours and stops nothing; you get an email after the fact. Smoke alarm, not sprinkler. The actual protection is the un-upgraded account type.

Step 1 — make the SSH key on your own machine, before touching the console

The console asks for your public key during instance creation, so the key comes first. Generate it locally: the private half should never exist anywhere but your machine. ssh-keygen ships with macOS, Linux, and Windows 10+ (PowerShell):

ssh-keygen -t ed25519 -a 100 -C "oci-free-vm" -f ~/.ssh/oci_free_ed25519

Say yes to the passphrase prompt. On macOS you can store the passphrase in the Keychain so you type it once (ssh-add --apple-use-keychain ~/.ssh/oci_free_ed25519); on Linux and Windows, ssh-agent does the same job.

The file you'll paste into Oracle is ~/.ssh/oci_free_ed25519.pub. The .pub, never the other one. While you're here, add a host alias so you never hand-type the address:

cat >> ~/.ssh/config <<'EOF'

Host ocifree
    HostName        PUBLIC_IP_GOES_HERE
    User            ubuntu
    IdentityFile    ~/.ssh/oci_free_ed25519
    IdentitiesOnly  yes
EOF

Step 2 — create the instance

Menu → Compute → Instances → Create instance. Every field that matters:

Field Set it to Why
Image Canonical Ubuntu 24.04 LTS Long support runway; logs you in as ubuntu
Shape VM.Standard.A1.Flex The ARM shape, far more useful than the micro
OCPUs 2 Your entire free ARM allowance
Memory 12 GB Usually auto-fills from the OCPU count
Boot volume Leave at 50 GB Raising it eats the shared 200 GB pool
Public IPv4 Assign (ephemeral) Fine and free
SSH keys Paste your .pub From step 1

Watch for the "Always Free eligible" label on the shape and image as you select them. If it disappears, something you just changed costs money. Change it back. That label is the real signal, on Oracle and as a habit on every cloud console you'll ever use.

If you hit "Out of host capacity": extremely common on the ARM shape, and not your fault. It's a queue, not a rejection. Try a different availability domain in the same region, then retry every few minutes; capacity frees up as others release instances. (Your home region was fixed when the account was created and can't be changed, so there's no shopping around.) If your region stays dry for days, the AMD micro shape is always available as a fallback.

Step 3 — narrow SSH to your own address

The default rule opens port 22 to the entire internet. Tighten it to just you. From the instance page: Virtual cloud network → Security Lists → Default Security List → Ingress Rules. Get your current public address:

curl -s https://ifconfig.me; echo

Then edit the port-22 rule so its source CIDR is that address with /32 on the end (meaning "exactly this one address").

If your home IP is dynamic (most residential connections), it can change and lock you out of your own box. Either widen the rule to your ISP's prefix (weaker, still far better than 0.0.0.0/0), or leave 22 open to the world and lean on key-only auth plus fail2ban from step 5. What you must not do is leave it wide open and enable password login.

Step 4 — connect

Put the instance's public IP into the config entry from step 1, then:

ssh ocifree

You should land as ubuntu@. Two failure modes, two meanings: if it hangs, the firewall rule from step 3 is blocking you (wrong IP, usually); if it refuses outright, the instance is still booting; wait a minute.

Step 5 — harden it

Patches, automatic security updates, and a brute-force blocker:

sudo apt update && sudo apt -y upgrade
sudo apt install -y unattended-upgrades fail2ban
sudo dpkg-reconfigure -plow unattended-upgrades

Give fail2ban an explicit policy rather than trusting defaults:

sudo tee /etc/fail2ban/jail.local >/dev/null <<'EOF'
[sshd]
enabled  = true
backend  = systemd
maxretry = 3
findtime = 10m
bantime  = 1h
EOF
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd

Then confirm — don't assume — that password login is off. Oracle's image ships that way, but verify the live daemon config, not the file:

sudo sshd -T | grep -E '^(passwordauthentication|permitrootlogin|pubkeyauthentication)'

You want passwordauthentication no, permitrootlogin no (or prohibit-password), pubkeyauthentication yes.

Do not enable UFW on this image. This is the single most common way people brick an OCI Ubuntu box. The image ships with iptables rules already in place and UFW deliberately disabled; Oracle's own guidance is to leave it that way. Turning UFW on collides with the existing rules and has locked people out cold. To open a port, insert an iptables rule above the trailing REJECT rule instead:

sudo iptables -L INPUT --line-numbers -n
sudo iptables -I INPUT N -p tcp --dport 443 -m state --state NEW -j ACCEPT && sudo netfilter-persistent save

(replace N with the REJECT rule's line number). And the one line that must never leave /etc/iptables/rules.v4: the ACCEPT rule for port 22.

Step 6 — the lockout rule, which applies to every server you'll ever touch

The rescue path you assume exists mostly doesn't. Oracle's serial-console connection works by opening a local SSH session on the instance, so if you've broken sshd_config or stopped the daemon, the console fails too, for the same reason. (The recovery paths that do work, Run Command via the cloud agent or detaching the boot volume and fixing it from a second instance, are slow and fiddly. Prefer not needing them.)

The habit that prevents all of it: whenever you edit SSH config or firewall rules, keep your current session open and prove the change from a second, brand-new terminal before closing the first.

sudo sshd -t && sudo systemctl reload ssh

sshd -t validates the config before you reload; the fresh connection in terminal 2 proves the daemon still accepts you. Config that parses and config that lets you in are different claims, and only the second one matters. This habit is provider-agnostic. It will save you on every VPS, home server, and cloud box for the rest of your life.

Cost tripwires

Things that look harmless in the console and are not:

Action Why it bites
Raising the boot volume above 50 GB Boot and block share one 200 GB pool
Adding a second block volume "to test" Same pool; easy to cross without noticing
A second load balancer Exactly one is free
Provisioning ARM past 2 OCPU / 12 GB All A1 instances disabled, deleted after 30 days
Any shape without the "Always Free eligible" label The label is the signal; read it every time
Upgrading to Pay As You Go to clear a warning The one click that makes billing possible at all

Monthly 30-second check: Billing & Cost Management → Cost Analysis, range set to this month. On a correctly built Always Free account it reads $0.00.

FAQ

Is this really free forever, or a trial? Both exist and they're different things. The 30-day trial with credits expires; the Always Free resources don't. As long as you never upgrade the account, Oracle states your card will not be charged. The risk you carry instead is idle-reclamation, not billing.

Why Oracle and not AWS/GCP/Azure free tiers? The others' free tiers are mostly 12-month trials, credit-limited, or backed by a card that can be charged when you misconfigure something. Oracle's un-upgraded Always Free account is the only one of the majors where overage takes the machine away instead of billing you. For a first VM, that failure mode is the one you want.

What can 2 OCPUs and 12 GB actually run? Plenty for learning: a web server, a small database, Docker with a handful of containers, a VPN endpoint, a Minecraft server for a few friends, small local-AI experiments. It's a real ARM server, not a toy.

My instance got reclaimed. Did I do something wrong? Only in the sense that it sat idle: under 20% CPU, network, and memory for a week. Rebuild it with the steps above (this is why you keep the commands), and either give it a real job or accept the occasional rebuild as the price of $0.

Does any of this transfer to other providers? All of it except the console paths. SSH keys before instance, smallest disk that works, firewall narrowed to your address, key-only auth, fail2ban, and the two-terminal rule before touching sshd: that's the setup ritual everywhere.


Last updated 2026-09-01. Time-sensitive: free-tier limits are exactly the kind of fact that changes without announcement; June 2026 proved it. Re-check the linked Oracle docs if you're reading much later.

Sources (verified 2026-09-01): Oracle Always Free Resources (limits, idle-reclamation criteria), OCI Free Tier overview (account types, the no-charge-without-upgrade and A1-overage statements), Budgets overview (~24-hour evaluation cycle), Oracle Developers blog on OCI Ubuntu network traffic (iptables/UFW guidance), Instance Console Connection docs, InfoQ on the June 2026 limit reduction.