Saturday, April 11, 2026

Why I Couldn’t SSH Into My OCI VM Using Mobile Hotspot (And How I Finally Fixed It)

Why I Couldn’t SSH Into My OCI VM Using Mobile Hotspot (And How I Finally Fixed It)

There are moments in cloud troubleshooting where everything looks perfectly configured… and yet, nothing works. This was one of those moments.

I had set up an Oracle Cloud (OCI) virtual machine, configured the networking correctly, added my public IP to the security list, and confidently tried to SSH into the server.

And then… it failed. Not once. Not twice. Every single time.

If you’ve ever faced a similar issue while working on a mobile hotspot, this article will save you hours of confusion.

๐Ÿ” The Setup — Everything Looked Correct

Let me first explain the setup so you can relate.

I had:
A compute instance in OCI with a public IP
A security rule allowing SSH (port 22) from my IP
My laptop connected via a mobile hotspot

From a configuration standpoint, this is textbook correct. In a typical home or office broadband setup, this should work instantly.

But here’s the catch — mobile networks behave very differently.

๐Ÿงช The First Suspicion — IP Mismatch

When SSH didn’t work, I did what most of us do — I verified my IP address. From the browser, I checked using an IP lookup website.
Then from terminal, I ran: curl ifconfig.me

To my surprise, both showed different results. At first glance, this might look like a minor inconsistency. But in reality, this is the starting point of the entire problem.

⚠️ Understanding the Real Problem


After digging deeper, I discovered that two things were happening simultaneously — and both are very common when using mobile hotspots.
๐ŸŒ 1. IPv6 vs IPv4 Mismatch

The IP returned from the terminal looked something like:

2509:50c2:104d:df9b:9e6b:732d:a081:d7e2

This is clearly an IPv6 address. However, most OCI environments (unless explicitly configured) operate using IPv4:
Public IP assigned to VM → IPv4
Security rules → IPv4 CIDR ranges
SSH access → typically IPv4

So what was happening?

๐Ÿ‘‰ My laptop was trying to connect using IPv6
๐Ÿ‘‰ My OCI VM was expecting IPv4 traffic

These two simply don’t talk to each other unless specifically configured.

๐Ÿ“ก 2. Carrier-Grade NAT (CGNAT)

Now comes the second and more subtle issue.

Mobile network providers don’t assign a unique public IPv4 address to every user. Instead, they use something called Carrier-Grade NAT (CGNAT).
Let me simplify this.

Instead of:

Your Laptop → Internet → OCI VM

The actual flow looks like:

Your Laptop → Mobile Network NAT → Shared Public IP → OCI VM

This means:
  • Your device does not directly own a public IPv4 address
  • Multiple users share the same external IP
  • The IP you see may not be the one OCI sees
  • The IP can change frequently
So even if you whitelist an IP in OCI, the request might come from a completely different IP.

๐Ÿšซ Why SSH Failed Despite Correct Configuration

At this point, everything started to make sense.
I had configured:
Source: <my-ip>/32
Port: 22

But OCI evaluates the actual incoming IP, not what I think my IP is. Due to CGNAT and IPv6 behavior:
My outgoing request did not match the whitelisted IP. OCI security rules blocked the connection.
Result → SSH timeout

This is why the issue feels so confusing — because the configuration is technically correct, but the network behavior breaks the assumption.

๐Ÿงช Confirming the Diagnosis
To validate this, I ran:
curl ifconfig.me
curl -4 ifconfig.me
curl -6 ifconfig.me

At this point, it was clear that this was not an OCI issue — it was a network limitation.

✅ What Actually Works (Practical Solutions)

Once you understand the root cause, the solution becomes much clearer.

๐Ÿฅ‡ Solution 1 — Use OCI Bastion (Recommended Approach)

The most effective and professional way to handle this is by using
OCI Bastion

Instead of exposing your VM directly to the internet, Bastion acts as a secure entry point.

Why this works so well:
  • It does not rely on your public IP being stable
  • It works even if your IP changes frequently
  • It eliminates the need to open SSH to the world
  • It aligns with security best practices
In simple terms, you connect to Bastion, and Bastion connects to your VM internally. This completely avoids the problems caused by CGNAT and IP mismatch.

๐Ÿฅˆ Solution 2 — Forcing IPv4 (Temporary Workaround)

If you still want to try direct SSH, you can attempt to force IPv4:
curl -4 ifconfig.me

If you get a valid IPv4 address:

Add that IP in OCI security rules
Use ssh -4 to force IPv4 connection

However, this is not reliable because:
  • The IP may change at any time
  • CGNAT may still interfere
  • You may lose access intermittently
This is more of a quick test rather than a long-term solution.

Conclusion

This issue wasn’t really about OCI configuration — it was about how mobile networks behave. With CGNAT, dynamic IPs, and IPv6 in play, the IP you whitelist is often not the one OCI actually sees, which leads to SSH failures.

Instead of trying to chase changing IPs, the better approach is to use solutions designed for such environments, like OCI Bastion or OCI Cloud Shell.

๐Ÿ‘‰ The key takeaway: when working from a mobile hotspot, don’t rely on IP-based access — use network-independent access methods for a stable and secure connection.


Thanks & Regards,
Chandan Tanwani

Friday, February 13, 2026

Shrinking Storage in Shared Autonomous Database on OCI

Shrinking Storage in Shared Autonomous Database on OCI

In one of our projects, we had deleted a huge volume of historical data from our Autonomous Database. Naturally, the expectation was simple:

Data is deleted → storage should reduce → cloud cost should go down.

