# Zenko CloudServer: S3 Compatibility Across Multiple Storage Backends

> Zenko CloudServer gives applications one Amazon S3 API while routing data to local, memory, or multiple storage backends. It fits local S3 emulation and storage abstraction work, but its Node.js requirements currently conflict between the README and `package.json`.

**scality/cloudserver** — Zenko CloudServer, an open-source Node.js implementation of the Amazon S3 protocol on the front-end and backend storage capabilities to multiple clouds, including Azure and Google.

- Repository: https://github.com/scality/cloudserver
- Website: https://www.zenko.io/cloudserver
- Stars: 1,954 · Forks: 259
- Language: JavaScript
- License: Apache-2.0
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/scality-cloudserver

## Why CloudServer Places One S3 Endpoint Over Different Storage

Zenko CloudServer addresses a specific interoperability problem: applications often expect Amazon S3 requests, while the actual object data may need to live on a workstation, in a public cloud, or in more than one storage location. The server exposes an Amazon S3-compatible API and acts as an abstraction between those clients and backend data stores. This makes it relevant to developers who need an S3 service for continuous integration tests, local application development, or an object-storage gateway in front of several backends.

The project is not presented as a replacement for the full AWS S3 control plane. Its documented focus is the server-side S3 protocol and the ability to select backend storage. The repository includes JavaScript, Python, and Go examples related to metadata search, while `package.json` declares the package as `@scality/cloudserver`. The README calls CloudServer, formerly S3 Server, part of Zenko and describes Zenko as Scality's open-source multi-cloud data controller.

CloudServer is most useful when the compatibility boundary matters more than direct access to one storage vendor. A client can use S3 operations while CloudServer decides where data is kept. The trade-off is that operators must understand CloudServer's routing rules, credentials, local metadata, data paths, and additional internal ports. It is not simply a local directory that happens to accept S3-shaped requests.

## CloudServer Request Routing and Backend Selection

The file-backed configuration stores metadata in `localMetadata` and object data in `localData`, both under `./S3` by default. Those directories are described as pre-created in the repository. CloudServer also supports replacement absolute paths through `S3DATAPATH` and `S3METADATAPATH`, which separates the two concerns that an application might otherwise assume share one storage volume.

For ephemeral testing, setting `S3DATA=mem` selects an in-memory backend. This is explicitly intended for testing or cases where persistence is unnecessary. Data stored there should therefore be treated as temporary according to the project's stated purpose. The separate `yarn run mem_backend` command provides another documented route for starting with memory storage.

The multiple-backend mode uses `S3DATA='multiple'`. A client can send `x-amz-meta-scal-location-constraint` on a PUT request to choose a location. When that header is absent, the bucket's location constraint determines the destination. If the bucket also has no location constraint, CloudServer uses the PUT endpoint. This fallback chain is useful because it allows several forms of deployment configuration, but it also makes routing dependent on state outside the request. Incorrect location constraints can send an object somewhere other than the operator intended. The repository contains `locationConfig.json` and configuration documentation, so backend names and valid constraints need to be checked before production routing is configured.

## Installing CloudServer and Starting the File Backend

The README provides a source installation path, although its runtime requirement appears outdated relative to the repository metadata. It says building and running requires Node.js 10.x and Yarn v1.17.x. In contrast, the current `package.json` sets `"engines.node": ">=24"`, and the Dockerfile defaults to `NODE_VERSION=24.21.0-bookworm-slim`. This mismatch should be resolved before installation. Following the current package metadata and container definition is more consistent with the repository than following the older README statement.

Clone the repository and install the locked JavaScript dependencies from its root directory:

```bash
git clone https://github.com/scality/cloudserver.git
yarn install --frozen-lockfile
```

The dependency installation can fail around native components. The README specifically recommends installing `g++` if the `diskUsage` module fails and clearing the Yarn cache if `level-down` bindings fail:

```bash
yarn cache clean
```

The README also says TypeScript is needed for `subaclient` and gives this installation command:

```bash
npm install -g typescript
```

After dependencies are available, the documented first server run is:

```bash
yarn start
```

The README says the S3 service starts on port 8000. Ports 9990 and 9991 are also opened locally for internal metadata and data transfer. The default credentials are `accessKey1` and `verySecretKey1`. Treat them as local starting credentials rather than deployment credentials. The server should expose its metadata and data paths under the expected directories, and its S3 endpoint should be available on port 8000. The repository also provides a Docker route, but the README does not include a complete image invocation in the documented text.

## Persistent Paths, Memory Runs, and Multi-Backend Exercises

A useful first exercise is to replace the default file locations while retaining persistent storage. The README requires absolute paths for custom data and metadata directories:

```bash
mkdir -m 700 $(pwd)/myFavoriteDataPath
mkdir -m 700 $(pwd)/myFavoriteMetadataPath
export S3DATAPATH="$(pwd)/myFavoriteDataPath"
export S3METADATAPATH="$(pwd)/myFavoriteMetadataPath"
yarn start
```

