Self-hosted, S3-compatible
object storage.

Keep files, backups and app data on your own server. Cairn speaks the S3 API, stores everything as normal files, and runs as one binary — no external database or cluster.

What it is

A single-node object store that speaks S3

Point any S3 client at it — the AWS CLI, an SDK, or the built-in console — and it keeps your data as files on a normal disk. A small SQLite database holds the index and settings, not the data itself.

Your files, your disk
Objects are ordinary files on disk, not a proprietary store. Cairn handles compression and encryption; use S3 or the CLI to export the original bytes.
A small database, not a server
SQLite holds the index and settings. If the index is lost, Cairn rebuilds it from the object files at startup.
One binary
Server, console and CLI in one file. A distroless container image is published too.
Architecture

How it works

Cairn is one process, one data folder and one small database. Requests come in through two ports, are checked, and are written as normal files.

Clients
S3 SDKsAWS CLICairn CLIBrowser console

Anything that speaks S3 can connect. The console and CLI use the same API.

Request path
authenticatecheck policystream the bodyencrypt

Requests arrive on :7373 (S3 and admin) or :7374 (console). They are authenticated, checked against policy, then streamed to disk. Encryption happens on the way in and out.

Index
one writerparallel readsSQLite indexsettings + activity

A small SQLite database holds the index, settings and activity log. One writer keeps writes ordered; reads run in parallel.

Files
normal filesflush to diskatomic movechecksum

Objects are files. Cairn flushes each file to disk before it records the object, so the file is the source of truth.

Background
replicationlifecycle + TTLwebhookscleanupintegrity check

Replication, expiry, webhooks and cleanup run in the background, driven by a durable queue.

Cairn writes the file first, flushes it, and only then says the write succeeded. The database row is an index; if it is lost, startup rebuilds it from the files. That is why an acknowledged write survives a crash.

1write a temp file2flush to disk3move into place4record it5clean up

The object is safe before the database row exists. New objects carry a BLAKE3 checksum; older objects keep SHA-256. The storage format is one-way after v42 — restore a snapshot to go back.

Features

What it does

S3 API
Buckets, objects, versions, large uploads, range reads, checksums, tags, lifecycle, Object Lock and shareable links. Standard S3 clients work unchanged.
Web console
Browse, upload, preview and share from the browser. Manage buckets, users and settings. Turn it off and the API still works.
Access control
Bucket and user policies, access lists (ACLs), Block Public Access, ownership controls and temporary credentials.
Security & encryption
TLS, encrypted secrets, and server-side encryption at rest. The AWS KMS option is a label over the node key, not a separate key service.
Durability
Files are flushed to disk before Cairn says yes. The database catches up; if it is lost, startup rebuilds it from the files.
Storage efficiency
Optional compression that still supports range reads. Large uploads can finish faster on XFS or btrfs.
Operations
Metrics, health checks, replication, webhooks, import, quotas and object expiry. Backup and restore from the CLI.
Console

What it looks like

The console ships in the same binary. These are real screens from a running node — browse and share objects, manage buckets and users, and check health and activity.

Buckets, objects, storage and node health at a glance.
Buckets, objects, storage and node health at a glance.
Browse, preview, share or delete objects.
Browse, preview, share or delete objects.
Preview images, video, PDFs, Markdown, JSON and text in place.
Preview images, video, PDFs, Markdown, JSON and text in place.
Edit bucket policy, ownership and public-access settings.
Edit bucket policy, ownership and public-access settings.
Encryption, Object Lock and lifecycle rules per bucket.
Encryption, Object Lock and lifecycle rules per bucket.
Create short-lived, scoped credentials.
Create short-lived, scoped credentials.
Requests, errors, throughput and latency over time.
Requests, errors, throughput and latency over time.
See every tag in use and the objects that carry it.
See every tag in use and the objects that carry it.
An audit log of admin actions, with actor, bucket and key.
An audit log of admin actions, with actor, bucket and key.
Replication rules and remote targets.
Replication rules and remote targets.
Performance

Measure the workload you run

We compare Cairn with RustFS and MinIO's warp on the same host, with the same workload. Results depend on the hardware, object size and durability settings, so read the ratios, not just the absolute numbers.

On our shared test host, Cairn was faster than RustFS on every equal-durability workload: 2.24× on 4 KiB writes, 1.14× on 1 MiB writes, 1.92× on 1 MiB reads, 5.33× on listing 1,000 keys, 1.07× on multipart uploads, and 5.17× on versioned deletes.

The unversioned delete row is not an equal-durability comparison. The benchmark record has the method, limitations and reproduction commands; the scaling guide covers sizing limits.

Why Cairn

Built to replace a single-node MinIO

If you run a single-node MinIO, Cairn is a simpler replacement: one binary, normal files, a built-in console and async replication — without a cluster to operate.

Written in Rust
Fast, predictable and memory-safe.
Self-contained
Console and CLI live inside the binary; nothing extra to deploy.
Honest about limits
Single-node by design. The trade-offs are written down, not hidden.
Scope

Single-node by design

