Skip to content

Sysopoly/media-service

Repository files navigation

Media Service

Self-hosted media upload, storage, and serving service. Handles image validation, resizing, content moderation, and serves files via Nginx with edge caching.

Architecture

Upload:  App → POST /api/v1/media/upload (JWT) → validate → moderate → resize → local filesystem
Serve:   App → GET /media/{owner}/{id}/{variant}.jpg → Nginx (static) → CDN cache
Delete:  App → DELETE /api/v1/media/:id (JWT) → remove files + metadata
Admin:   Browser → GET /gallery → SSO login → manage all uploads
  • Storage: Local filesystem at {STORAGE_PATH}/{owner_id}/{file_id}/{variant}.jpg
  • Metadata: PostgreSQL
  • Serving: Nginx serves static files directly; CDN caches at edge
  • Processing: Auto-resize to thumb (200px), standard (800px), and original
  • Moderation: Optional Azure Content Safety integration blocks inappropriate content
  • Admin Gallery: Built-in web UI with SSO authentication for managing all uploads

Port

Environment Port
Production 8005
Local dev 8003

Quick Start

cp .env.example .env
docker compose up -d    # Starts service + local PostgreSQL

Or without Docker:

# Requires local PostgreSQL with media_db database
cp .env.example .env
make run

API Endpoints

Method Path Auth Description
GET /health No Health check
POST /api/v1/media/upload JWT Upload an image file
GET /api/v1/media/list JWT List user's files
DELETE /api/v1/media/:id JWT Delete a file
GET /media/:owner_id/:file_id/:variant No Serve a file (dev fallback)

Image Variants

Each uploaded image is processed into three variants:

Variant Width Use Case
thumb.jpg 200px Thumbnails, lists
standard.jpg 800px Detail views
original.jpg unchanged Full resolution

Configuration

Variable Default Description
PORT 8003 Server port
DATABASE_URL PostgreSQL connection string
STORAGE_PATH ./uploads Local file storage path
JWT_SECRET Shared JWT signing secret
BASE_URL http://localhost:8003 Public URL for building file links
MAX_FILE_SIZE_MB 20 Max upload size
MAX_STORAGE_MB 500 Per-user storage quota
ALLOWED_TYPES image/jpeg,image/png,image/webp Accepted MIME types
ADMIN_USER_IDS Comma-separated user IDs for gallery admin access
AUTH_SERVICE_URL http://localhost:8001 OAuth auth service URL for gallery SSO
INTERNAL_API_KEY Key for service-to-service calls (GDPR deletion)
AZURE_CONTENT_SAFETY_ENDPOINT Azure Content Safety endpoint (optional)
AZURE_CONTENT_SAFETY_KEY Azure Content Safety API key (optional)

Production Deployment

Deploy with Docker/Podman:

docker build -t media-service .
docker run -d --name media-service \
  --env-file .env \
  -v media-data:/data/media \
  -p 8003:8003 \
  media-service

For production, place behind a reverse proxy (Nginx) that:

  • Serves /media/ as static files from the storage volume
  • Proxies API requests to the service
  • Terminates TLS

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages