Skip to content

CasualEngineerZombie/django-rustfs

django-rustfs

Django storage backend for RustFS; an S3-compatible object storage server.

PyPI version Python versions Django versions License Tests Coverage

pip install django-rustfs

Installation - Quick Start - Configuration - Advanced Usage - Contributing


Why django-rustfs?

You can already use RustFS with Django via django-storages + boto3. So why another package?

The Problem

django-storages is great for AWS S3, but using it with RustFS means:

  • Pretending RustFS is AWS (AWS_S3_ENDPOINT_URL, AWS_ACCESS_KEY_ID...)
  • Configuring 10+ settings you do not need
  • No built-in health checks or bucket setup tools
  • Writing custom code for static files

The Solution

django-rustfs is purpose-built for RustFS:

Feature django-storages + boto3 django-rustfs
Configuration 10+ AWS-branded settings 4 clean settings (RUSTFS_ENDPOINT, RUSTFS_ACCESS_KEY, RUSTFS_SECRET_KEY, RUSTFS_BUCKET_NAME)
Scope General-purpose (S3, Azure, GCP...) Built exclusively for RustFS
Bucket setup Manual CLI/console python manage.py rustfs_init_buckets
Health checks None python manage.py rustfs_health
Static files Custom subclass required RustFSStaticStorage included
Dependencies django-storages + boto3 boto3 only
Codebase ~1,500 lines ~400 lines focused on RustFS

Bottom line: If you are using RustFS, django-rustfs removes the mental overhead of pretending you are configuring AWS S3.


Installation

pip install django-rustfs

Requirements:

  • Python 3.9+
  • Django 4.2+
  • boto3 1.28+

Quick Start

1. Add to Installed Apps

# settings.py

INSTALLED_APPS = [
    # ... your apps
    "django_rustfs",
]

2. Configure Connection

# settings.py

# Required
RUSTFS_ENDPOINT = "http://localhost:9000"
RUSTFS_ACCESS_KEY = "your-access-key"
RUSTFS_SECRET_KEY = "your-secret-key"

# Optional (defaults shown)
RUSTFS_BUCKET_NAME = "django-media"
RUSTFS_AUTO_CREATE_BUCKET = True

3. Set as Default Storage

Django 4.2+ (recommended):

# settings.py

STORAGES = {
    "default": {
        "BACKEND": "django_rustfs.storage.RustFSStorage",
    },
    "staticfiles": {
        "BACKEND": "django_rustfs.storage.RustFSStaticStorage",
    },
}

Django < 4.2:

DEFAULT_FILE_STORAGE = "django_rustfs.storage.RustFSStorage"
STATICFILES_STORAGE = "django_rustfs.storage.RustFSStaticStorage"

4. Initialize Buckets

python manage.py rustfs_init_buckets

5. Verify Everything Works

python manage.py rustfs_health

Output:

🔍 Checking RustFS health...
   Endpoint: http://localhost:9000
   Bucket:   django-media

  ✅ Bucket 'django-media' is accessible
     Response time: 12.3ms
  ✅ List operation works (0 objects visible)

  🧪 Running upload/download roundtrip test...
  ✅ Upload/download roundtrip successful

✅ RustFS health check completed successfully!

Configuration

All settings use the RUSTFS_ prefix for clarity.

Required Settings

Setting Description
RUSTFS_ENDPOINT RustFS server URL, e.g. "http://localhost:9000"
RUSTFS_ACCESS_KEY RustFS access key
RUSTFS_SECRET_KEY RustFS secret key

Optional Settings

Setting Default Description
RUSTFS_BUCKET_NAME "django-media" Default bucket for media files
RUSTFS_STATIC_BUCKET_NAME "django-static" Bucket for static files
RUSTFS_AUTO_CREATE_BUCKET True Auto-create buckets on first use
RUSTFS_CUSTOM_DOMAIN "" CDN domain, e.g. "cdn.example.com"
RUSTFS_SECURE_URLS True Use HTTPS in generated URLs
RUSTFS_URL_EXPIRATION 3600 Presigned URL expiry (seconds)
RUSTFS_DEFAULT_ACL "private" Default ACL (private, public-read)
RUSTFS_FILE_OVERWRITE False Allow overwriting existing files
RUSTFS_LOCATION "" Prefix path for uploads, e.g. "media/"
RUSTFS_REGION "us-east-1" Region name
RUSTFS_USE_SSL False Use SSL/TLS for connections
RUSTFS_VERIFY_SSL True Verify SSL certificates

Management Commands