This separates object payloads from metadata and allows the operator to place them on different storage paths. The directory mode is set to 700, which limits access to the owner on systems that honor Unix permission modes. The README does not document backup coordination between data and metadata, so an operator cannot assume that moving or restoring one directory alone is sufficient.

For a disposable test server, use the documented memory selection:

```bash
export S3DATA=mem
yarn start
```

To exercise location-based routing, start multiple-backend mode and send the documented location header during a PUT:

```bash
export S3DATA='multiple'
yarn start
```

```http
'x-amz-meta-scal-location-constraint':'myLocationConstraint'
```

The header example is not a complete request, and the README does not provide a full upload command. A reader should therefore use it with an S3 client configured for `http://localhost:8000` and the documented default credentials, then confirm the selected location through the backend configuration. The repository's examples concern metadata search rather than basic upload, so they do not replace an upload tutorial.

## Container Operation and Backend Boundaries

The repository includes a Dockerfile and a Docker image reference, but the README does not provide a full run command. The Dockerfile exposes 8000 and 8002, creates `/usr/src/app/localData` and `/usr/src/app/localMetadata` as volumes, and starts `yarn start` through `docker-entrypoint.sh`. This differs from the source README, which also mentions ports 9990 and 9991 for internal transfers. That port difference is a concrete deployment check. An operator should not publish ports solely by copying the source-run description into a container deployment.

The Docker build installs production dependencies in a builder stage using Node.js 24.21.0 by default, then copies `node_modules` into the production image. The container declares persistent volumes for the local data and metadata directories. This supports the file backend, but it does not by itself configure Azure, Google Cloud, Redis, Vault, or every backend listed in the repository context. Those integrations require their own configuration, credentials, and network access.

Vault user management is documented through `S3VAULT=vault`, but the README explicitly states that Vault is proprietary and must be accessed separately. CloudServer should not be adopted on the assumption that this option provides a self-contained open-source user-management stack. Likewise, the multiple-backend mode does not mean that every available backend can be enabled without separate setup.

## Limitations, Maintenance, and Upgrade Work

The clearest limitation is documentation drift. The README requires Node.js 10.x, while `package.json` requires Node.js >=24 and the Dockerfile uses Node.js 24.21.0. Native modules add another installation concern because the README calls out `diskusage`, `level-down`, `g++`, and Yarn cache handling. A clean install therefore depends on the developer's native build environment, not only JavaScript package downloads.

The project is not archived, and the last push was on 2026-10-16. Recent release entries include 9.5.0-preview.5, 7.10.61, and 9.4.7. This indicates recent repository activity, but it does not remove upgrade work. The package uses preview versions in the visible release list, and dependency specifications include version ranges, a Git dependency for `bucketclient`, and a GitHub dependency for `utapi`. Upgrades can therefore involve more than changing a server binary: the lockfile, native bindings, backend credentials, and compatibility between CloudServer and its Arsenal dependencies matter. The Apache-2.0 license permits use and modification under its terms, but operators must review those terms and dependency notices themselves.

Compared with running MinIO directly, CloudServer's distinguishing design is the S3-facing multi-backend layer, including location-constraint routing and metadata transfer. A simpler single-backend deployment may need fewer routing decisions. Compared with AWS S3 itself, CloudServer can run locally and target non-AWS storage, but it does not document full parity with every AWS service feature. Its scope is the documented S3 server protocol and storage abstraction.

## Conclusion

Developers should consider CloudServer when an application needs an S3-compatible endpoint and flexibility across local or cloud storage backends. Operators should not deploy it until they reconcile the README's Node.js 10.x requirement with `package.json`, which requires Node.js >=24, then verify backend routing, persistence, credentials, and exposed ports before adoption.

## FAQ

### How do I install Zenko CloudServer?

The README says to clone the repository and run `yarn install --frozen-lockfile`. It states Node.js 10.x and Yarn v1.17.x are required, but the current `package.json` requires Node.js >=24, so the runtime requirement should be resolved before installation.

### How do I run CloudServer with a persistent file backend?

Run `yarn start` to use the default `localData` and `localMetadata` directories. For custom storage locations, set absolute paths through `S3DATAPATH` and `S3METADATAPATH` before starting the server.

### Can CloudServer use memory storage for testing?

Yes. Set `S3DATA=mem` and run `yarn start`, or use the documented `yarn run mem_backend` command. The README describes the memory backend as useful for testing and for cases where persistent storage is not needed.

## Sources

- [License: Apache-2.0](https://github.com/scality/cloudserver/blob/development/9.6/LICENSE)
- [Project website](https://www.zenko.io/cloudserver)
- [README](https://github.com/scality/cloudserver/blob/development/9.6/README.md)
- [Releases](https://github.com/scality/cloudserver/releases)
- [scality/cloudserver on GitHub](https://github.com/scality/cloudserver)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/scality-cloudserver
