Self-hosted media infrastructure. Upload, process, and serve files at scale.
866
Self-hosted open-source media infrastructure platform.
Upload, process, and serve images, videos, and files at scale. Think self-hosted Cloudinary / Imgix / Mux — with a built-in admin dashboard.
MediaOS is a complete media backend you can self-host. It replaces the patchwork of S3 + image CDN + video transcoder + dashboard that most teams build from scratch.
One docker compose up gives you:
curl -fsSL https://raw.githubusercontent.com/arrrrniii/MediaOs/main/install.sh | bash
Pulls images, generates secure secrets, and starts all services. Done in under a minute.
curl -O https://raw.githubusercontent.com/arrrrniii/MediaOs/main/docker-compose.hub.yml
curl -O https://raw.githubusercontent.com/arrrrniii/MediaOs/main/.env.example
cp .env.example .env
# Edit .env with your MASTER_KEY (generate with: node -e "console.log('mv_master_' + require('crypto').randomBytes(24).toString('hex'))")
docker compose -f docker-compose.hub.yml up -d
# In .env, set:
COMPOSE_PROFILES=
Run docker compose up -d — only the worker API and infrastructure start. Manage everything via API.
| Tag | Description | Size |
|---|---|---|
arrrrniii/mediaos:worker | Express API server (Node.js 20 + FFmpeg + Sharp) | ~230 MB |
arrrrniii/mediaos:dashboard | Next.js 15 admin panel | ~70 MB |
Both images support linux/amd64 and linux/arm64 (Apple Silicon, AWS Graviton).
# Pull the worker
docker pull arrrrniii/mediaos:worker
# Pull the dashboard
docker pull arrrrniii/mediaos:dashboard
MediaOS runs as a 6-service stack:
| Service | Image | Port | Role |
|---|---|---|---|
| Worker API | arrrrniii/mediaos:worker | 3000 | Upload, process, serve, API |
| Dashboard | arrrrniii/mediaos:dashboard | 3001 (optional) | Admin panel, analytics |
| PostgreSQL | postgres:16-alpine | internal | Metadata, accounts, keys |
| MinIO | minio/minio:latest | internal | S3-compatible object storage |
| Redis | redis:7-alpine | internal | Rate limiting, caching |
| imgproxy | darthsim/imgproxy:latest | internal | On-the-fly image resizing |
Only the Worker API and Dashboard expose ports. All infrastructure communicates over Docker's internal network.
Every image gets instant resize URLs powered by imgproxy:
/f/{key} → Original
/img/fit/200/200/f/{key} → Fit within 200x200
/img/fill/500/500/f/{key} → Fill 500x500 (crop)
/img/auto/800/0/f/{key} → Smart resize, 800px wide
COMPOSE_PROFILES=)curl -fsSL .../update.sh | bashKey environment variables (see .env.example for full list):
| Variable | Required | Description |
|---|---|---|
MASTER_KEY | Yes | Admin key for management API |
PG_PASSWORD | Yes | PostgreSQL password |
MINIO_ROOT_PASSWORD | Yes | MinIO storage password |
REDIS_PASSWORD | Yes | Redis password |
NEXTAUTH_SECRET | Yes | Dashboard session encryption |
PUBLIC_URL | No | Public URL (default: http://localhost:3000) |
COMPOSE_PROFILES | No | Set to dashboard to enable admin panel (default), empty for API-only |
WEBP_QUALITY | No | Image quality 1-100 (default: 80) |
VIDEO_CRF | No | Video quality, lower=better (default: 20) |
MAX_FILE_SIZE | No | Max upload bytes (default: 104857600 / 100MB) |
npm install @mediaos/sdk
import { MediaOS } from '@mediaos/sdk';
const media = new MediaOS({
url: 'https://cdn.yoursite.com',
apiKey: 'mv_live_...',
});
// Upload
const file = await media.upload(buffer, { name: 'hero.jpg', folder: 'images' });
// Resize URL (no API call)
const thumb = media.url(file.storage_key, { width: 300, height: 300, fit: 'fill' });
// List files
const files = await media.files.list({ type: 'image', limit: 20 });
# Upload an image
curl -X POST http://localhost:3000/api/v1/upload \
-H "X-API-Key: mv_live_..." \
-F "[email protected]"
# Response includes optimized WebP + resize URLs
{
"filename": "photo-a8x3k2.webp",
"url": "http://localhost:3000/f/proj-id/photo-a8x3k2.webp",
"urls": {
"thumb": "http://localhost:3000/img/fit/200/200/f/proj-id/photo-a8x3k2.webp",
"sm": "http://localhost:3000/img/fit/400/0/f/proj-id/photo-a8x3k2.webp",
"md": "http://localhost:3000/img/fit/800/0/f/proj-id/photo-a8x3k2.webp",
"lg": "http://localhost:3000/img/fit/1200/0/f/proj-id/photo-a8x3k2.webp"
},
"type": "image",
"size": 45200,
"processing_ms": 124
}
curl -fsSL https://raw.githubusercontent.com/arrrrniii/MediaOs/main/update.sh | bash
Or manually: docker compose pull && docker compose up -d. Your data is safe — everything lives in Docker volumes.
MediaOS is evolving into a complete open-source media platform:
| Phase | Status | Description |
|---|---|---|
| v1 — Media CDN | Done | Upload, process, serve images/videos/files |
| v2 — Streaming | Next | HLS/DASH adaptive streaming, video player SDK |
| v3 — Security | Planned | DRM, geo-restrictions, watermarking |
| v4 — Scale | Planned | Multi-node, edge caching, S3/R2/B2 backends |
| v5 — Intelligence | Planned | AI tagging, moderation, smart thumbnails |
MIT License — Free to use for personal and commercial projects.
Built by ARN
Content type
Image
Digest
sha256:9ce262096…
Size
134.9 MB
Last updated
6 months ago
docker pull arrrrniii/mediaos:worker