Record StoreRecord Store
Apache-2.0 · Self-hosted · Developer Preview

S3-compatible object storage.One process. One server.

Record Store is a self-hosted object storage service written in Rust. No external database, no message broker, no coordination service alongside it. Your applications keep the AWS SDK they already use — you change the endpoint.

Brought to you by the people of Open Elements®.

Record Store
Quickstart

Pull the image, keep your SDK.

Production images for linux/amd64 and linux/arm64 are published to the GitHub Container Registry. Both packages are public — no docker login.

Record Store ships with no built-in credentials. You set them, and it starts.

docker pull ghcr.io/openelementslabs/record-store:0.1.1
docker pull ghcr.io/openelementslabs/record-store-console:0.1.1

docker compose --env-file .env \
  -f deploy/docker/compose.ghcr.yml up -d
  • 7600

    S3 API, also serves embeds

  • 7601

    Management API, keep it private

  • 7602

    Web console and share pages

Every listener is configurable. Objects live under one data directory as ordinary files — back it up the way you back up everything else.

What Record Store does

The S3 surface your SDK expects

SigV4 header auth and presigned GET/PUT, streaming objects, ListObjectsV2 with pagination, multipart uploads, bucket versioning with delete markers, per-bucket CORS, CopyObject, byte ranges, conditional headers and SHA-256 checksum validation.

Checked against the real clients

Compatibility runs against boto3, the AWS SDK for JavaScript v3 and the AWS SDK for Go on a live server — bucket and object I/O, listing, multipart completion, presigned requests, browser CORS, ranges, versioning and copy behaviour.

Credentials, policies and an audit trail

Service accounts with rotatable credentials, allow/deny policies where explicit deny wins, temporary credentials, and management roles held separately from S3 access. Storage events go out as HMAC-signed webhooks; deletions are audited.

Encryption at rest, under your key

Chunked AES-256-GCM with a per-object data key wrapped by a master key you supply and control. Record Store never stores that key, and refuses to start rather than making encrypted data silently unreadable.

Share links and embeds, not credentials

A share link gives a person read access to one object through a Record Store page; an embed link gives a site a read-only URL for the bytes. Both are revocable capabilities that name exactly one object — they can never list, write or delete.

What it does not do

Being precise about this is more useful than a longer feature list.

A deployment is one process with one copy of your data. Durability is whatever the storage underneath it gives you — use redundant disks and take backups. Erasure coding is not implemented, and if the machine is gone the service is down until you restore it.

ACLs, Object Lock, UploadPartCopy, server-side encryption headers and AWS's aws-chunked trailing checksums are not implemented. Unsupported operations return an S3 NotImplemented error — they are never silently accepted.

Browser uploads through the console are not resumable. An interrupted upload has to be sent again from the first byte, and the console says so instead of implying otherwise.

Client code

Point the endpoint at 7600. That is the integration.

Use path-style addressing and any credential the deployment authorises. Guides for JavaScript, Next.js, Python, Go and Rust are in the documentation.

JavaScript
const s3 = new S3Client({
  endpoint: "http://localhost:7600",
  region: "us-east-1",
  forcePathStyle: true,
  credentials: { accessKeyId, secretAccessKey }
});
Python
s3 = boto3.client(
    "s3",
    endpoint_url="http://localhost:7600",
    aws_access_key_id=key,
    aws_secret_access_key=secret,
)
Go
client := s3.NewFromConfig(cfg, func(o *s3.Options) {
    o.BaseEndpoint = aws.String("http://localhost:7600")
    o.UsePathStyle = true
})
AWS CLI
aws configure set s3.addressing_style path
aws --endpoint-url http://localhost:7600 \
  s3 cp ./example.pdf s3://demo/example.pdf

Open source, Apache-2.0.Run it this afternoon.