storage-service is a Django backend that provides Supabase-compatible object storage APIs for ShellUI (/storage/v1/*).
It authenticates with JWTs issued by identity-service (JWKS / RS256), stores blobs in S3 (or local filesystem), enforces per-company and optional per-user quotas, exposes WebDAV for third-party file clients, and fires Django signals on upload/delete (including Markdown sidecar extraction).
/storage/v1/* (one company bucket, upload, download, list with folders, move/copy, signed URLs)IDENTITY_JWKS_URL)/dav/ for third-party file clients (quotas + signals apply)X-Accel-Redirect, or Django streamhttp://localhost:4000), admin, and extra originsconfig/ — Django settings and URL routingapps/authapi/ — JWKS JWT authenticationapps/storage/ — buckets, objects, quotas, downloads, signalsapps/webdav/ — WebDAV connectordocs/ — topic guides (Docusaurus)| Area | Path |
|---|---|
| Health | GET /storage/v1/health |
| Buckets | GET/POST /storage/v1/bucket, GET/PUT/DELETE /storage/v1/bucket/{name} |
| Access grants | GET/POST /storage/v1/access/grant, DELETE /storage/v1/access/grant/{id} |
| Share links | POST/GET /storage/v1/share/{bucket}/{*path}, GET/DELETE /storage/v1/share/link/{token} |
| Upload | POST/PUT /storage/v1/object/{bucket}/{*path} |
| Download | GET /storage/v1/object/{bucket}/{*path} |
| By id (picker) | GET /storage/v1/object/id/{uuid} |
| List (folders) | POST /storage/v1/object/list/{bucket} |
| Folder prefix | GET/POST/DELETE /storage/v1/object/prefix/{bucket} (stats, rename, recursive delete) |
| Delete many | DELETE /storage/v1/object/{bucket} |
| Move / copy | POST /storage/v1/object/move, POST /storage/v1/object/copy |
| Sign URL | POST /storage/v1/object/sign/{bucket}/{*path} |
| Quota | GET /storage/v1/quota |
| Stats | GET /storage/v1/stats |
| Metrics | GET /storage/v1/metrics, GET /storage/v1/metrics/all |
| WebDAV | /dav/{bucket}/… |
| OpenAPI | /api/docs/, /api/docs/redoc/ |
Auth header: Authorization: Bearer <access_token> from identity-service. Supabase clients may also send apikey (ignored; JWT is authoritative).
# Requires https://docs.astral.sh/uv/
uv sync
cp .env.example .env
# Set SECRET_KEY; point IDENTITY_JWKS_URL at identity-service
uv run python manage.py migrate
uv run python manage.py runserver 8001
Open http://localhost:8001/ for Swagger / ReDoc. Create the one-time admin user from the home page if you need Django admin (quotas, grants, share links).
Dependencies live in pyproject.toml and are locked in uv.lock. Add a package with uv add <name>; refresh the lock with uv lock.
Tokens come from identity-service. Point storage at its JWKS with an env var:
# Local
IDENTITY_JWKS_URL=http://localhost:8000/.well-known/jwks.json
# Production
IDENTITY_JWKS_URL=https://id.shellui.com/.well-known/jwks.json
# Or only the base URL (path /.well-known/jwks.json is appended):
IDENTITY_SERVICE_URL=https://id.shellui.com
Copy .env.example → .env and change the value there (Compose and runserver both load it).
For identity DEBUG/HS256 locally, also set JWT_HS256_FALLBACK_SECRET to the same SECRET_KEY as identity-service.
STORAGE_BACKEND=s3
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
AWS_STORAGE_BUCKET_NAME=shellui
AWS_S3_ENDPOINT_URL=http://localhost:9000 # MinIO; omit for AWS
AWS_S3_REGION_NAME=us-east-1
Compose helper:
docker compose --profile s3 up minio
| Mode | When to use |
|---|---|
redirect (auto for S3) |
302 to a signed object URL — best bandwidth offload, no nginx required |
xaccel |
NGINX serves bytes after Django authorizes (X-Accel-Redirect) — great for local disk |
stream |
Django streams the file — simplest, uses app workers |
See docs/downloads.md.
Mirror Supabase Storage so one client can target either backend:
// Planned shape — not shipped in shellui yet
storage: {
type: 'shellui', // or 'supabase'
url: 'http://localhost:8001',
}
// Client calls `${url}/storage/v1/...` like @supabase/storage-js
cp .env.example .env
docker compose up --build
Default host port: 8001.
uv run python manage.py test
Hosted at https://storage.docs.shellui.com (published to GitHub Pages on main and v* tags).
Build docs site: ./tools/generate-docs.sh