But when we checked OCI metrics, the storage size was still the same. This created confusion in the team and raised an important question: “If the data is gone, why is storage still allocated?” If you have faced this, you are not alone. This is one of the most common and misunderstood behaviours in the Shared Autonomous Database on OCI.

This exact scenario is something I see very often across customers and projects using Shared Autonomous Database on OCI. 

First, Let’s Understand How Storage Works in Autonomous Database

One of the biggest advantages of Autonomous Database is automatic storage scaling.

This means:
-> As your data grows → storage automatically increases.
-> You never need to worry about provisioning disks.
-> Performance remains consistent.
However, here is the important part many people don’t realize: When data is deleted, storage does NOT shrink automatically.

Yes — that surprises many people.

Why Storage Does Not Automatically Reduce

This behavior is actually by design.Oracle keeps the allocated storage to ensure:
-> Stable performance
-> No frequent resizing overhead
-> Faster future data growth handling

So when you delete data:
✔ The space becomes free inside the database
❌ But OCI still considers it allocated storage

And that means you continue paying for that storage unless you reclaim it. This is why understanding storage shrinking is very important for cloud cost optimization.

When Should You Shrink Storage?

Based on my real project experience, you should consider shrinking storage after:
  • Large data purging activities
  • Archiving historical records
  • Cleaning up staging tables
  • Dropping big tables or partitions
  • Post-migration cleanup
  • Temporary ETL data removal
Basically, whenever a significant amount of data is removed.

Check Before Shrinking Storage

One important point to understand is that Oracle Autonomous Database does not add multiple datafiles to the DATA tablespace. Instead, it uses a single large datafile (bigfile tablespace) and automatically increases its size of that big datafile as storage grows.

Because of this architecture, shrinking storage can take significant time, since the database must reorganize and reclaim space within a very large datafile.

Run the following query to assess the potential storage savings before initiating the shrink operation. All columns in the output are expressed in MB.

select file_name,
       ceil( (nvl(hwm,1)*&&blksize)/1024/1024 ) sm,
       ceil( blocks*&&blksize/1024/1024) currsize,
       ceil( blocks*&&blksize/1024/1024) -
       ceil( (nvl(hwm,1)*&&blksize)/1024/1024 ) savings
from dba_data_files a,
     ( select file_id, max(block_id+blocks-1) hwm
         from dba_extents where tablespace_name='DATA' 
        group by file_id ) b
where a.file_id = b.file_id(+) and a.tablespace_name='DATA';

You should proceed with storage shrinking only when the savings column indicates a significant amount of reclaimable space. If the expected savings are minimal, it is not recommended to run this operation, as it is time-consuming and resource-intensive with limited practical benefit.

Steps to Shrink Storage in Autonomous Database

Step 1 — Log in to the OCI Console

Navigate to:
OCI Console → Autonomous Database → Select your database

Step 2 — Open Resource Allocation

Click the More actions drop-down menu and select Manage resource allocation.


Step 3 — Review Storage Details

In the Storage section, review:
"Allocated storage" — Total storage currently reserved
"Approximate used storage" — Actual space consumed by data


You can also run the query below to identify space usage by schemas/objects.

select file_name,
ceil( (nvl(hwm,1)*&&blksize)/1024/1024 ) sm,
ceil( blocks*&&blksize/1024/1024) currsize,
ceil( blocks*&&blksize/1024/1024) -
ceil( (nvl(hwm,1)*&&blksize)/1024/1024 ) savings
from dba_data_files a,
( select file_id, max(block_id+blocks-1) hwm
from dba_extents
group by file_id ) b
where a.file_id = b.file_id(+)

If you observe a significant difference between allocated and used storage, you may be able to reclaim space. For example, in my case there was approximately 4 TB of reclaimable storage between allocated and actual usage.

Step 4 — Click the "Shrink" Button

Click Shrink to initiate the storage reduction process.

Preconditions for Shrink Operation
The Shrink option is available only when all of the following conditions are met:

- Storage auto-scaling is enabled
- Allocated storage is greater than base (minimum) storage
- Allocated storage − Used storage > 100 GB

If these conditions are not satisfied and you click Shrink, Autonomous Database displays an “Action unavailable” message.

Considerations and Challenges with the Shrinking Process

There are a few important aspects to be aware of before initiating storage shrink:

1. No visible progress indicator
Once the shrinking process starts, there is no direct way in the console or database views to monitor its progress. The only practical approach is to raise an SR with Oracle Support and request periodic updates on the completion percentage.

2. Potentially long execution time
The duration largely depends on the size of the data file.
In my case, the data file was about 9 TB, and the shrink process took more than 28 hours to complete.

NOTE: 
๐Ÿ‘‰  The shrink operation runs an alter table... move online operation hence it is taking long time to complete it.
๐Ÿ‘‰ Once your data deletion operation is complete, wait at least 1–2 hours before initiating the shrink process. Autonomous Database needs time to recalculate storage usage, and the updated values may take some time to appear in the OCI Console.
Because of this delay, the Shrink operation may occasionally be unavailable or fail immediately after large deletions, as the console has not yet reflected the updated storage metrics.

3. ECPU allocation impacts duration
The time required for shrinking also depends on the number of ECPUs allocated to the Autonomous Database. Higher ECPU allocation provides more processing power for the reorganization work.

๐Ÿ‘‰ Therefore, it is recommended to scale up ECPUs before starting the shrink operation.
This helps in two ways:
-> Reduces overall shrink duration
-> Minimizes impact on your ongoing workload

My final conclusion

๐Ÿ‘‰ Storage will NOT shrink automatically
๐Ÿ‘‰ You must reclaim it manually via console

This small step can save significant cloud costs.



Thanks & Regards,
Chandan Tanwani