DEV Community

Cover image for Self-Hosting S3-Compatible Storage on Bare Metal
Ethan Carter
Ethan Carter

Posted on

Self-Hosting S3-Compatible Storage on Bare Metal

You self-host S3-compatible storage on bare metal by installing a single Rust binary on a Linux server and pointing any S3 client at it. RustFS installs with one script, listens on port 9000 (S3 API) and 9001 (console), and is Apache 2.0 licensed. Single-node mode is production-ready today; multi-node clustering is still under testing.

Every command below is copied verbatim from the official source cited beside it. This sandbox has no Docker daemon, so none of the commands were executed here; they are marked accordingly.

Key Stats

Fact Source
RustFS installs with one command and runs as a systemd service on x86_64 or aarch64 Linux RustFS docs (Linux quick-start)
Default S3 API port is 9000; console port is 9001 RustFS GitHub README
Default credentials are rustfsadmin / rustfsadmin and must be changed RustFS README + docs
RustFS is Apache 2.0 licensed and S3-compatible RustFS GitHub README
Single-node mode is production-ready; distributed mode is still under testing RustFS README Feature & Status

What is self-hosted S3-compatible storage?

A self-hosted S3-compatible storage server is a program you run on your own hardware that speaks the Amazon S3 API. Applications using AWS SDKs, the aws CLI, or MinIO's mc can talk to it without code changes, because the bucket, object, and credential model matches S3. The difference from a cloud bucket is ownership: the disks, the network path, and the uptime are yours.

RustFS is one such server, written in Rust and licensed under Apache 2.0. It exposes the S3 API on port 9000 and a web console on 9001, and it stores objects on the local filesystem. Because it is S3-compatible, the same client code that targets AWS S3 also targets a RustFS node. That compatibility is the whole point of self-hosting here: you get an S3 endpoint without renting one.

Why run object storage on bare metal?

Running object storage on bare metal means installing the server directly on a Linux machine instead of in a container or a managed cloud. The appeal is control. Your data stays on disks you own, in a network you define, and the cost is the hardware plus your time rather than a per-gigabyte cloud bill that grows with every upload.

The trade-off is real and worth stating plainly. You own the failure modes too. A single disk dies, the server reboots, the certs expire, and that is now your incident, not a vendor's. Bare metal suits teams that already run Linux servers, care about data residency, or have steady high-volume storage that makes a cloud bill painful. It is a poor fit if you want zero operational responsibility. Self-hosting trades a recurring fee for recurring attention.

What you need before you start

Minimum: a Linux server with systemd on x86_64 or aarch64, root or sudo access, the unzip utility, outbound network access to pull the package, and open ports 9000 (S3 API) and 9001 (console) so clients and the browser console can reach the service.

Plan the data disk before you install. The quick-start runs RustFS in single-node, single-disk (SNSD) mode, which stores everything under /data/rustfs0 with no redundancy. That is fine for evaluation and dev, but a single disk has no spare. For anything you would hate to lose, attach a second disk, schedule filesystem or object-level backups, or wait for distributed mode to leave testing. The installer lets you change the data path and ports at install time, so decide the layout now rather than after data accumulates.

How do you install RustFS on bare metal?

Run the official one-line installer. It downloads the binary, installs it to /usr/local/bin/rustfs, registers a systemd service, starts it, and stores data under /data/rustfs0 by default:

curl -O https://rustfs.com/install_rustfs.sh && bash install_rustfs.sh
Enter fullscreen mode Exit fullscreen mode

[sourced from RustFS docs (Linux quick-start), NOT EXECUTED IN CI]

After it finishes you get a summary with the service port (9000), console port (9001), and data directory, plus a security warning to replace the default credentials. Open http://<server-ip>:9001 in a browser to reach the console, then log in with the access and secret keys you set. The same server answers S3 API calls on 9000. From here you can create a bucket in the console or from the command line, which the next sections cover.

How do you run RustFS with Docker instead?

If you prefer a container, the Docker image gives you the same server with no systemd dependency. The official command maps both ports, persists data and logs to local volumes, and detaches:

docker run -d -p 9000:9000 -p 9001:9001 -v $(pwd)/data:/data -v $(pwd)/logs:/logs rustfs/rustfs:latest
Enter fullscreen mode Exit fullscreen mode

[sourced from RustFS GitHub README, NOT EXECUTED IN CI]

