In this article
This guide covers how object storage works on an OpenMetal private cloud, the specific places where Ceph’s RADOS Gateway behaves differently from OpenStack Swift, how each difference can affect an application, and a practical way to test your own workloads before migrating.
If your application stores objects through the OpenStack Swift API, it will most likely keep working when you move it to an OpenMetal private cloud. Our clouds provide the Swift API through Ceph’s RADOS Gateway (RGW), which supports Swift’s core data model. But “most likely” isn’t good enough for production data. A few behaviors differ from upstream Swift, and the time to find out which ones affect you is before the migration, not during it.
This comes up most often with portable workloads. A team running an application on another OpenStack provider’s Swift service wants to move it, and the application was written against Swift’s behavior: its error codes, its limits, its access controls. The core operations, like creating containers and uploading, downloading, copying, and deleting objects, carry over cleanly. The edges are where surprises live.
We know where those edges are because we documented them. When we validated Private Cloud Core v4 with OpenStack’s Tempest test suite, we excluded a handful of object storage tests and wrote down why for each one. Combined with the Ceph project’s own feature support table, that gives a clear list of what to check.
How Object Storage Works on an OpenMetal Private Cloud
On an OpenMetal private cloud, Ceph provides block storage for your volumes and images, and Ceph’s RADOS Gateway provides object storage. RGW presents a Swift-compatible API that works with your cloud’s Keystone identity service, so your OpenStack users and projects work for object storage the same way they do for everything else.
The same object storage is also reachable through an S3-compatible API. You generate EC2-style credentials in Keystone with openstack ec2 credentials create, then point any S3 tool at your cloud’s endpoint. Our guide to creating EC2 credentials for S3 API access walks through the setup.
Because object storage runs on the same Ceph cluster as your block storage, it shares the cluster’s replication and capacity. There’s no separate storage system to size or maintain.
What Works the Same
Before getting into the differences, it helps to know how much carries over. Ceph’s feature table lists these Swift operations as fully supported:
- Authentication, including Keystone integration
- Creating, listing, and deleting containers
- Reading account metadata, and reading, updating, and deleting container metadata
- Uploading, downloading, copying, and deleting objects
- Reading and updating object metadata
- Large object uploads
- Expiring objects
For applications that store and retrieve files through authenticated clients, such as backups, logs, build artifacts, media processing pipelines, and data exports, that list covers nearly everything. Those workloads tend to move with no code changes at all.
Where RGW Behaves Differently From Swift
The Ceph Object Gateway Swift API documentation lists which Swift features RGW supports. Most are fully supported, including authentication, container and object operations, metadata, large objects, expiring objects, and copy. The differences below come from that table and from the exclusions in our Tempest run guide.
Error Codes for Unauthenticated Requests
When an unauthenticated client tries to write or delete an object, upstream Swift returns a 401 Unauthorized. RGW returns a 404 Not Found instead.
Why it matters: Some applications and client libraries treat a 401 as a signal to refresh their token and retry. If your code branches on that status code, an expired or missing token on RGW will look like a missing object rather than an authentication problem. Check how your client handles token expiry and make sure it refreshes tokens proactively rather than waiting for a 401.
Container Metadata Limits
Swift enforces caps on how many metadata items a container can have and how long they can be. RGW doesn’t enforce those Swift-specific limits.
Why it matters: This is permissive rather than restrictive, so it won’t break working code. But if your application relies on Swift rejecting oversized metadata as a form of validation, that rejection won’t happen. Enforce any limits you depend on in your own code.
Anonymous Downloads
On upstream Swift, a container can be made publicly readable so anyone can download objects without credentials. RGW supports this as an option, but we don’t enable anonymous downloads by default on our clouds.
Why it matters: If your application serves public files directly from a public container, such as images for a website, those links won’t work on a default configuration. You have a few options: use temporary URLs (covered below), put a proxy or CDN in front of the storage that authenticates on the application’s behalf, or talk with our team about your requirements.
Static Website Hosting
RGW can serve a container as a static website, similar to Swift’s static web feature. We don’t enable it by default, because static website hosting requires knowing the domains it will serve when RGW is configured.
Why it matters: If you host a static site out of object storage today, plan for it before you migrate rather than assuming it will work the same way. If you need it, talk with our team about your serving domains before deployment.
Swift ACLs
RGW supports a subset of Swift ACLs, according to Ceph’s feature table.
Why it matters: Basic read and write grants between projects and users work. If your application relies on more complex ACL rules, test each one you use rather than assuming full parity.
Temporary URLs
RGW supports Swift temporary URLs, with one gap: there’s no support for container-level keys. Temporary URLs signed with account-level keys work.
Why it matters: Temporary URLs are a common way to give time-limited access to private objects without making a container public. If your application signs temporary URLs with container-level keys, switch to account-level keys before you move.
Object Versioning
RGW’s Swift API has partial support for object versioning.
Why it matters: If you rely on Swift’s versioning to keep previous copies of overwritten objects, test the exact versioning behavior your application depends on, including how old versions are listed and restored.
CORS
RGW’s Swift API doesn’t support CORS.
Why it matters: Browser-based applications that read or write objects directly from JavaScript running on another domain rely on CORS headers. Without them, the browser blocks the request. If your frontend talks to object storage directly from the browser, route those requests through your own backend or a proxy that adds the headers you need.
Should You Use the Swift API or the S3 API?
Since both APIs reach the same storage, you can choose per application.
Stay on the Swift API if:
- Your application is already written against Swift and works within the differences above
- You rely on Keystone tokens and OpenStack project scoping for access
- You’re moving from another OpenStack cloud and want the smallest code change
Consider the S3 API if:
- Your tooling is already built around S3, such as the AWS CLI, S3 SDKs, or backup tools that speak S3
- You’re consolidating applications that came from AWS
- You want access to the broad set of tools and libraries that support S3
Whichever you choose, test the specific operations your application uses. Compatibility layers on any platform cover the common paths well and vary at the edges.
How to Test Before You Migrate
A short, structured test plan catches nearly all of these issues in a day or two.
Step 1: List the Swift Features You Actually Use
Go through your application code and configuration and list every object storage feature it touches: authentication and token refresh, container ACLs, public containers, temporary URLs, versioning, large object uploads, expiring objects, metadata, and any browser-side access. Most applications use far fewer features than the full API offers.
Step 2: Compare Against the Differences Above
Mark each feature from your list as fully supported, different, or not enabled by default. Anything in the second or third group gets a specific test.
Step 3: Run Your Application’s Own Tests Against the New Endpoint
Point a staging copy of your application at your OpenMetal cloud’s object storage and run your existing integration tests. Pay attention to authentication failures, permission errors, and any 404 that should have been a 401.
Step 4: Run Tempest’s Object Storage Tests
If you want an independent check of the platform itself, run Tempest’s object storage tests against your cloud using our published configuration and exclusion list. That separates platform behavior from your application’s behavior. Our article on running the same OpenStack tests we used to validate Private Cloud Core v4 walks through the process.
Step 5: Copy Data With a Tool That Speaks Both Sides
For the data itself, a tool like rclone can copy between Swift or S3 endpoints and verify the results. Our guide to backing up VM data to Ceph with rclone shows rclone working against OpenMetal object storage.
Who This Is For
This is most relevant if you:
- Run applications against the Swift API on another OpenStack provider and plan to move them
- Serve public files or static sites directly from object storage
- Use temporary URLs, ACLs, or versioning heavily
- Have browser-based frontends that access object storage directly
You probably have little to change if you:
- Use object storage for backups, logs, or internal artifacts through authenticated clients
- Access storage through S3-compatible tools rather than Swift-specific features
- Already proxy object access through your own backend
The Short Version
Ceph’s RADOS Gateway handles the core of the Swift API cleanly, and most applications move without code changes. The differences sit at the edges: error codes, public access, CORS, and a few partially supported features. List the features you use, test those specifically, and you’ll know before migration day whether anything needs to change.
If you want to test your object storage workloads on real hardware, apply for a proof of concept. You can also size a cloud with our private cloud pricing calculator or talk with our team about your storage requirements.
Frequently Asked Questions
Does OpenMetal use OpenStack Swift for object storage?
OpenMetal private clouds provide the Swift API through Ceph’s RADOS Gateway rather than running OpenStack Swift itself. RGW supports Swift’s core data model and works with Keystone, so most Swift applications work without changes.
Can I use S3 tools with OpenMetal object storage?
Yes. You can generate EC2-style credentials in Keystone and use S3-compatible tools such as the AWS CLI or rclone against your cloud’s object storage endpoint.
Why does an unauthenticated request return 404 instead of 401?
That’s how Ceph’s RADOS Gateway responds to unauthenticated writes and deletes. Upstream Swift returns 401 in the same situation. If your client refreshes tokens only after receiving a 401, update it to refresh proactively.
Can I make a container public on an OpenMetal private cloud?
Anonymous downloads aren’t enabled by default. Temporary URLs signed with account-level keys are one way to share objects without credentials, or you can serve public files through a proxy or CDN. Talk with our team if you need public access.
Does Ceph RGW support CORS for the Swift API?
No. Ceph’s documentation lists CORS as not supported for the Swift API. Route browser-based requests through your own backend or a proxy that adds the CORS headers you need.
Are Swift temporary URLs supported?
Yes, with one gap. Temporary URLs signed with account-level keys work, but container-level keys aren’t supported.
Schedule a Consultation
Get a deeper assessment and discuss your unique requirements.
Read More on the OpenMetal Blog

































