django-rustfs
Django storage backend for RustFS; an S3-compatible object storage server.
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-rustfsremoves the mental overhead of pretending you are configuring AWS S3.
Installation
pip install django-rustfs
Requirements:
- Python 3.9+
- Django 4.2 through 6.1
- boto3 1.28+
Django compatibility
| Django | Python |
|---|---|
| 4.2 | 3.9 - 3.12 |
| 5.0 | 3.10 - 3.12 |
| 5.1 | 3.10 - 3.13 |
| 5.2 | 3.10 - 3.14 |
| 6.1 | 3.12 - 3.14 |
Django 6.1 support is tested against Python 3.12, 3.13, and 3.14 in CI.
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
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
FileResponsewrapper
License
Apache 2.0 - see LICENSE file.
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.3.0.tar.gz.
File metadata
- Download URL: django_rustfs-0.3.0.tar.gz
- Upload date:
- Size: 161.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7770b851458cc07b4be379b8e65a94f095bcf1e7cb72396326a0f0fb0c9f3500
|
|
| MD5 |
164405873c590a7eeab39323465c58f2
|
|
| BLAKE2b-256 |
393b5b55deee3343b4e43794b3f23926ba1c87413b4683e1c7c2e2e84099e2ce
|
Provenance
The following attestation bundles were made for django_rustfs-0.3.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.3.0.tar.gz -
Subject digest:
7770b851458cc07b4be379b8e65a94f095bcf1e7cb72396326a0f0fb0c9f3500 - Sigstore transparency entry: 2791659579
- Sigstore integration time:
-
Permalink:
CasualEngineerZombie/django-rustfs@b6c9dbb1fb98d14550db6728d685fab92130d258 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/CasualEngineerZombie
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@b6c9dbb1fb98d14550db6728d685fab92130d258 -
Trigger Event:
release
-
Statement type:
File details
Details for the file django_rustfs-0.3.0-py3-none-any.whl.
File metadata
- Download URL: django_rustfs-0.3.0-py3-none-any.whl
- Upload date:
- Size: 21.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e71ad49c57cbf06f06817731a346254aef9da65e3f02dd5bd1eb766ef5e021f9
|
|
| MD5 |
c9285a535441a4f02a6d694478c997e9
|
|
| BLAKE2b-256 |
a7ed1feeb1cef6f1fc10b3c2d43fbe5b47e1547f6c574c24b02a5ed196056ffb
|
Provenance
The following attestation bundles were made for django_rustfs-0.3.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.3.0-py3-none-any.whl -
Subject digest:
e71ad49c57cbf06f06817731a346254aef9da65e3f02dd5bd1eb766ef5e021f9 - Sigstore transparency entry: 2791659606
- Sigstore integration time:
-
Permalink:
CasualEngineerZombie/django-rustfs@b6c9dbb1fb98d14550db6728d685fab92130d258 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/CasualEngineerZombie
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@b6c9dbb1fb98d14550db6728d685fab92130d258 -
Trigger Event:
release
-
Statement type: