post3
S3-compatible object storage you can run anywhere.
post3 is a lightweight, self-hosted S3-compatible storage server written in Rust. Store objects in PostgreSQL or on the local filesystem — your choice, same API. Works with any S3 client: the AWS SDK, the AWS CLI, boto3, MinIO client, or plain curl.
Why post3?
- Drop-in S3 compatibility — 20+ S3 operations, validated against the Ceph s3-tests conformance suite (124 tests passing)
- Two backends, one API — PostgreSQL (objects chunked into 1 MiB blocks) or local filesystem. Swap at startup with a flag.
- Zero external dependencies for FS mode — No database, no message queue, no cloud account. Just the binary and a directory.
- Multipart uploads — Full support for creating, uploading parts, completing, aborting, and listing multipart uploads. 5 GiB body limit.
- Custom metadata —
x-amz-meta-*headers preserved and returned on GET/HEAD - Rust SDK included — Ergonomic client wrapping
aws-sdk-s3with sane defaults. One-liner setup. - Built on proven foundations — axum, tokio, sqlx, tower. Production-grade async Rust.
Quick Start
Filesystem backend (no database needed)
# Build and run
PostgreSQL backend
# Start PostgreSQL and the server
Try it out
# Create a bucket
# Upload an object
# Download it
# List objects
# Delete
Or use the AWS CLI:
Rust SDK
[]
= { = "crates/post3-sdk" }
use Post3Client;
let client = new;
client.create_bucket.await?;
client.put_object.await?;
let data = client.get_object.await?;
assert_eq!;
// Large files — automatic multipart upload
client.multipart_upload.await?;
// List with prefix filtering
let objects = client.list_objects.await?;
Since post3-sdk re-exports aws_sdk_s3, you can drop down to the raw AWS SDK for anything the convenience API doesn't cover.
Supported S3 Operations
| Category | Operations |
|---|---|
| Buckets | CreateBucket, HeadBucket, DeleteBucket, ListBuckets, GetBucketLocation |
| Objects | PutObject, GetObject, HeadObject, DeleteObject |
| Listing | ListObjects (v1 & v2), ListObjectVersions, delimiter/CommonPrefixes |
| Batch | DeleteObjects (up to 1000 keys) |
| Multipart | CreateMultipartUpload, UploadPart, CompleteMultipartUpload, AbortMultipartUpload, ListParts, ListMultipartUploads |
| Metadata | Custom x-amz-meta-* headers on PUT, returned on GET/HEAD |
Architecture
crates/
post3/ Core library — StorageBackend trait, PostgresBackend,
FilesystemBackend, models, migrations
post3-server/ HTTP server — axum-based, generic over any StorageBackend
post3-sdk/ Client SDK — wraps aws-sdk-s3 with ergonomic defaults
ci/ CI pipeline — custom Dagger-based build/test/package
The server is generic over B: StorageBackend. Both backends implement the same trait, so the HTTP layer doesn't know or care where bytes end up.
PostgreSQL backend splits objects into 1 MiB blocks stored as bytea columns. Seven tables with ON DELETE CASCADE for automatic cleanup. Migrations managed by sqlx.
Filesystem backend uses percent-encoded keys, JSON metadata sidecars, and atomic writes (write-to-temp + rename). No database required.
S3 Compliance
post3 is validated against the Ceph s3-tests suite — the same conformance tests used by Ceph RGW, s3proxy, and other S3-compatible implementations.
124 passed, 0 failed, 0 errors
Run them yourself:
Development
Requires mise for task running.
Examples
Configuration
| Variable | Default | Description |
|---|---|---|
POST3_HOST |
127.0.0.1:9000 |
Address to bind |
DATABASE_URL |
— | PostgreSQL connection string (pg backend) |
--backend |
pg |
Storage backend: pg or fs |
--data-dir |
— | Data directory (fs backend) |
License
Licensed under the MIT License.