How Media Storage Works
Images, renditions, and uploads all go to RustFS S3 — no local disk, no PVC for media.
When you upload an image in the Wagtail admin, it doesn’t land on the server’s disk. Instead, it goes straight to RustFS — an S3-compatible object store running right here on the cluster.
The pipeline
Every upload follows the same path:
- You drop an image into the Wagtail admin
- Django hands it to
django-storages - The file lands in the
blog-mediabucket on RustFS - Wagtail auto-generates renditions (thumbnails, crops) — also stored in S3
- The public URL points directly to
s3-api.evillab.tech
Why not local disk?
Running on a single-node k3s cluster means the pod can restart, reschedule, or get replaced. A PVC for media files works, but S3 is simpler: no volume management, no permissions headaches, and backups are a bucket sync away.
The code
# settings.py
AWS_S3_ENDPOINT_URL = "https://s3-api.evillab.tech"
AWS_STORAGE_BUCKET_NAME = "blog-media"
STORAGES = {
"default": {"BACKEND": "storages.backends.s3.S3Storage"},
}
One gotcha
Django 6.0 requires the STORAGES dict — the old DEFAULT_FILE_STORAGE setting is ignored. If you skip it, uploads silently fall back to the local filesystem. Took 20 minutes to debug.