That is deliberate — it keeps the system small and easy to run.

  • Need a copy elsewhere? Use async bucket replication. It is not a cluster, and it does not fail over automatically.
  • Disk redundancy is your filesystem's job: ZFS, RAID or a replicated volume.
  • Supported: Linux 5.6+ on x86_64 or arm64. XFS is recommended; ext4 works. Backups and a tested restore are required.
  • Format: new objects use a fast BLAKE3 checksum; older objects keep SHA-256. The format is one-way after v42 — restore a snapshot to go back.
  • Not built in: login rate limiting. Put a proxy or firewall in front of a public endpoint. The AWS KMS option is a label, not a separate key service.
  • Best for homelabs and small-to-mid production.

Full supported scope and operational limits are in the support statement.

Get started

Deploy Cairn

Requires Linux 5.6+ on x86_64 or arm64. The installer sets up Docker or a host service, creates credentials and a key, and keeps both ports on localhost.

curl -fsSL https://raw.githubusercontent.com/Harsh-2002/Cairn/main/install.sh | sudo sh

Run with Docker

Create cairn.env once. It holds the master key and admin secret; keep it out of version control and reuse it with the data volume.

(umask 077; set -C
  printf '%s\n' \
    "CAIRN_MASTER_KEY=$(openssl rand -hex 32)" \
    "CAIRN_ROOT_ACCESS_KEY=cairn" \
    "CAIRN_ROOT_SECRET_KEY=$(openssl rand -hex 24)" \
    > cairn.env
)

The image runs as nonroot and stores data in /data. Start it:

docker run -d --name cairn \
  -p 127.0.0.1:7373:7373 -p 127.0.0.1:7374:7374 \
  -v cairn-data:/data --env-file ./cairn.env \
  ghcr.io/harsh-2002/cairn:latest

Open http://localhost:7374 and sign in with cairn and the secret from cairn.env. For remote access, use TLS and the ingress guide. Upgrading? Follow the upgrade and rollback guide.

Configuration

Configure with the environment

Cairn uses CAIRN_* environment variables: no config file, no server flags. Unknown names or bad values fail at startup, and cairn validate-config checks the environment first.

VariableDefaultWhat it's for
CAIRN_MASTER_KEYa dev key (insecure)A 32-byte hex key for encrypting secrets. Set it once and keep it safe; the built-in key is for local tests only.
CAIRN_ROOT_ACCESS_KEYcairnThe admin access key. The default is fine for local use; change it for a public node.
CAIRN_ROOT_SECRET_KEYcairnadminThe admin secret. Change it before exposing the node.
CAIRN_API_ADDR0.0.0.0:7373S3 and the admin API. Health, metrics and temporary credentials live here too.
CAIRN_CONSOLE_ADDR0.0.0.0:7374The web console. Set to off for API-only operation.
CAIRN_DATA_DIR./dataWhere object files live; /data in the container.
CAIRN_DB_PATH./data/cairn.dbThe SQLite index; /data/cairn.db in the container.
CAIRN_TLS_CERT_PATH / _KEY_PATHunsetSet both for built-in TLS; otherwise use a TLS-terminating proxy.
CAIRN_ENCRYPT_AT_RESToffEncrypt every object on disk, even when the client does not ask for it.
CAIRN_META_SYNCHRONOUSfullfull flushes the index before saying yes. normal is faster but can lose recent admin or settings changes; objects are rebuilt from disk.

That's the common set. Replication workers, object TTL, scrubbing, lifecycle, webhooks, KMS and sharding are in the full CAIRN_* reference.

Upgrading? Old listener and URL names are rejected; follow the configuration migration. The CLI uses --api-endpoint or CAIRN_API_ENDPOINT.

Usage

Use it with the AWS CLI

The aws CLI and the AWS SDKs work unchanged — just point them at the endpoint. Configure a profile with the keys from your installer or cairn.env:

aws configure --profile cairn

Then use normal bucket and object commands:

# A short alias for the endpoint
alias s3="aws --profile cairn --endpoint-url http://localhost:7373"

s3 mb s3://demo                        # create a bucket
s3 cp ./report.pdf s3://demo/          # upload a file
s3 ls s3://demo/                       # list objects
s3 cp s3://demo/report.pdf ./out.pdf   # download it back
s3 sync ./site s3://demo/site          # sync a directory
s3 presign s3://demo/report.pdf --expires-in 3600   # shareable link

Multipart uploads, range reads, versions, tags and presigned links work. See the S3 API matrix for the exact surface.

Releases

One version, always the latest

Cairn uses calendar versions (vYYYY.MM.DD). Older releases and tags are retired, so the latest release is the supported one. Releases are cut manually, only after CI is green.

Binaries and the container image are signed, with checksums, a software bill of materials (SBOM) and build provenance. See the verification guide before deploying.

Current status: 1.0 for a single node with backups and a tested restore. The evidence and limits are in the stability record and support statement. The binary reports its version and checks for updates hourly; turn that off with CAIRN_UPDATE_CHECK_ENABLED=false.