A content-addressable object storage service with strong consistency guarantees, automatic deduplication, and crash-safe operations.
- Overview
- Key Features
- Quick Start
- API Reference
- Architecture
- Deployment
- Operations
- Development
- Documentation Index
- Status & Roadmap
JustStorage is an internal object storage service designed to replace generic S3/GCS usage with a domain-specific, streamlined interface:
Replace generic S3/GCS usage with a domain-specific, streamlined interface designed for internal services:
- Simple API with 10-15 well-defined operations
- Strong consistency with read-after-write guarantees
- Clear cost model without complex pricing tiers
- Optimized for model hosting, knowledge base, and general file storage workloads
- Longhorn + ZFS foundation: Node-level HA, disk redundancy, volume snapshots
- Content-addressable storage: Automatic deduplication, integrity verification
- Two-phase writes: Crash-safe, atomic operations
- Background GC: Deferred cleanup, no read/delete races
- Hot: NVMe-backed for models, active data
- Cold: HDD-backed for archives, bulk storage
POST /v1/objects- UploadGET /v1/objects/{id}- Download by IDGET /v1/objects/by-key/{namespace}/{tenant}/{key}- Download by keyDELETE /v1/objects/{id}- Delete (async GC)GET /v1/objects- List with pagination
This project follows Clean Architecture with clear separation of concerns:
Domain Layer (Core Business Logic)
↑
Application Layer (Use Cases)
↑
Infrastructure Layer (DB, Storage)
↑
API Layer (HTTP Handlers)
Key Principles:
- SRP: Each module has one responsibility
- Dependency Inversion: Domain depends on nothing, infra depends on domain
- Testability: Easy to mock ports for unit testing
- Extensibility: Add new storage backends without touching business logic
See Architecture Overview for detailed architecture documentation.
# Start all services
docker compose up -d
# View logs
docker compose logs -f just_storage
# Test API
curl http://localhost:8080/health- Postgres 14+ with uuid extension
- Rust 1.96 (pinned via
rust-toolchain.toml; minimum supported 1.94, required by sqlx 0.9)
# 1. Copy environment file
cp rust/.env.example rust/.env
# 2. Start PostgreSQL
docker compose up -d postgres
# OR use local PostgreSQL
# 3. Create database and run migrations
make db-setup
# OR manually:
# createdb just_storage
# psql just_storage < schema.sql
# 4. Build and run
cd rust
cargo run --releaseSee Contributing Guide for detailed development guide.
curl -X POST http://localhost:8080/v1/objects \
-H "X-Namespace: models" \
-H "X-Tenant: acme" \
-H "X-Key: example-model" \
-H "X-Storage-Class: hot" \
-H "Content-Type: application/octet-stream" \
--data-binary @model.binResponse:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"namespace": "models",
"tenant_id": "acme",
"key": "example-model",
"content_hash": "sha256:abcdef123...",
"size_bytes": 1073741824,
"storage_class": "hot",
"created_at": "2025-12-11T10:30:00Z"
}# By ID
curl http://localhost:8080/v1/objects/550e8400-e29b-41d4-a716-446655440000 \
-H "X-Tenant: acme" -o model.bin
# By key
curl http://localhost:8080/v1/objects/by-key/models/acme/example-model -o model.bincurl "http://localhost:8080/v1/objects?namespace=models&tenant=acme&limit=50"curl -X DELETE http://localhost:8080/v1/objects/550e8400-e29b-41d4-a716-446655440000 \
-H "X-Tenant: acme"Comprehensive documentation is available in the project wiki:
- Quick Start Guide - Get running in 5 minutes
- API Reference - Complete API documentation with examples
- Architecture Overview - System design and components
- Performance Analysis - Detailed performance benchmarks and analysis
- Contributing Guide - How to contribute to the project
- Deployment Guide - Production deployment instructions
- Clean Architecture - Layer separation and patterns
- Design Decisions - State machine and consistency model
- Database Schema - Schema, indexes, and migrations
- Benchmark Tools - Remote performance testing guide
- Contributing Guidelines - Development workflow and standards
- Node failures & replica management
- Disk failures & checksums
- Volume snapshots & backups to remote storage
- Block-level integrity
- Object semantics (tenants, namespaces, keys)
- Concurrency control (writes, deletes, GC)
- Content-addressable storage with deduplication
- Metadata indexing & fast listing
- Object-level integrity (SHA-256 hashing)
- API, auth, metrics
| S3/GCS Problem | Our Solution |
|---|---|
| Fake filesystem semantics | No directories, opaque keys |
| Slow listing (millions of objects) | DB-backed indexes |
| Eventual consistency | Strong read-after-write |
| Mysterious throttling | Explicit 429 + metrics |
| Versioning tombstone hell | Explicit versions in DB |
| Complex pricing | Simple $/GB model |
Every object transitions through explicit states:
(none)
↓ POST /objects
WRITING (temp file, DB txn #1)
↓ file written, fsync, rename, DB txn #2
COMMITTED (visible to reads)
↓ DELETE /objects
DELETING (metadata marked, ref_count--)
↓ background GC
DELETED (file removed)
Crash safety: If crash occurs before COMMITTED, object is not visible and will be GC'd as orphan.
Deploy JustStorage instantly to popular platforms with a single click:
Note:
- For Heroku/DigitalOcean: set
INTERNAL_ADMIN_TOKENfor bootstrap/admin access, then create DB-backed API keys through the API.JWT_SECRETand staticAPI_KEYSare not required by the v1 runtime.
JustStorage includes a CLI tool for generating deployment configurations:
# Build the deployment CLI
cd rust && cargo build --release --bin just-storage-deploy
# Generate configuration for your platform
cargo run --release --bin just-storage-deploy -- generate <platform>
# Supported platforms: caprover, heroku, flyio, railway, render, digitaloceanExample:
# Generate Heroku configuration
just-storage-deploy generate heroku
# Generate Fly.io config with custom settings
just-storage-deploy generate flyio --app-name my-app --region ordSee Deployment Guide for detailed platform-specific instructions.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: just-storage
spec:
serviceName: just-storage
replicas: 1
selector:
matchLabels:
app: just-storage
template:
metadata:
labels:
app: just-storage
spec:
containers:
- name: just-storage
image: just-storage:0.1.0-baikonur.20260619.1
ports:
- containerPort: 8080
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: just-storage-secrets
key: database-url
- name: INTERNAL_ADMIN_TOKEN
valueFrom:
secretKeyRef:
name: just-storage-secrets
key: admin-token
optional: true
- name: MAX_UPLOAD_SIZE_BYTES
value: "10737418240"
- name: DISABLE_AUTH
value: "false"
volumeMounts:
- name: hot-storage
mountPath: /data/hot
- name: cold-storage
mountPath: /data/cold
volumeClaimTemplates:
- metadata:
name: hot-storage
spec:
storageClassName: longhorn-nvme
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 1Ti
- metadata:
name: cold-storage
spec:
storageClassName: longhorn-standard
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10TiGET /health- LivenessGET /health/ready- Readiness (DB, applied migrations, and storage directories)
- GitHub Actions keeps the reusable Rust CI gate and publishes multi-arch GHCR images on non-PR events. Pull requests build the image without pushing.
- Gitea Actions publishes the Baikonur Harbor image at
registry.bk.glpx.pro/just-storage/just-storage. It builds nativelinux/amd64andlinux/arm64images, then creates a multi-arch manifest. - Gitea requires repository Actions secrets named
REGISTRY_USERNAMEandREGISTRY_PASSWORD; the workflow fails before build if either is missing. - Production GitOps should use an immutable release tag or digest, not
latest. To produce the current Baikonur chart tag, push a matching Git tag such as0.1.0-baikonur.20260619.1and verify it with:
docker buildx imagetools inspect registry.bk.glpx.pro/just-storage/just-storage:0.1.0-baikonur.20260619.1just_storage_requests_total{method, status, namespace}
just_storage_request_duration_seconds{method, namespace}
just_storage_objects_total{namespace, tenant, status}
just_storage_storage_bytes{storage_class, namespace}
just_storage_gc_runs_total
just_storage_gc_deleted_blobs_total
# Unit tests
cargo test
# Integration tests (requires test DB)
cargo test --test integration
# With coverage
cargo tarpaulin --out Html- Read the Architecture Overview for design context
- Check the Contributing Guide for development guidelines
- Follow established patterns in the codebase
- Write tests for new features
- Update metrics for new operations
This project is licensed under the MIT License — see the LICENSE file for details.
- Main repository: Glowing-Pixels-UG/just-storage
- SDKs:
- Node: just-storage-node-sdk
- Python: just-storage-python-sdk
- Go: just-storage-go-sdk
Core Implementation Complete:
- Clean Architecture with domain/application/infrastructure/api layers
- Database schema with state machine and migrations
- All CRUD operations (upload, download, delete, list)
- Content-addressable storage with automatic deduplication
- Two-phase commit for crash safety
- Background garbage collection with tested worker
- Internal admin token bootstrap and DB-backed API key authentication
- Health check endpoints
- Error handling without unsafe unwrap/expect
- Unit test coverage with in-memory mocks
- Database validation CLI tool
- Clippy-clean, formatted code
- API documentation and examples
Deployment Ready:
- Docker and docker compose configurations
- Kubernetes manifests
- Environment variable configuration
- Migration scripts
- Integration tests with real database (testcontainers)
- Prometheus metrics middleware
- Performance benchmark suite (criterion)
- OIDC authentication + session hardening
- CI gate: fmt, clippy, tests, cargo-deny
- Monitoring dashboards
- Load testing at scale
| Component | Technology |
|---|---|
| Language | Rust 1.96 (2021 edition) |
| Runtime | Tokio async |
| HTTP Framework | Axum 0.8 |
| Database | PostgreSQL 14+ with SQLx |
| Storage | Content-addressable filesystem |
| Authentication | JWT + API Keys |
| Logging | tracing + tracing-subscriber |
| Testing | cargo test, mockall |
Next Milestone: Deploy to production and migrate first service (Model Hub).