A plug-and-play Django storage backend for RustFS - the high-performance, S3-compatible object storage.
Project description
django-rustfs
A plug-and-play Django storage backend for RustFS - the high-performance, S3-compatible object storage built in Rust.
pip install django-rustfs
Why django-rustfs?
You can already use RustFS with Django today via django-storages + boto3. So why another package?
| django-storages + boto3 | django-rustfs | |
|---|---|---|
| Configuration | 10+ AWS-named settings (AWS_S3_ENDPOINT_URL, AWS_ACCESS_KEY_ID, AWS_STORAGE_BUCKET_NAME, AWS_S3_SIGNATURE_VERSION, AWS_S3_FILE_OVERWRITE, AWS_DEFAULT_ACL, AWS_S3_VERIFY, AWS_S3_MAX_MEMORY_SIZE...) |
5 clean, RustFS-branded settings (RUSTFS_ENDPOINT, RUSTFS_ACCESS_KEY, RUSTFS_SECRET_KEY, RUSTFS_BUCKET_NAME) |
| Scope | General-purpose (S3, Azure, GCP, FTP, SFTP...) | Built exclusively for RustFS - nothing more, nothing less |
| Bucket setup | Manual - create buckets via RustFS console or CLI | python manage.py rustfs_init_buckets - creates buckets automatically |
| Health checks | None built-in | python manage.py rustfs_health - connectivity, auth, upload/download roundtrip |
| Static files | Requires custom subclass | RustFSStaticStorage included with public-read defaults |
| Dependencies | django-storages, boto3 (~2 packages to configure) |
boto3 only (~1 direct dependency) |
| Codebase | ~1,500 lines for S3 backend (handles many edge cases for AWS) | ~400 lines focused on RustFS - lean, readable, auditable |
Bottom line: If you're using RustFS,
django-rustfsremoves the mental overhead of pretending you're configuring AWS S3.
Quick Start
1. Install
pip install django-rustfs
2. Configure Django Settings
# settings.py
INSTALLED_APPS = [
# ... your apps
"django_rustfs",
]
# RustFS connection (required)
RUSTFS_ENDPOINT = "http://localhost:9000" # Your RustFS server URL
RUSTFS_ACCESS_KEY = "your-access-key" # RustFS access key
RUSTFS_SECRET_KEY = "your-secret-key" # RustFS secret key
# Bucket configuration (optional - defaults shown)
RUSTFS_BUCKET_NAME = "django-media" # Media files bucket
RUSTFS_STATIC_BUCKET_NAME = "django-static" # Static files bucket
RUSTFS_AUTO_CREATE_BUCKET = True # Auto-create buckets on first use
# Use RustFS for media files
DEFAULT_FILE_STORAGE = "django_rustfs.storage.RustFSStorage"
3. Initialize Buckets (Optional but Recommended)
python manage.py rustfs_init_buckets
This creates your media and static buckets with the correct permissions.
4. Health Check
python manage.py rustfs_health
Checks connectivity, authentication, and runs an upload/download roundtrip test.
Full Configuration Reference
All settings use the RUSTFS_ prefix for clarity and to avoid conflicts.
Required Settings
| Setting | Default | Description |
|---|---|---|
RUSTFS_ENDPOINT |
(none) | RustFS server URL, e.g. "http://localhost:9000" |
RUSTFS_ACCESS_KEY |
(none) | RustFS access key (or AWS_ACCESS_KEY_ID from RustFS console) |
RUSTFS_SECRET_KEY |
(none) | RustFS secret key |
Bucket Settings
| Setting | Default | Description |
|---|---|---|
RUSTFS_BUCKET_NAME |
"django-media" |
Default bucket for media files |
RUSTFS_STATIC_BUCKET_NAME |
"django-static" |
Bucket for static files (used by RustFSStaticStorage) |
RUSTFS_AUTO_CREATE_BUCKET |
True |
Automatically create buckets if they don't exist |
URL & Access Settings
| Setting | Default | Description |
|---|---|---|
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 in seconds |
RUSTFS_DEFAULT_ACL |
"private" |
Default ACL for uploaded objects (private, public-read) |
RUSTFS_FILE_OVERWRITE |
False |
Allow overwriting existing files |
File Settings
| Setting | Default | Description |
|---|---|---|
RUSTFS_LOCATION |
"" |
Prefix path for all uploads, e.g. "media/" |
RUSTFS_OBJECT_PARAMETERS |
{} |
Extra parameters passed to boto3 put_object() |
Connection Settings
| Setting | Default | Description |
|---|---|---|
RUSTFS_REGION |
"us-east-1" |
Region name (RustFS uses us-east-1 by default) |
RUSTFS_USE_SSL |
False |
Use SSL/TLS for connections |
RUSTFS_VERIFY_SSL |
True |
Verify SSL certificates |
Static Files Configuration
Django 4.2+ uses the STORAGES dictionary:
# settings.py
STORAGES = {
"default": {
"BACKEND": "django_rustfs.storage.RustFSStorage",
"OPTIONS": {
"bucket_name": "my-media-bucket",
},
},
"staticfiles": {
"BACKEND": "django_rustfs.storage.RustFSStaticStorage",
"OPTIONS": {
"bucket_name": "my-static-bucket",
"location": "static/",
},
},
}
For Django < 4.2:
DEFAULT_FILE_STORAGE = "django_rustfs.storage.RustFSStorage"
STATICFILES_STORAGE = "django_rustfs.storage.RustFSStaticStorage"
RustFSStaticStorage automatically uses public-read ACL so your CSS/JS/images are directly accessible.
Management Commands
rustfs_health
Check connectivity, authentication, and run an upload/download roundtrip test:
python manage.py rustfs_health
# ๐ 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!
Options:
--bucket <name>- Check a specific bucket--verbose- Show detailed response information
rustfs_init_buckets
Create and configure RustFS buckets:
python manage.py rustfs_init_buckets
# ๐ชฃ Initializing RustFS buckets...
#
# ๐ฆ Bucket: django-media
# Status: Created โ
# Policy: private (default)
#
# ๐ฆ Bucket: django-static
# Status: Created โ
# Policy: public-read โ
#
# โ
All done: 2 bucket(s) ready to use
Options:
--bucket <name>- Create only a specific bucket--public- Make the bucket public-readable--skip-static- Don't create the static files bucket--dry-run- Preview what would be done
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 user 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, # Direct URLs, no presigning needed
)
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()
# Generate a presigned POST URL for the browser
post_data = storage.get_presigned_post_url(
name="uploads/user123/photo.jpg",
expires_in=600, # 10 minutes
)
# Return this to your frontend:
# {
# "url": "http://localhost:9000/django-media",
# "fields": {
# "key": "uploads/user123/photo.jpg",
# "AWSAccessKeyId": "...",
# "policy": "...",
# "signature": "..."
# }
# }
Object Metadata Access
Access RustFS-specific metadata like ETag, version ID, and storage class:
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
Copy files within RustFS without downloading them:
storage.copy_object("uploads/photo.jpg", "backups/photo-backup.jpg")
Comparison: django-rustfs vs. django-storages + boto3
Configuration Verbosity
django-storages (S3 backend):
# settings.py
AWS_ACCESS_KEY_ID = "your-key"
AWS_SECRET_ACCESS_KEY = "your-secret"
AWS_STORAGE_BUCKET_NAME = "my-bucket"
AWS_S3_ENDPOINT_URL = "http://localhost:9000"
AWS_S3_SIGNATURE_VERSION = "s3v4"
AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = "private"
AWS_S3_VERIFY = True
AWS_S3_USE_SSL = False
AWS_S3_REGION_NAME = "us-east-1"
AWS_S3_OBJECT_PARAMETERS = {}
AWS_QUERYSTRING_AUTH = True
AWS_S3_CUSTOM_DOMAIN = ""
# ... and more
DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
django-rustfs:
# settings.py
RUSTFS_ENDPOINT = "http://localhost:9000"
RUSTFS_ACCESS_KEY = "your-key"
RUSTFS_SECRET_KEY = "your-secret"
RUSTFS_BUCKET_NAME = "my-bucket"
DEFAULT_FILE_STORAGE = "django_rustfs.storage.RustFSStorage"
Runtime Behavior
| Feature | django-storages | django-rustfs |
|---|---|---|
| Bucket auto-creation | No (fails if bucket missing) | Yes (on by default) |
| Built-in health check | No | rustfs_health command |
| Bucket initialization | Manual via CLI/console | rustfs_init_buckets command |
| Presigned POST for direct uploads | Requires manual implementation | get_presigned_post_url() method |
| Object metadata access | Raw boto3 response | Structured get_object_metadata() |
| Copy within storage | Manual boto3 call | copy_object() method |
| Static files setup | Custom subclass needed | RustFSStaticStorage included |
How It Works
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 cleaner API:
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ Django โโโโโโโโ django-rustfs โโโโโโโโ boto3 โ
โ โ โ (this package) โ โ (AWS SDK) โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโฌโโโโโโโ
โ
HTTP/HTTPS
โ
โโโโโโโโโโโ
โ RustFS โ
โ Server โ
โโโโโโโโโโโ
Requirements
- Python 3.9+
- Django 4.2+
- boto3 1.28+
Roadmap
- RustFS-native features - Expose RustFS-specific capabilities (bucket replication, lifecycle rules, event notifications) as they stabilize beyond beta
- Django Admin integration - View bucket contents, object metadata, and storage statistics in Django admin
- Management commands -
sync_to_rustfs,sync_from_rustfs,clean_orphaned - Async support -
aioboto3-based async storage backend for ASGI deployments - URL caching - Cache presigned URLs with Django's cache framework to reduce S3 API calls
- Multipart upload - Support large file uploads with resumable multipart uploads
- Streaming responses - Memory-efficient
FileResponsewrapper for serving large files
License
Apache 2.0 License - see LICENSE file.
Contributing
Contributions are welcome! Please open an issue or pull request on GitHub.
git clone https://github.com/CasualEngineerZombie/django-rustfs
cd django-rustfs
pip install -e ".[dev]"
pytest
See CONTRIBUTING.md for detailed guidelines.
Releasing
See RELEASE_GUIDE.md for step-by-step instructions on publishing to PyPI.
Built with โค๏ธ for the RustFS community.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_rustfs-0.2.0.tar.gz.
File metadata
- Download URL: django_rustfs-0.2.0.tar.gz
- Upload date:
- Size: 572.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
966d3c021f327db24d51638dbec170194f2547fd3c969c0cbb7ff799f0024f1b
|
|
| MD5 |
5bf7bce58280ebf2eebe1920098cda57
|
|
| BLAKE2b-256 |
98830fc04bb153ecb50773bbd102a0604e9a120e1204d5ff531d8aa1a2162ef6
|
Provenance
The following attestation bundles were made for django_rustfs-0.2.0.tar.gz:
Publisher:
python-publish.yml on CasualEngineerZombie/django-rustfs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_rustfs-0.2.0.tar.gz -
Subject digest:
966d3c021f327db24d51638dbec170194f2547fd3c969c0cbb7ff799f0024f1b - Sigstore transparency entry: 1713540829
- Sigstore integration time:
-
Permalink:
CasualEngineerZombie/django-rustfs@940e57a714311251b87363659ab5f7e53afbe1e1 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/CasualEngineerZombie
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@940e57a714311251b87363659ab5f7e53afbe1e1 -
Trigger Event:
release
-
Statement type:
File details
Details for the file django_rustfs-0.2.0-py3-none-any.whl.
File metadata
- Download URL: django_rustfs-0.2.0-py3-none-any.whl
- Upload date:
- Size: 21.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b93fb78cd3bfd65b77fa099d3f25f11aa3ce6e84f9fc8e39bc641bb847747e2f
|
|
| MD5 |
50df89566dbfaa8ae30485e1387dc07f
|
|
| BLAKE2b-256 |
d589b69360145d3770ab509334000604c349073eed3d1b9cb5ad69c81c7272cb
|
Provenance
The following attestation bundles were made for django_rustfs-0.2.0-py3-none-any.whl:
Publisher:
python-publish.yml on CasualEngineerZombie/django-rustfs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_rustfs-0.2.0-py3-none-any.whl -
Subject digest:
b93fb78cd3bfd65b77fa099d3f25f11aa3ce6e84f9fc8e39bc641bb847747e2f - Sigstore transparency entry: 1713540938
- Sigstore integration time:
-
Permalink:
CasualEngineerZombie/django-rustfs@940e57a714311251b87363659ab5f7e53afbe1e1 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/CasualEngineerZombie
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@940e57a714311251b87363659ab5f7e53afbe1e1 -
Trigger Event:
release
-
Statement type: