RustFS — Components Deep Dive

A study guide to RustFS, an open-source, S3-compatible distributed object store written in Rust: what each component is, the commands and settings you will actually use, when to use it, the traps, and where the docs live.

How to read this guide. Each component has (1) a mental model, (2) the code or config, (3) a when to use / when not to verdict, (4) traps and (5) 📖 doc links. The decision tables are in §2 (which deployment mode) and §11 (should I use RustFS at all). The sibling page Prefect — Components Deep Dive covers an orchestrator that can use an S3-compatible store for results and code. Version note: written 23 Oct 2026 from docs.rustfs.com. The S3 compatibility page was snapshotted by RustFS against a commit dated 9 Aug 2026, so treat counts as a moving target. ⚑ marks items from prior knowledge or inference rather than the pages I read (boto3 usage, exact Prefect wiring). Read §11 before adopting: this is a young project, so verify production readiness yourself.


0. The map: what RustFS is

Analogy: a warehouse of labelled bins with a front desk that speaks Amazon's language. Customers (applications) hand over boxes (objects) with a bin label (bucket) and a shelf label (key). The front desk (the S3 API) uses the same forms as Amazon's warehouse, so existing tools just work. Behind the desk, each box is split into pieces and spread over many shelves (disks) so a few broken shelves do not lose anything.

