Laravel and Object Storage on OCI
Opinionated article with possible ways to solve the problem.

Recently there is a lot of buzz around Oracle Cloud Infrastructure (OCI) because of their generous “Always Free Tier”. I wanted to explore what are the possibilities and limitations compared to AWS. In this new series we will discover how we can run a Laravel application on OCI.
OCI offers a lot of free resources, but there are limits. After creating a new account I switch to the Pay-as-you-go subscription, so that certain features are available (nothing expensive, but it allows better insights and more options).
Coming from AWS, my Laravel project works with S3 for filestorage. OCI has something similar called Object Storage. It basically works the same, you have buckets, objects, policies, etc.
The good news first: The Laravel S3 driver is drop-in compatible with OCI Object Storage. There is no need to create a custom service provider.
The bas news: Not all functions are supported. You can upload, download and delete objects, but you cannot move or copy them. More later.
Inspired by Laravel Vapor I am using a tmp folder for all uploads. Once the file is confirmed, the file is moved to it’s final destination via the Storage::move() function. That leaves me with the following options when migrating to OCI:
- Downloading the temp file to the server and re-uploading it to it’s new destination
- Storing it in the right destination in the first place
- Implementing the OCI API
- Writing a wrapper for the OCI CLI
I am not a fan of option A, because that would mean to download potentially huge files to the server. I would need to increase the hard drive for this purpose and take traffic cost, bandwidth and server load into consideration. For small applications only dealing with files like avatars this still might be a viable option.
The second option would require an architectural change. If you have a big code base that might be a problem. Also you have to track uploads that were not persisted by the user yourself, as you cannot leverage lifecycle rules to automatically clean up orphaned uploads anymore. You would need to pass down the final destination from your front-end logic, which is not nice, or create several routes to conceal this information. If you only have one type of file upload per route, you probably could read out the originator and determine the final location based on that, but once your application grows, you have to fallback to one of the other implementations in anyway.
Option three would be possible by extending the Flysystem package with using the OCI API as underlying logic. Personally I like this option, because it is an established package that most users are familiar with. There is a documentation page about how to create your own adapter.
Finally you could create a wrapper around the OCI CLI which can do everything the flysystem can do and more. Considering security this might not be the best option as it would generate shell commands executed on the server.
Personally I will pursue option 3. You can follow along on GitHub.