Skip to content
localisyncDocs
Open panel

Private image storage and quotas

Run migrations separately with old API and worker processes stopped. The image migration adds storage reservations, immutable-file references and audited quota functions. Do not return to older writers that omit image references or language permissions.

Run pnpm transfers:prepare to create separate local transfer and image directories with permission 0700. Configure IMAGE_STORAGE_DIR as an absolute private path. The API and content worker need read/write access to the same files. The assistance worker needs read-only access. Do not mount it into the panel, a public static directory or either delivery service. Deployments use /var/lib/localisync/images; existing deployments must add the directory and service mounts before starting the updated application.

Run pnpm db:migrate and pnpm db:queue before pnpm dev:worker or the compiled worker. The localisync-images queue uses ID-only payloads. Decoding is limited to one active operation across worker processes, a 30-second child timeout, 128 MiB V8 heap and sampled 384 MiB RSS ceiling. Also enforce container memory limits: sampled checks are not a hard kernel memory reservation. The isolated decoder receives no application credentials.

System Admin UI remains separate and is not implemented here. A database administrator provisions a dedicated login with membership in the NOLOGIN role localisync_image_operator. Grant database connection and schema usage required for that login, but no tenant-table privileges, SUPERUSER or BYPASSRLS. Do not grant this role to localisync_app, localisync_queue or customer accounts. Use individual operator logins so image_quota_audit.operator_name identifies the acting operator.

Store the operator PostgreSQL connection URL in a regular private 0600 file, outside the repository. Use verified TLS for a remote database. The CLI reads that file and never prints it. With the same LOCALISYNC_MAINTENANCE_DIR as the application and backup agent:

Terminal window
export LOCALISYNC_MAINTENANCE_DIR=/var/lib/localisync/maintenance
pnpm images:quota --workspace WORKSPACE_UUID --connection-file /run/secrets/image-operator-db
# Use the returned version; this example changes the budget to 2 GiB.
pnpm images:quota --workspace WORKSPACE_UUID --connection-file /run/secrets/image-operator-db --bytes 2147483648 --version 1

The compiled equivalent is node apps/api/dist/cli/image-quota.js with the same arguments. The command returns byte counts and version only. Changes require the exact current version and record old/new budgets, time and database login atomically. Allowed budgets are 0 through 1 TiB; this is a validation range, not a tested hosting-capacity claim. Zero blocks new uploads. Existing images and reservations survive a reduction.

Add the persistent image directory as source images in the backup inventory and images-worker to required maintenance participants. API uploads, decoder commits, reference cleanup and quota changes join the common barrier. Stop old writers before migrating; prepare the image mount, queue and updated backup inventory before reopening uploads. The source directory and operator recovery configuration are private.

The encrypted common point must include both PostgreSQL references/reservations and the image directory. Restore into an empty isolated target. Verify each ready file’s size/hash, references, quotas and tenant isolation before enabling the application. Raw pending files are never served. Stale processing reservations are reclaimed by bounded cleanup once the worker is explicitly enabled; recovery does not initiate a paid AI call.

If the store is missing or unreadable, stop new uploads and inspect mounts and permissions. Do not delete referenced files to repair quota counters. Monitor aggregate stored/reserved bytes, queue age, worker heartbeat, processing failures and disk capacity in the existing alarm setup. Metrics contain no workspace or image IDs.

Cookie preferences

Your choice applies to localisync.com and docs.localisync.com. You can change it at any time using Cookie settings.