The default backend: blobs streamed to a directory. Depends only on Node
built-ins and @orthacms/media-domain.
id:local- Capabilities:
{ directUrl: false, contentTypeMetadata: false, streamingPut: true }
Install
npm install @orthacms/media-provider-localConfigure
# .env — point at a persistent volume in production
MEDIA_LOCAL_ROOT=/var/lib/orthacms/media| Variable | Default | Notes |
|---|---|---|
MEDIA_LOCAL_ROOT | ./.storage/media | Resolved once, at construction |
The reference server, apps/server/config/media.ts (a generated app has the
same in config/media-storage.ts):
storage: {
rootDir: readEnv('MEDIA_LOCAL_ROOT') ?? './.storage/media'
},LocalStorageConfig is { rootDir } and nothing else.
The default root is ephemeral
./.storage/media is inside the container. A new container starts empty while
the database still lists every asset, so every download 404s — silently.
Mount a volume before uploading anything you care about.
# docker-compose.yml
services:
cms:
environment:
MEDIA_LOCAL_ROOT: /data/media
volumes:
- media:/data/media
volumes:
media:Register
// apps/server/src/plugins.ts
import { createLocalStorageProvider } from '@orthacms/media-provider-local';
MediaServerPlugin({
provider: createLocalStorageProvider(config.plugins.media.storage),
config: config.plugins.media
});Verify
Upload a file (curl example), then:
ls -R "$MEDIA_LOCAL_ROOT"
# <workspaceId>/<assetId>/kingfisher.jpg
# <workspaceId>/<assetId>/variants/thumb.webp …MEDIA_DIRECT_SERVE=signed-url is a boot error here
A filesystem cannot sign a URL. Downloads always stream through the app.
Behaviour worth knowing
- Keys are
<workspaceId>/<assetId>/<sanitized-filename>; derivatives go undervariants/, so a derivative never overwrites an original. putis all-or-nothing: written to a temp file, then onerename. A failure removes the temp file and any directories it created.- Every key is checked against the root. A key resolving outside it throws
StorageKeyOutsideRootError. - Content type is kept in the database, not on disk.
- Backups: the database alone restores rows pointing at missing bytes. Back up the media root with it.