Troubleshooting¶
Organized by symptom. Find your symptom, work through the checks in order, skip to the next symptom if the current one doesn't apply.
Can't SSH¶
Symptom: ssh: connect to host <ip> port 22: Connection timed out or
Permission denied (publickey).
Timeout — you can't even reach port 22:
- Is the instance actually running? OCI console → Compute → Instances → check state = Running.
- Is the public IP right? OCI console → Instance → Networking → Primary VNIC → Public IPv4 address.
- OCI security list allows port 22? Networking → VCN → Security
Lists → default → Ingress Rules. Should have a rule allowing TCP
22from0.0.0.0/0(or your specific IP). - Route table has default route to Internet Gateway?
Networking → VCN → Route Tables → the one attached to your subnet.
Should have
0.0.0.0/0→ Internet Gateway. - Instance firewall allows port 22? SSH via the OCI serial
console (Instance → Console Connections → Launch Cloud Shell
Connection or serial console) to check
iptables -L/nft list ruleset.
Permission denied (publickey):
- Right SSH key on your local machine?
ssh -i ~/.ssh/oci_lab ubuntu@<ip> -v— the-vflag shows which key is being tried. - Right SSH key in the instance's
authorized_keys? Log in via OCI's serial console and checkcat /home/ubuntu/.ssh/authorized_keys. - Right username? For Ubuntu images, it's
ubuntu. For Oracle Linux images, it'sopc. For custom images, whatever you set. - Permissions on the private key? On your local machine:
chmod 600 ~/.ssh/oci_lab. SSH refuses to use keys with too-open permissions.
Caddy TLS fails¶
Symptom: sudo journalctl -u caddy shows something like no such host,
connection refused, or too many failed authorizations.
-
DNS resolves to the right IP?
Should return your instance's public IP. If not, DNS isn't set up right — see DNS with Cloudflare. -
Port 443 is open at OCI? VCN Security List → Ingress → TCP 443 allowed from
0.0.0.0/0. -
Port 443 is open in the instance firewall?
-
Port 80 also open? Let's Encrypt's HTTP-01 challenge (which Caddy tries as a fallback) needs port 80. Even if you want to force HTTPS-only, port 80 needs to be reachable for the challenge.
-
DNS record is gray-cloud (DNS only), not orange-cloud (Proxied)? Cloudflare orange-cloud terminates TLS at Cloudflare's edge and Caddy can't answer the
tls-alpn-01challenge. See DNS gotcha. -
Let's Encrypt rate-limited you? Look for
Verify staging works, then remove thetoo many failed authorizationsorrate limitedin the journal. Wait ~1 hour and try again. To avoid this during debugging, temporarily use the staging endpoint:acme_caline and reload for real certs. -
Caddy actually listening on 443?
Should show caddy. If nothing's on 443,systemctl status caddy— something's wrong with the service.
DNS not resolving¶
Symptom: dig lab.example.com returns nothing, or curl says Could not
resolve host.
-
Cloudflare is authoritative for the domain?
Should return two.ns.cloudflare.comnameservers. If not, your registrar hasn't propagated the nameserver change yet — wait up to 48 hours (usually much less). -
A record exists in Cloudflare? DNS → Records → check for
lab(or whatever subdomain) with type A pointing at your IP. -
Waiting on caching? If you previously queried before creating the record, negative caching (NXDOMAIN) can persist for minutes. Try:
Direct queries to public resolvers skip your local cache. -
Right hostname? Typos in Caddyfile vs. DNS records happen. Copy from one to the other.
OCI shows charges I didn't expect¶
Symptom: your budget alert fired or your Cost Analysis shows non-zero.
Walk the staying-free checklist. Common culprits:
- NAT Gateway from the VCN Wizard, never deleted
- Flexible Load Balancer created by accident
- Extra Reserved Public IPs not attached to instances
- Boot volumes >47 GB × 3 instances >141 GB, adding block volumes pushes over 200 GB total
- Bandwidth over 10 TB/month — check Usage Reports
ARM Ampere "out of host capacity"¶
See Provision the ARM Ampere → Capacity constraints. Not really a bug, just the free-tier reality.
Instance is running but unreachable, and it was reachable before¶
Something changed. Recent changes to check, most-recent first:
-
You edited nftables/iptables and now port 22 doesn't work. OCI console → Instance → Console Connections → serial console. Fix the rules from the serial console.
-
OCI security list was edited. Check ingress rules are still there.
-
Boot disk is full. Serial console →
df -h. If root is at 100%, SSH can start but sshd may fail to create session files. Free space or resize the boot volume. -
Reboot in progress. Check the instance status in the OCI console — if it's showing "Provisioning" or "Stopping", wait.
Caddy reloaded but old content still served¶
-
Browser cached the old content. Try a hard refresh (Ctrl+F5 or Cmd+Shift+R) or an incognito window.
-
Caddy served-from-cache. Caddy has a small cache for static files. Restart instead of reloading:
-
Reload failed silently. Check the journal:
Look for a Caddyfile parse error. Caddy refuses to load a broken config and keeps serving the old one. -
You wrote to the wrong directory.
sudo cat /etc/caddy/Caddyfile— confirm therootdirective points where you think.
The instance was terminated and I need it back¶
You can restore a terminated instance from its boot volume if the boot volume wasn't also deleted (Terminate has a "Permanently delete the attached boot volume" checkbox — leave it unchecked to keep the option open).
- Storage → Boot Volumes → find the one for the terminated instance.
- … menu → Create Instance → configure a new instance using this boot volume.
If the boot volume was also deleted, restore from a manual backup if you had one, or start over. This is why the staying-free checklist suggests periodic backup — Object Storage is free for the first 20 GB and boot volume backups compress well.
Still stuck?¶
- The Oracle Cloud Free Tier docs are the authoritative reference for what's free.
- The Caddy documentation is exceptional — search there for any Caddy question.
- Open an issue on this guide's GitHub repo if you found a gap or a mistake.