Search iThub

Search tools, categories and collections. Type at least two characters.

Explore all tools
↑ ↓ to explore resultsEnter to open · Esc to close

Openinary

Self-hostable image and video transformations by URL, with S3 storage, caching and an API

Visit website Save

Openinary is an AGPL-3.0 media processing platform that resizes, crops, converts and watermarks images and videos from URL parameters, caches each variant and stores files on disk or S3-compatible buckets. Self-hosted with Docker or hosted as Openinary Cloud.

Pricing
Freemium
Deployment
Self-hosted
Platforms
Web
428stars60forks
0views
Updated

What is Openinary?

Openinary is an open-source media processing platform that its repository describes as the self-hostable alternative to Cloudinary. Files are uploaded once and then requested through URLs that carry transformation parameters, for example /t/w_400,h_400,c_fill,f_avif/photos/portrait.jpg. Each variant is rendered on its first request and served from cache afterwards. The same URL syntax covers images and videos, and the project ships a web dashboard for asset management alongside a REST API. According to the legal notice, the openinary.dev website and the Openinary Cloud service are published by Florian Heysen, an individual entrepreneur based in France.

There are two ways to run it. The self-hosted edition is installed with the create-openinary CLI or with the official Docker images openinary/openinary (API and dashboard) and openinary/openinary-api (headless API only), as described in the Quick Start. Openinary Cloud is the hosted version, in public alpha with open sign-up at app.openinary.dev; it uses the same transformation syntax and upload API, with delivery URLs that carry a bucket prefix. The README also links one-click templates for Railway, Coolify and Dokploy. The project states that full backward compatibility is not guaranteed before version 1.0.0.

The latest GitHub release is v0.8.0, published on November 5, 2026; its notes point to the documentation changelog. That release added image effects through e_ parameters (blur, sharpen, brightness, contrast, saturation, grayscale, sepia, tint, colorize, fill light), o_ opacity and co_ color, automatic and blurred padding backgrounds, borders, dpr_ for high-density images, horizontal and vertical flips, additional crop modes, default placeholder images and a configurable STORAGE_PREFIX. It also fixed EXIF orientation handling and made image overlays resize instead of crop. Version 0.7.0 introduced image and video overlays and watermarks, and 0.6.0 moved the Docker images to Node.js 22 and fixed WebM output, which is now encoded with VP9 and Opus. The documentation changelog additionally lists a v0.9.0 entry dated November 6, 2026, with job phase and time estimates in 202 responses and a fix for the API-only image.

The code is a pnpm and Turbo monorepo written in TypeScript. The transformation engine lives in @openinary/core and uses sharp for images, FFmpeg through fluent-ffmpeg for video, the AWS SDK S3 client for storage and a SQLite job store for the video queue. The self-hosted API is built with Hono, the dashboard with Next.js 15, and authentication uses Better Auth on a SQLite database. The project structure page describes the layout package by package.

Licensing is stated in the README: the repository is AGPL-3.0, with two exceptions. The managed Cloud service under apps/cloud/ is source-available and needs a written agreement to run, and the marketing website under apps/marketing/ is MIT. Self-hosting needs nothing from apps/cloud/. The project's own Cloudinary migration guide lists what is not covered yet: AI effects, text overlays, adaptive streaming and webhooks.

Inside the application

Openinary screenshots

Explore the interface. Open a screenshot to view it at full size.

Openinary dashboard media browser with a bucket selector, folders and image thumbnails
Openinary screenshot 1

Official product preview of the Openinary dashboard asset browser; one sample photo thumbnail has been blurred.

Landscape image cropped to a 600 by 600 circle with the URL parameters w_600,h_600,r_max
URL transformation example

Frame from the official product film showing a circular 600x600 crop produced by URL parameters.

Openinary FileUploader React component with a drop zone, one uploaded image and a video upload in progress
React file uploader

FileUploader component figure from the Openinary documentation.

Diagram of the Openinary App service with a database connected to an S3-compatible assets storage bucket
Railway template layout

Documentation figure of the Railway deployment template: the Openinary app with its database and an S3-compatible bucket.

Source: official Openinary project page.