Do not drop the -p or -v flags. Without -p 9000:9000 the S3 API is unreachable from the host, and without the volume mounts a container restart loses everything under /data and /logs. The image tag :latest tracks the newest build; pin a specific release like 1.0.0-rc.2 if you need reproducibility. Podman users run the equivalent with :Z,U on the volume mounts for SELinux. Either path lands you at the same console on 9001 and the same S3 endpoint on 9000.

How do you point an S3 client at your server?

RustFS ships its own CLI, rc, which handles both object operations and admin checks. After installing it, register an alias that stores the endpoint and keys, then verify the server is alive:

rc alias set local http://localhost:9000 <your-access-key> <your-secret-key>
rc ping local
rc ready local
Enter fullscreen mode Exit fullscreen mode

[sourced from RustFS docs (rc CLI), NOT EXECUTED IN CI]

Create a bucket and push a file the same way any S3 client would:

rc bucket create local/my-bucket
rc object copy /path/to/hello.txt local/my-bucket/hello.txt
rc object list local/my-bucket
Enter fullscreen mode Exit fullscreen mode

[sourced from RustFS docs (rc CLI), NOT EXECUTED IN CI]

Because the API is S3-compatible, AWS SDKs, the aws CLI with --endpoint-url, and MinIO's mc all work against port 9000 with the same keys. You are not locked into rc; it is just the native client. Point your application at http://<server-ip>:9000 and the buckets behave like any other S3 endpoint.

What RustFS does today, and what it doesn't

RustFS today is a solid single-node S3-compatible server. The features marked available in the project's own status table include S3 core operations, upload/download, versioning, logging, event notifications, bucket replication, bitrot protection, single-node mode, multi-tenancy, Keystone auth, and the Swift API. If your workload fits one node, those are real and usable now.

Be honest about the gaps. Distributed mode, lifecycle management, and RustFS KMS are still under testing, so multi-node erasure-coded clusters and automated tiering or expiry are not production promises yet. There is no Object Lock, no FUSE or POSIX mount, and no built-in erasure coding in the current release. RustFS does not ship a turnkey multi-region setup. For a single bare-metal node serving S3 to your apps, that is plenty. If you need cross-node redundancy or compliance retention today, plan around those limits rather than assuming they exist.

How do you keep a bare-metal server healthy?

First, change the default credentials. The installer leaves placeholder keys in /etc/default/rustfs; set your own access and secret keys there, then restart:

RUSTFS_ACCESS_KEY=<your-access-key>
RUSTFS_SECRET_KEY=<your-secret-key>   # e.g. output of: openssl rand -base64 24
Enter fullscreen mode Exit fullscreen mode
sudo systemctl restart rustfs
sudo systemctl status rustfs --no-pager
Enter fullscreen mode Exit fullscreen mode

[sourced from RustFS docs (Linux quick-start), NOT EXECUTED IN CI]

Keep the service under systemd so it restarts on boot, and watch systemctl status rustfs for the active (running) line. Because single-node mode has no redundancy, back up the data directory or replicate the bucket to a second site on a schedule you trust. Check disk space before it is gone, since a full volume stops writes. None of this is exotic, but it is yours to do. The console on 9001 shows bucket and object state when you want a visual check.

FAQ

Is RustFS free to self-host?

Yes. RustFS is licensed under Apache 2.0, so you can run it on your own hardware at no license cost. You pay only for the server, disks, and your time to operate it.

What are the default RustFS credentials?

The default access key and secret key are both rustfsadmin. The installer warns you to replace them, and if you leave them unset the server falls back to those same defaults. Set RUSTFS_ACCESS_KEY and RUSTFS_SECRET_KEY in /etc/default/rustfs and restart the service before exposing the port.

Can RustFS replace MinIO on a single Linux server?

For single-node S3-compatible needs, yes. Both speak the S3 API, so existing client code and SDKs work against either. RustFS is written in Rust, licensed Apache 2.0, and ships its own rc CLI alongside the standard S3 interface.

Does RustFS support multi-node distributed storage?

Distributed mode is listed as under testing in the project's Feature & Status table, so it is not a production promise yet. Single-node mode is available and production-ready today. If you need cross-node erasure coding now, that gap should factor into your decision.

What port does RustFS use?

The S3 API listens on port 9000 and the web console on 9001. Both must be reachable: 9000 for client and application traffic, 9001 for the browser console.

Top comments (0)