Technical — Minio Uploader
RAGA's file upload to MinIO service, built on Python + FastAPI. Accepts image and document files via multipart form, validates MIME type and size, then streams them directly to MinIO object storage. The public file URL is returned as soon as the upload finishes. Used by api-tarantula as the storage backend for files uploaded by users.
Note: this service does not use Infisical — configuration is read directly from a
.envfile viapython-dotenv.
Repository
| Key | Value |
|---|---|
| Git Remote | https://git.tlab.co.id/tarantula/service/minio-uploader.git |
| Active Branch | main |
git clone https://git.tlab.co.id/tarantula/service/minio-uploader.git
cd minio-uploaderTech Stack
| Layer | Technology |
|---|---|
| Runtime | Python 3.11 |
| Framework | FastAPI + uvicorn |
| Storage Client | minio Python SDK |
| Config | python-dotenv (.env file directly, no Infisical) |
| Upload | python-multipart (multipart/form-data) |
| Containerization | Docker (python:3.11-slim) |
Folder Structure
minio-uploader/
├── app.py # FastAPI app + all upload logic
├── requirements.txt
├── .env.sample
├── Dockerfile # Dev/local image (python:3.11-slim)
├── Dockerfile.stag # Staging/production image (python:3.11, used by CI deploy)
└── docker-compose.yml # Dev setup: MinIO + minio-uploaderEnvironment Variables
All configuration is read from a .env file via python-dotenv. No Infisical.
.env File
MINIO_ENDPOINT=minio:9000
MINIO_ACCESS_KEY=
MINIO_SECRET_KEY=
MINIO_BUCKET=tarantula-api
MINIO_DOMAIN=https://s3.ziwardingai.xyz| Variable | Default | Description |
|---|---|---|
MINIO_ENDPOINT | minio:9000 | MinIO server host:port (without http://) |
MINIO_ACCESS_KEY | — | MinIO access key (required) |
MINIO_SECRET_KEY | — | MinIO secret key (required) |
MINIO_BUCKET | tarantula (code default) / tarantula-api (in .env.sample) | Target bucket name; created automatically if it doesn't exist |
MINIO_DOMAIN | — | MinIO's public base URL (e.g. https://s3.ziwardingai.xyz); used to build the response URL (required) |
The MinIO connection is created with
secure=False— make sure the endpoint is on an internal network or already reverse-proxied with TLS in front of it.
Endpoint
| Method | Path | Description |
|---|---|---|
POST | /upload/ | Upload images and/or documents to MinIO |
POST /upload/
Content-Type: multipart/form-data
images (List[UploadFile], optional) — image / video files
files (List[UploadFile], optional) — document files
folder_path (str, query param, optional) — root folder in MinIOAt least one of images or files must be provided.
200 OK Response:
{
"images": [
"https://s3.ziwardingai.xyz/tarantula-api/my-project/document.png"
],
"files": [
"https://s3.ziwardingai.xyz/tarantula-api/my-project/report.pdf"
]
}Folder Path Logic
| Condition | Images Path | Files Path |
|---|---|---|
folder_path not provided | upload-api-service/jajal/images/ | upload-api-service/jajal/files/ |
folder_path=my-project | my-project/ | my-project/ |
When folder_path is provided, images and files are stored in the same folder (no images/ or files/ subfolder is added). Final object name: {folder}/{filename}.
File Validation
Allowed Types
Images (Content-Type):
| MIME Type | Extension |
|---|---|
image/png | .png |
image/jpeg | .jpg, .jpeg |
image/jpg | .jpg |
video/mp4 | .mp4 |
video/quicktime | .mov |
Files (Content-Type):
| MIME Type | Extension |
|---|---|
application/pdf | .pdf |
application/vnd.openxmlformats-officedocument.wordprocessingml.document | .docx |
text/plain | .txt |
application/vnd.openxmlformats-officedocument.presentationml.presentation | .pptx |
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | .xlsx |
text/csv | .csv |
application/json | .json |
Size Limit
- Maximum 100 MB per file
400 Bad Requestif the limit is exceeded or the MIME type is invalid
Upload Flow
The upload is streamed (upload_to_minio_direct) — the file is never fully read into memory; only its size is checked (seek) before it's streamed directly to MinIO via put_object.
Docker
docker-compose.yml (dev)
services:
minio:
image: minio/minio
environment:
MINIO_ROOT_USER: minioAccessKey
MINIO_ROOT_PASSWORD: minioSecretKey
volumes:
- minio_data:/data
ports:
- "9000:9000" # S3 API
- "9090:9001" # MinIO Console
command: ["server", "--console-address", ":9001", "/data"]
minio-uploader:
container_name: minio-uploader
build: .
volumes:
- .:/app
env_file: .env
ports:
- "8000:8000"
depends_on:
- minioBuild & Run
# Install dependencies
pip install -r requirements.txt
# Run development (make sure .env is filled in)
uvicorn app:app --reload --port 8000
# Docker Compose (dev — includes local MinIO)
docker compose up --build
# Standalone Docker build & run
docker build -t minio-uploader .
docker run -p 8000:8000 \
-e MINIO_ENDPOINT=minio:9000 \
-e MINIO_ACCESS_KEY=your-access-key \
-e MINIO_SECRET_KEY=your-secret-key \
-e MINIO_BUCKET=tarantula-api \
-e MINIO_DOMAIN=https://s3.ziwardingai.xyz \
minio-uploader