Key capabilities

  • URL-based image transformations Parameters go after /t/ in any order, separated by commas: width and height, crop modes such as c_fill, c_pad, c_lfill and c_mpad, aspect ratio with ar_, rotation, rounded corners with r_ and quality with q_. Gravity g_face picks the most visually salient region for avatar crops. The full parameter table is in the image transformations guide and the API reference.
  • Automatic format selection When no f_ is given, Openinary reads the Accept header and User-Agent and serves AVIF, then WebP, then JPEG or PNG, caching each format separately. f_auto encodes every supported format and serves the smallest, at a higher CPU cost on the first request. Default quality is 80 for AVIF, 85 for WebP, 90 for JPEG and lossless for PNG, as listed on the automatic format selection page.
  • Image effects (v0.8.0) The e_ family adds blur, sharpen, brightness, contrast, saturation, grayscale, sepia, tint, colorize and fill light, with o_ for opacity and co_ for color. b_auto derives a padding color from the image, b_blurred pads with a blurred copy, and bo_ draws a border. dpr_ serves high-density variants and d_ serves a placeholder when the requested file does not exist.
  • Video transformations Videos use the same URL shape: resizing, quality, trimming with so_ and eo_, format conversion to MP4 or WebM, and poster frames with t_true and tt_. A bare /t/ video URL streams the stored file with range requests and is never transcoded. A transformation that is not cached yet answers HTTP 202 with a status URL and a Retry-After value, and the original is never served in its place.
  • Video processing limits Encoding runs as background jobs with FFmpeg. Fixed limits in the code are a 720p downscale when no width or height is requested, a 200 MB source size cap, a five minute FFmpeg timeout, the ultrafast preset and audio copied without re-encoding. Worker concurrency, retries, cleanup age and FFmpeg threads are set through VIDEO_* variables, documented under video processing.
  • Overlays and watermarks Since v0.7.0, l_ places an image from the instance's own storage on top of an image or a video, with opacity, position, offsets, size and tiling parameters. Remote overlay URLs are not fetched. Tiled video overlays are limited to 400 tiles, and a pending watermarked video is never served without its watermark, per the overlays page.
  • Caching Every variant is rendered once and then served from cache, keyed by URL. Self-hosted instances keep cached transformations in the openinary-cache volume, or in the bucket when S3 storage is configured. A cache invalidation endpoint is part of the API, and replacing a file under the same name requires invalidating the variants that use it.
  • Upload and cache warming POST /upload accepts a transformations list, so selected variants are rendered right after upload instead of on the first visit. Video variants and thumbnails are queued in the background without blocking the upload response. Uploads are checked against magic-byte signatures, so a renamed payload with an allowed extension is rejected.
  • Storage backends Files go to local disk by default. Five STORAGE_* variables switch the instance to AWS S3, Cloudflare R2, MinIO, DigitalOcean Spaces, Wasabi, Backblaze B2 or another S3-compatible provider, detected from STORAGE_ENDPOINT. STORAGE_PREFIX (default public) lets Openinary serve a bucket that another system already writes to. The storage page notes that the bundled Compose file does not pass these variables through by default.
  • Signed delivery URLs The public /t/ route accepts any transformation. The /authenticated/s--{signature}/ route only serves URLs signed with an HMAC-SHA256 of the path, keyed on API_SECRET (at least 16 characters) and truncated to 16 hex characters. Signed delivery URLs are listed as not yet available on Cloud.
  • REST API and API keys Endpoints cover uploads, presigned upload signatures, folders, downloads and ZIP archives, storage listing and statistics, metadata, moves, cache invalidation, the video queue and health. Keys are sent as a Bearer token or x-api-key header and stored hashed in SQLite. The API reference documents both Cloud and self-hosted, marking self-hosted-only pages.
  • Admin dashboard The full-stack image includes a Next.js dashboard with a media browser, folders, bulk actions, an asset details panel with Deliver, Transform and Info sections, API key management, image and video playgrounds and a Logs view. Logs keep the latest 500 public deliveries and hourly counts for a year. A first-run onboarding sets the workspace name and logo.
  • React file uploader <FileUploader /> is a shadcn/ui-compatible component installed with pnpm dlx shadcn@latest add @openinary/file-uploader. It offers drag and drop, per-file progress, previews, retry and cancel, and uploads with short-lived presigned signatures minted by the application's backend, so the browser never holds an API key. A Next.js integration guide is included.
  • Self-hosted installation npx create-openinary needs Docker 20.x or later and Node.js 20+, asks for full-stack or API-only mode and optional S3 storage, writes a docker-compose.yml and .env, and starts the containers on port 3000. The global CLI adds start, stop, restart, upgrade and reset. Three volumes hold the database, uploads and cache.
  • Docker resource profiles The Compose file reads DOCKER_CPU_LIMIT, DOCKER_MEMORY_LIMIT and two reservation variables, defaulting to 2 cores and 4 GB. The documentation lists a 1 to 2 GB images-only profile and a 16 GB video-heavy profile, and states that video jobs fail below 2 GB of memory. The CPU limit also caps automatic video worker detection.
  • Openinary Cloud plans The Cloud overview lists a Free plan with 1 GB storage, 500 image transformations, 15 video minutes and 25,000 CDN requests per month, and an Alpha plan at no monthly fee with double those allowances plus pay-as-you-go overage: $0.03 per extra GB, $0.40 per 1,000 transformations, $0.01 per video minute and $0.50 per 100,000 CDN requests. Free returns HTTP 402 at its limits.
  • Cloudinary migration script A Node.js script in the repository copies files from Cloudinary to Openinary with the same paths, supports --dry-run, resumes after interruption and writes a JSONL file mapping old and new URLs. Openinary follows the Cloudinary URL parameter style, so migration mostly changes the start of each URL.
  • Anonymous telemetry Self-hosted instances send three anonymous events (first boot, a daily heartbeat and onboarding answers as option ids) through a project proxy to PostHog, with counts bucketed. The telemetry page states that the instance IP reaches PostHog for coarse geolocation, and OPENINARY_TELEMETRY=false turns it off.
