I recently started using the Oracle Cloud Free Tier to host some lab servers and external monitoring. The overall package is quite nice: You get 4 Ampere A1 (arm64) CPU cores and 24 GB of RAM, two AMD (x86) VMs with 1 core and 512 MB of RAM each, 200 GB of block volume space, as well as some databases, a load balacer, and other stuff. All for free.
When creating a compute instance, there are some common OS images to choose from, like Oracle Linux, Ubuntu, Rocky Linux, and more. But my personal favorite, Debian, is unfortunately not part of the portfolio.
The Oracle Cloud platform offers a way to upload custom images, but this feature is not available in the free tier as it requires a pay-as-you-go account. Somebody sane would now choose one of the available images and call it a day, but instead I started to test some things…
Messing around with block volumes
Taking a look at how volumes work, we can note the following things:
- There are “block volumes” and “boot volumes”
- We can attach multiple volumes to a single compute instance
- We can’t select block volumes (created in the “Storage” -> “Block Storage” section) as a boot volume when creating a compute instance
- When deleting a compute instance, we can opt to keep the boot volume
- Boot volumes have additional metadata that shows which OS image is installed on them
- Detached boot volumes from deleted instances can be attached to other instances like any other block volume
Thinking about the constraints above, I got an idea how we might be able to use custom images. The plan looks as follows:
- Create a compute instance
- Delete the compute instance, while keeping the boot volume
- Attach the now detached boot volume as a secondary volume to any other compute instance
- Write the custom image to the secondary volume
- Detatch the secondary volume
- Create a new compute instance using the detached boot volume instead of an OS image
Checking if it actually works
Kind of hyped to have found a loophole that might actually work, I started to test if it indeed does:
- I downloaded the Debian Bookworm “genericcloud-arm64” image in the qcow2 format to an existing compute instance
- After that, I created a new Ampere A1 instance, selected Ubuntu as the OS image and deleted it right after provisioning
- I then attached the detached boot volume to my existing instance and wrote the qcow2 image to that volume using
qemu-img convert -f qcow2 -O raw debian-12-genericcloud-arm64.qcow2 /dev/sdb
- As the last step, I detached the volume again and created another compute instance using that volume as its boot volume
And there we go! The instance booted without any problems and I was able to log in over SSH as usual. It seems that the Oracle Cloud platform just uses standard cloudinit, so even the injection of my SSH key worked.
The approach described is definitely not as nice as simply uploading your own images. If you want to provision instances automatically (e.g. with OpenTofu), this is not suitable. It is definitely not supported by Oracle and may not work with any image. However, since I only use the Oracle Cloud for testing purposes anyway, it’s fine for me.
By default, metrics like CPU and RAM usage will probably be missing in the cloud portal because the Oracle agent is missing in the custom image. However, this has the funny side effect that the instance is apparently no longer reclaimed if it idles for too long.