Addressing. Path-style by default (http://host:9000/my-bucket/path/to/hello.txt). For virtual-host style (https://my-bucket.s3.example.com/hello.txt) set RUSTFS_SERVER_DOMAINS=s3.example.com and create wildcard DNS (*.s3.example.com) pointing at RustFS.

📖 Docs home · S3 protocol · Virtual-host access · GitHub


1. Installing it

GoalPath
Try it locallyOne-command install script, or a container
Single-server productionSNSD (one disk) or SNMD (several disks), on Linux
Multi-server productionMNMD after the pre-installation checklists
KubernetesHelm chart (standalone or distributed) or the RustFS Operator (tenants, pools, KMS)
Windows or macOSNative install; the Windows build is for development and debugging only

1.1 Docker, the fastest start

docker volume create rustfs-data
docker run -d --name rustfs --restart unless-stopped \
  -p 9000:9000 -p 9001:9001 -v rustfs-data:/data \
  -e RUSTFS_ACCESS_KEY='<your-access-key>' -e RUSTFS_SECRET_KEY='<your-secret-key>' \
  -e RUSTFS_ADDRESS=':9000' -e RUSTFS_CONSOLE_ADDRESS=':9001' -e RUSTFS_CONSOLE_ENABLE=true \
  rustfs/rustfs:latest /data
curl --fail http://localhost:9000/health         # S3 API health; Console on :9001

📖 Installation · Docker · Linux · Kubernetes · Checklists · TLS · Reverse proxy


2. Deployment modes: which one?

ModeNodesDisksFault toleranceUse for
SNSD11None. Rely on backupsDev, test, small non-critical
SNMD1SeveralUp to M parity disks inside the node; the node itself is a single point of failureMid-sized non-critical on one server
MNMD4 or moreSeveral per nodeDisk- and node-level via erasure coding across serversProduction

Decision rule: if losing a server or its data would hurt, you need MNMD plus a backup or replication strategy (erasure coding protects against disk failures, not against deletion, corruption by software, or a lost site). SNSD is a development tool, not a storage strategy.

Disk preparation (Linux). Use dedicated data disks, format, mount and verify them before installing (the docs refer to XFS and a verification step); keep identical service environment configuration on every node. Work through the hardware, network, software and security checklists first.

📖 SNSD · SNMD · MNMD · Disk preparation · Hardware selection


3. Erasure coding and capacity

Analogy: a jigsaw with spare pieces. Each object is cut into N-M data pieces plus M extra 'parity' pieces, then spread across N disks. Any N-M of the N pieces rebuild the object, so up to M pieces can be lost.

Drives per set (N)Automatic STANDARD parityApprox. efficiency
1EC:0100%
2-3EC:150-67%
4-5EC:250-60%
6-7EC:350-57%
8-16EC:450-75%
# /etc/default/rustfs
RUSTFS_STORAGE_CLASS_STANDARD=          # recommended: leave empty for automatic per-pool parity
# or pin explicitly (must be valid for the NARROWEST pool):
RUSTFS_STORAGE_CLASS_STANDARD=EC:4
RUSTFS_STORAGE_CLASS_RRS=EC:1           # REDUCED_REDUNDANCY writes; default 1 parity on multi-drive sets
RUSTFS_ERASURE_SET_DRIVE_COUNT=16       # pin set width only if you verified the whole layout

Trap. More parity buys durability at the price of usable capacity and write cost; do not pin high parity on small sets without checking the efficiency. Leaving the default is the documented recommendation unless you have a validated requirement.

📖 EC configuration · Status check · Storage env vars


4. Configuration surface

SettingPurpose
RUSTFS_ACCESS_KEY / RUSTFS_SECRET_KEYRoot credentials. Set unique values
RUSTFS_ADDRESSS3 API bind address (default :9000)
RUSTFS_CONSOLE_ADDRESS, RUSTFS_CONSOLE_ENABLEConsole bind address and switch (port 9001)
RUSTFS_VOLUMESThe storage endpoints; supports {1...4} range expansion for multi-node
RUSTFS_SERVER_DOMAINSDomain for virtual-host style access
RUSTFS_TLS_PATHDirectory with certificates
RUSTFS_STORAGE_CLASS_*, RUSTFS_ERASURE_SET_DRIVE_COUNTErasure coding (§3)
RUSTFS_OBS_*Logging and observability (level, log directory)

The reference page also lists variables for KMS, the scanner, healing and event targets. rustfs has subcommands and server flags with environment equivalents (CLI reference). Keep the same environment file on every node.

📖 Environment variables · CLI reference · CORS


5. The S3 API and compatibility

Analogy: speaking a dialect. RustFS speaks Amazon S3 well enough for most everyday conversation, but not every idiom. The project says so itself: it is a tested subset, not a claim of full coverage.

# AWS CLI against RustFS: just add --endpoint-url
aws --endpoint-url "$RUSTFS_ENDPOINT" s3 cp hello.txt s3://my-bucket/path/to/hello.txt
aws --endpoint-url "$RUSTFS_ENDPOINT" s3 ls s3://my-bucket/
aws --endpoint-url "$RUSTFS_ENDPOINT" s3api head-object --bucket my-bucket --key path/to/hello.txt
aws --endpoint-url "$RUSTFS_ENDPOINT" s3 presign s3://my-bucket/path/to/hello.txt

# Python (boto3)  ⚑
import boto3
s3 = boto3.client('s3', endpoint_url='http://localhost:9000',
                  aws_access_key_id=KEY, aws_secret_access_key=SECRET, region_name='us-east-1')
s3.upload_file('hello.txt', 'my-bucket', 'path/to/hello.txt')
AreaStatus in the compatibility gate
Bucket create/delete/list/inspect, tagging, policies, public access blockTested
Object put/get/copy/head/delete, listing (prefix, delimiter, marker, max-keys; V1 and V2)Tested
Range and conditional reads, user metadata, object tags, presigned GET/PUTTested
Multipart create/upload/complete/abort; selected copy and checksum casesTested
Selected versioning, Object Lock, CORS and lifecycle cases; SSE-C and selected SSE-KMSTested (only the cases in the implemented lists)
Bucket access logging, bucket ownership controls, POST Object form checksum handlingPlanned (not implemented)
ACL authorisationExcluded: intentionally unsupported
Multipart upload listing and part-lookup edge casesExcluded from the default gate

Practical advice: if you depend on ACLs, bucket access logging, or exotic multipart listing behaviour, test those exact calls against RustFS before committing. Use rclone or your SDK's integration test suite as a smoke test.

📖 S3 compatibility matrix · SDKs · Python · SFTP · WebDAV


6. Data management features

FeatureWhat it doesUse it forGotcha
VersioningKeeps prior versions; deletes create markersRecover from overwrites and accidental deletesStorage grows; required by replication
Object LockRetention periods and legal holds on versioned objectsWORM and compliance retentionNeeds versioning; test retention modes before relying on them
Lifecycle rulesExpire or transition objects by ageCost control, log retentionManaged with the rc client; verify rules fire
Tiered storageLifecycle-driven transition to a remote storage tierMove cold data to cheaper storageReads of tiered objects depend on the remote tier
Bucket quotaHard storage quota per bucketMulti-tenant limitsHard limit: writes fail at the cap
Bucket replicationAsynchronous replication between versioned bucketsCopies in another clusterAsync, so a failover can lose the last writes; both ends need versioning
Site replicationMulti-site replication managed with rcDisaster recovery across sitesPlan network and consistency expectations
Multipart uploadParts for large objects; Console task monitorBig files, resumable uploadsIncomplete uploads consume space; clean up
ScannerBackground object scan with a bit-rot cycle and metricsDetect silent corruptionWatch its metrics to confirm scans still run
S3 TablesTable buckets with a built-in Iceberg REST catalogLakehouse without a separate catalogNewer feature; test with your engines (PyIceberg, Spark docs exist)
Event notificationsFiltered bucket events to external targets (webhook and others)React to uploads, trigger pipelinesTargets and queue directories need persistent storage

📖 Versioning · Object Lock · Lifecycle · Tiering · Quota · Bucket replication · Site replication · Scanner · S3 Tables · Event notifications


7. Security

Analogy: badges, keys and a locked cabinet. IAM decides who may enter which room (badges). Encryption keeps the contents unreadable even if someone steals a disk (locked cabinet). TLS protects the hallway.

Traps. Default credentials left in place. Exposing the Console (9001) to the internet. Putting RustFS behind a reverse proxy that rewrites the Host header without enabling the matching virtual-host settings. Losing the KMS key means losing the data.

📖 Security and compliance · IAM · Service accounts and STS · Encryption · OIDC · Audit · Credentials


8. Operations

Runbook items to write before go-live: disk replacement, node replacement, credential rotation, certificate renewal, capacity alert thresholds, upgrade order, restore test from backup or replica.

📖 rc client · Observability · Scaling · Node healing · Drive failures · Node failures · Upgrade · Cluster lifecycle


9. Integrations relevant to a data platform

RustFS documents step-by-step integrations (mostly Docker Compose based) for tools that speak S3. Grouped by purpose:

PurposeTools with a RustFS guide
Orchestration and ingestionAirflow (S3 provider), DolphinScheduler, SeaTunnel, Kafka Connect S3 sink, AutoMQ
Lakehouse and queryApache Iceberg (Spark, REST catalog), PyIceberg via S3 Tables, Delta Lake (delta-rs), Hudi, Paimon, Hive, Spark, Flink, Trino, DuckDB (httpfs), ClickHouse (S3 disk), Databend, Doris, lakeFS
Vector and MLLanceDB, Milvus, MLflow artifact store, Ray Data, vLLM model weights
Observability storageLoki, Tempo, Thanos, Cortex, OpenObserve, GreptimeDB, Fluentd, OpenTelemetry, VictoriaMetrics backups
Backup and DRRestic, Kopia, Velero, Longhorn, Vitess
DevOps and platformTerraform state with locking, Elasticsearch and OpenSearch snapshots, Gitea LFS, Jenkins artifacts, Harbor and Docker Registry, Flux, Nextcloud
Filesystem viewss3fs-fuse, rclone, JuiceFS, ZeroFS (NFS), Alluxio cache, SFTPGo, OpenDAL

9.1 Using it with Prefect ⚑

Prefect can keep results and deployment code in S3-compatible storage through the prefect-aws integration. Because RustFS speaks S3, the wiring is the integration's S3 bucket block with a custom endpoint URL pointing at RustFS and a service-account key. I wrote this from how prefect-aws normally works, not from a tested RustFS example; check the prefect-aws docs for the current block and client-parameter names and run a write/read round trip before trusting it.

📖 Integrations index · Airflow · Iceberg · DuckDB · Spark · lakeFS · Terraform state · rclone · prefect-aws


10. Moving data in and out


11. Should you use RustFS? (the part to challenge)

SituationVerdict
Local dev and CI needing an S3 endpointGood fit. One container, quick to start
Self-hosted S3 for logs, artefacts, backups, ML datasets where a permissive licence mattersReasonable, after your own load and failure tests
Data lake or lakehouse storage with Iceberg or DeltaPlausible; documented integrations exist, but pilot with your engines and table sizes
Regulated or business-critical primary storageProceed carefully. Confirm KMS maturity, Object Lock behaviour, support terms and your recovery drills
Need full AWS S3 feature parity (ACLs, access logging, every multipart listing edge)Not a fit where those are documented as excluded or planned
Cloud-native workload already on a managed S3Staying on the managed service removes operations; self-host only for cost, sovereignty or latency reasons

Questions to answer before adopting: (1) Is the benefit the licence, the cost, performance, or Rust itself, and have you measured it? (2) Who is on call when a node dies at 3 a.m.? (3) Have you rehearsed a disk and node replacement and a restore? (4) What is the backup strategy beyond erasure coding? (5) How mature is the release you pin, and what is the upgrade policy? Pin a version rather than using :latest in production.


12. Trap checklist and exercises

  1. Default credentials; Console exposed publicly.
  2. Bind-mount directory not owned by UID 10001.
  3. Believing EC:4 equals four-node tolerance.
  4. Pinning parity that the narrowest pool cannot satisfy (startup fails), or setting a set width that does not divide the topology.
  5. SNSD or SNMD treated as production, with no backup.
  6. Replication configured without versioning; async replication assumed to be lossless.
  7. Relying on ACLs, access logging or encrypted-object portability.
  8. Using :latest; no upgrade rehearsal; no restore test.
  9. Windows build used in production.

Exercises. (1) Start the Docker command with unique credentials, create a bucket and upload a file with the AWS CLI using --endpoint-url. (2) Enable versioning, overwrite the file, and recover the first version. (3) Compute usable capacity for 8 nodes x 4 x 8 TiB drives if sets are 16 wide with EC:4, and say what a node loss does to a set. (4) Add a lifecycle rule to expire objects under tmp/ after one day and verify. (5) Run a write/read round trip from a Python script with boto3 and a presigned URL.

Solution notes
  1. Use aws --endpoint-url http://localhost:9000 s3 mb s3://demo, then cp; configure the CLI with the access key pair you set.
  2. Versioning is a per-bucket setting; list versions to see both, then fetch by version ID or remove the delete marker.
  3. Raw is 8 x 4 x 8 = 256 TiB; with a 16-wide set and EC:4 efficiency is 75%, so about 192 TiB before overhead. Whether a node loss is survivable depends on how many of a set's 16 drives sit on that node: if a node holds 4 drives of each set, losing it removes 4 shards, which EC:4 can reconstruct, with no margin left.
  4. Lifecycle rules are managed with rc; confirm by checking the object disappears after the scanner or lifecycle cycle runs.
  5. boto3 needs endpoint_url; generate_presigned_url('get_object', ...) gives a URL you can fetch with curl.

Sources: docs.rustfs.com: docs home, installation, Docker, EC configuration, S3 compatibility matrix, S3 protocol, docs index; GitHub README (claims). Sections 6-8 summarise the documentation index descriptions rather than every page body; items marked ⚑ are unverified.


Revision #1
Created 23 October 2026 15:07:42 by N8N
Updated 23 October 2026 15:07:42 by N8N