S3 Doesn't Have to Look Like S3
A practical way to access S3-compatible object storage through an ordinary filesystem interface

Object storage is usually accessed through an API.

You upload an object, download an object, list a bucket, delete an object, and so on. Applications that use S3 directly therefore tend to contain storage-specific logic: the application knows that its files are actually objects in a bucket.

That is perfectly reasonable when the application is designed around object storage.

But sometimes it is unnecessary.

A surprising number of applications only need a simple filesystem abstraction:

open("assets/image.webp")
read(...)
write(...)
mkdir(...)
rename(...)
unlink(...)

For those applications, introducing an S3 client library and rewriting the storage layer around an object-storage API can be considerably more work than the actual storage requirement justifies.

One useful alternative is to make S3 look like a filesystem.

With rclone, this can be done without changing the application itself.

The Basic Idea

rclone is commonly known as a command-line tool for synchronizing files with cloud storage services.

It supports a large number of storage backends, including S3-compatible object storage.

One of its less obvious capabilities is mounting a remote storage backend as a filesystem.

The resulting architecture looks roughly like this:

Application
|
| normal filesystem operations
v
/mnt/storage
|
| FUSE
v
rclone
|
| S3 API
v
Object Storage

From the application's perspective, there is simply a directory.

The application does not need to know whether that directory ultimately represents a local disk, an S3 bucket, or another supported storage backend.

This is the part that makes the approach interesting.

Configuring an S3 Remote

First, configure an S3 remote in rclone.

Run:

rclone config

Create a new remote and select S3 as the storage type.

For an S3-compatible service, the important parameters are generally:

# put this to `rclone config file`
[my-s3]
type = s3
provider = s3 | Cloudflare | gcs | azureblob | dropbox ...
access_key_id = find_it_from_your_s3_compatible_vendor
secret_access_key = find_it_from_your_s3_compatible_vendor
endpoint = https://......

The exact configuration depends on the storage provider.

Then make it read-only, and test if it's in the correct path:

chmod 600 ~/.config/rclone/rclone.conf

Once configured, verify that rclone can access the bucket:

rclone lsd my-s3:your_bucket_name

You can also inspect a specific bucket:

rclone lsf my-s3:your_bucket_name

At this point, rclone is already able to treat the object store through its normal file-oriented command interface.

Mounting the Bucket

Create a local mount point:

sudo mkdir -p /mnt/s3

Then mount the remote:

rclone mount my-s3:your_bucket_name /mnt/s3

The bucket is now visible through the normal filesystem namespace.

For example:

ls -lah /mnt/s3

Files can be read normally:

cat /mnt/s3/example.txt

And ordinary applications can access them using normal filesystem APIs.

For a long-running mount, it is common to run rclone in the background:

rclone mount my-s3:your_bucket_name /mnt/s3 --daemon

Depending on the deployment environment, systemd is usually a better choice than manually managing a background process.

Why This Is Useful

The most important benefit is not convenience at the command line.

It is architectural.

Suppose an application originally stores files under:

/var/lib/application/assets/

The application may have no reason to care where those files actually live.

If the storage implementation is expressed through normal filesystem operations, the same application can potentially use:

Local disk
|
+-- /var/lib/application/assets

S3
|
+-- /mnt/s3/assets

The application can continue using the same file APIs.

The storage backend becomes an operational concern rather than an application concern.

This can be particularly useful when moving an application from a single machine to an environment where object storage is preferable because of capacity, durability, replication, or operational simplicity.

It Is Not a Real POSIX Filesystem

There is, however, an important caveat.

An S3 bucket is not a POSIX filesystem.

Mounting it through rclone does not change that fact.

The filesystem interface is an abstraction layer translating filesystem operations into object-storage operations.

That distinction matters.

A local filesystem naturally supports operations such as:

  • random writes
  • in-place modification
  • atomic rename
  • directory traversal
  • file locking
  • low-latency metadata operations

Object storage has a fundamentally different model.

An object is generally addressed by a key, and the storage service is optimized for operations on complete objects rather than arbitrary byte ranges and filesystem metadata.

As a result, filesystem semantics exposed through a mounted S3 backend may have different performance characteristics or behavioral limitations.

This is why an S3 mount should not automatically be treated as a replacement for a local filesystem.

Choosing the Right Workload

The model works particularly well when files are relatively independent objects.

Examples include:

  • static assets
  • images
  • documents
  • backups
  • archives
  • media files
  • large generated files
  • content repositories

It is much less attractive for workloads that depend heavily on filesystem semantics.

For example, using an S3 mount as the storage layer for a database's data directory is generally a bad idea.

A database may depend on:

  • low-latency random I/O
  • precise filesystem semantics
  • file locking
  • frequent metadata operations
  • atomic operations
  • predictable fsync behavior

Object storage is designed around a different set of trade-offs.

The abstraction is useful precisely because many applications do not need the full complexity of a database workload.

Performance Considerations

A mounted object store inevitably introduces additional latency.

A local filesystem operation may involve a few kernel-level operations and a storage-device access.

An operation against a mounted S3 backend can instead involve:

Application
|
v
VFS
|
v
FUSE
|
v
rclone
|
v
HTTP
|
v
S3 service

Network latency therefore becomes part of the filesystem operation.

Caching can reduce some of the overhead, and rclone provides various cache-related options, but caching should be configured according to the workload rather than enabled blindly.

The key question is not:

"Is S3 as fast as a local filesystem?"

It is not.

The useful question is:

"Is the performance of an S3-backed filesystem sufficient for this workload?"

For many asset-oriented workloads, the answer can be yes.

The Interesting Part: Decoupling

The deeper lesson is not really about rclone.

It is about interfaces.

Applications often become unnecessarily coupled to infrastructure because developers expose the storage provider directly to the application.

For example:

Application
|
+-- S3 SDK
|
+-- bucket logic
|
+-- object key generation
|
+-- S3-specific error handling

Once this design is established, changing the storage backend becomes an application-level change.

Using a filesystem interface creates a different boundary:

Application
|
| filesystem API
v
Storage interface
|
+-- local filesystem
+-- rclone/S3
+-- other filesystem backend

The application only depends on the abstraction it actually needs.

The implementation can change underneath it.

This is an old Unix idea, but it remains remarkably useful.

A Useful Engineering Shortcut

There is a tendency to build a dedicated abstraction layer whenever two systems have different interfaces.

Sometimes that is exactly the right solution.

Sometimes a mature adapter already exists.

In the case of S3 and filesystem access, rclone provides a remarkably practical bridge.

Instead of rewriting an application around an object-storage API, it is possible to keep the application using ordinary filesystem operations and move the storage adaptation to the infrastructure layer.

That means fewer application-specific storage APIs, less backend-specific code, and a simpler deployment model.

The important qualification is that this should be treated as an interface adaptation, not as a transformation of S3 into a genuine POSIX filesystem.

Final Thoughts

S3 is an object store.

A filesystem is a filesystem.

They have different semantics and different performance characteristics.

But applications do not always need to know which one is underneath.

When the workload is fundamentally file-oriented and does not require strict local-filesystem semantics, mounting an S3-compatible backend with rclone can be a surprisingly effective solution.

The most useful part is not the command itself:

rclone mount my-s3:your_bucket_name /mnt/s3

It is the architectural possibility behind it:

Keep the application dependent on the simplest interface it actually needs, and let the infrastructure adapt the storage underneath it.

Sometimes the best abstraction is the one you do not have to write yourself.