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.
Metadata
Release files for django-rustfs 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| django_rustfs-0.3.0.tar.gz | 161.2 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_rustfs-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 182.1 kB
Release files / django_rustfs-0.3.0.tar.gz
| Download URL | django_rustfs-0.3.0.tar.gz |
|---|---|
| Size | 161.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7770b851458cc07b4be379b8e65a94f095bcf1e7cb72396326a0f0fb0c9f3500
|
|
BLAKE2b-256 checksum How to use checksums |
393b5b55deee3343b4e43794b3f23926ba1c87413b4683e1c7c2e2e84099e2ce
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logRelease files / django_rustfs-0.3.0-py3-none-any.whl
| Download URL | django_rustfs-0.3.0-py3-none-any.whl |
|---|---|
| Size | 21.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e71ad49c57cbf06f06817731a346254aef9da65e3f02dd5bd1eb766ef5e021f9
|
|
BLAKE2b-256 checksum How to use checksums |
a7ed1feeb1cef6f1fc10b3c2d43fbe5b47e1547f6c574c24b02a5ed196056ffb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logSecurity for django-rustfs 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for django_rustfs-0.3.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 11, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.