Advertisements

Where Openinary fits

Responsive images from one upload

A single original is stored and every size is requested by URL. The documentation shows a srcset built by varying w_ (for example 400, 800 and 1600 pixels), with each width rendered once and cached. Omitting f_ lets the server pick AVIF, WebP or JPEG per browser, and f_avif,q_80 forces a format and quality. Thumbnails with fixed dimensions use c_fill, and letterboxed versions use c_pad with a background color.

Avatars and profile pictures

The image guide describes square avatars with w_400,h_400,c_fill,g_face, where gravity selects the most salient region, and circular crops with r_max. Because rounded corners are cut to transparency, the guide pairs them with PNG, WebP or AVIF output, or with b_rgb:ffffff to keep JPEG on a solid background.

Video previews, clips and poster frames

Video URLs request a downscaled copy (w_1280,h_720,q_80), a trimmed section (so_5,eo_12), a smaller file through a lower q_, or a still frame with t_true,tt_5,f_webp. The first request for an uncached video variant answers 202 with an estimate and a status URL; listing the variants in the upload's transformations field queues them in advance. Encoding time depends mainly on output duration and format, with WebM (VP9) slower than MP4 (H.264), as the video guide explains.

Watermarking images and videos

A logo stored in the instance is placed with l_logos:watermark.png, positioned with lg_southeast and offsets, sized with lw_ or lh_ and faded with lo_. lt_1 repeats it across the asset, and video thumbnails can carry the overlay too. An invalid combination or a missing overlay file answers 400 with the reason.

Serving media from an existing bucket

Self-hosted instances connect to AWS S3, Cloudflare R2, MinIO or other S3-compatible storage through STORAGE_* variables, with STORAGE_PUBLIC_URL pointing at a CDN or custom domain. Since v0.8.0, STORAGE_PREFIX maps an existing bucket layout so that an object at photos/2024/sunset.jpg is delivered at /t/photos/2024/sunset.jpg without moving it. Storage options listed on iThub include MinIO and Cloudflare, whose R2 service appears in the Openinary configuration examples.

Browser uploads and platform deployment

Web applications embed the React <FileUploader />, whose backend calls POST /upload/sign with an API key and passes short-lived signatures to the browser. Deployment guides cover Docker, Coolify, Dokploy and a Railway template that pairs the Openinary app with an S3-compatible bucket. Teams moving away from Cloudinary follow the five-step migration guide and rewrite URL prefixes.

Install

npx create-openinary

Reviews of Openinary

No reviews yet

Be the first to share your experience with Openinary.

Loading review form…

Related to Openinary

Compare Openinary with these tools →