rustfs_health

Check connectivity, authentication, and run an upload/download roundtrip test:

python manage.py rustfs_health
python manage.py rustfs_health --bucket=my-bucket

rustfs_init_buckets

Create and configure RustFS buckets:

python manage.py rustfs_init_buckets              # Create all buckets
python manage.py rustfs_init_buckets --bucket=X   # Create specific bucket
python manage.py rustfs_init_buckets --public     # Make buckets public
python manage.py rustfs_init_buckets --dry-run    # Preview changes

Advanced Usage

Per-Field Storage Configuration

Configure different buckets for different model fields:

from django.db import models
from django_rustfs.storage import RustFSStorage

# Private storage for documents
private_storage = RustFSStorage(
    bucket_name="user-documents",
    default_acl="private",
)

# Public storage for avatars
public_storage = RustFSStorage(
    bucket_name="public-avatars",
    default_acl="public-read",
    presign_urls=False,
)

class UserProfile(models.Model):
    avatar = models.ImageField(storage=public_storage, upload_to="avatars/")
    documents = models.FileField(storage=private_storage, upload_to="docs/")

Direct Browser Uploads (Presigned POST)

Let browsers upload directly to RustFS without going through your Django server:

from django_rustfs.storage import RustFSStorage

storage = RustFSStorage()
post_data = storage.get_presigned_post_url(
    name="uploads/user123/photo.jpg",
    expires_in=600,
)

# Returns:
# {
#   "url": "http://localhost:9000/django-media",
#   "fields": {
#     "key": "uploads/user123/photo.jpg",
#     "AWSAccessKeyId": "...",
#     "policy": "...",
#     "signature": "..."
#   }
# }

Object Metadata Access

storage = RustFSStorage()
meta = storage.get_object_metadata("uploads/photo.jpg")

print(meta["etag"])           # "d41d8cd98f00b204e9800998ecf8427e"
print(meta["content_length"]) # 2048
print(meta["storage_class"])  # "STANDARD"
print(meta["version_id"])     # "uuid-v1"

Copy Objects

storage.copy_object("uploads/photo.jpg", "backups/photo-backup.jpg")

Architecture

┌─────────────┐      ┌─────────────────┐      ┌─────────────┐
│   Django    │──────│  django-rustfs  │──────│    boto3    │
│             │      │  (this package) │      │  (AWS SDK)  │
└─────────────┘      └─────────────────┘      └──────┬──────┘
                                                      │
                                               HTTP/HTTPS
                                                      │
                                                ┌─────────┐
                                                │  RustFS │
                                                │  Server │
                                                └─────────┘

django-rustfs uses boto3 to communicate with RustFS. RustFS is fully S3-compatible, so the AWS SDK works out of the box - we just wrap it in a purpose-built API.


Development

Setup

git clone https://github.com/CasualEngineerZombie/django-rustfs.git
cd django-rustfs
pip install -e ".[dev]"

Running Tests

pytest

With coverage:

pytest --cov=django_rustfs --cov-report=html

Code Quality

ruff check .          # Linting
ruff format .         # Formatting
mypy django_rustfs    # Type checking

Project Structure

django-rustfs/
├── django_rustfs/          # Main package
│   ├── storage.py          # Core storage backend
│   ├── conf.py             # Settings configuration
│   └── management/         # Management commands
│       └── commands/
│           ├── rustfs_health.py
│           └── rustfs_init_buckets.py
├── tests/                  # Test suite
├── .github/workflows/      # CI/CD
├── pyproject.toml          # Package config
└── README.md               # This file

Contributing

Contributions are welcome! See CONTRIBUTING.md for guidelines.

Quick start for contributors:

git clone https://github.com/CasualEngineerZombie/django-rustfs.git
cd django-rustfs
pip install -e ".[dev]"
pytest

Releasing

See RELEASE_GUIDE.md for step-by-step instructions on publishing to PyPI.


Roadmap

  • RustFS-native features - Expose RustFS-specific capabilities (replication, lifecycle rules, event notifications)
  • Django Admin integration - View bucket contents and storage statistics
  • Management commands - sync_to_rustfs, sync_from_rustfs, clean_orphaned
  • Async support - aioboto3-based async storage backend
  • URL caching - Cache presigned URLs with Django's cache framework
  • Multipart upload - Resumable multipart uploads for large files
  • Streaming responses - Memory-efficient FileResponse wrapper

License

Apache 2.0 - see LICENSE file.

About

Django storage backend for RustFS; an S3-compatible object storage server

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages