filestore

Read filestore configuration and statistics through m.filestore, for example {{ m.filestore.service }} or {{ m.filestore.stats.cloud }} in an admin template. All model paths below require an administrator context; unauthorized calls return {error, eacces}. The secret is also unavailable when system configuration is locked. See module#mod_filestore for setup, protocols, configuration precedence and migration.

File registry and upload queue

The filestore table records each relative local path, its backend (s3, ftp, or webdav), full remote URL and size. It also tracks local copies, errors, deletion and moves back to local disk. Use the filestore APIs rather than editing the table.

Paths are relative to the site's files directory, for example archive/2026/10/07/image.jpg. Remote locations retain the URL used for upload; changing configuration does not rewrite them or move the remote files.

The filestore_queue table holds pending uploads. Entries become eligible after one minute; bounded background batches and backoff determine when they complete. Statistics are database-derived counts and estimates, not remote or local disk scans.

Remote cache reads retain failed entries and retry on demand with exponential backoff (nominally 5 seconds initially, 80–100% jitter, capped at 10 minutes). There is no automatic permanent cutoff. Successful reads reset the error history. Cached copies remain available during a cooldown. A ten-minute database claim limits simultaneous probes across nodes and expires if the worker dies. Only its current token can record a result. Existing file-serving negative caches can delay the next lookup.

health reports completed remote cache reads in the current and preceding fourteen minute buckets, shared across nodes. A warning requires at least five failures and a failure rate of at least 20%. Unresolved errors older than 24 hours also warn. User 1 can mark an error older than 24 hours as unrecoverable. This stops read retries and excludes the entry from active error counts, while retaining its record and details. A new successful upload resets this flag. This action never deletes local or remote files. Historical request-rate statistics remain unchanged. Cache hits and suppressed retries are excluded. Buckets are retained for one day and pruned when the first result of a new minute is recorded.

Inspecting prolonged errors

Templates can read m.filestore.prolonged_errors[1]. The result is a map with entries, page, previous, and next. Pages contain at most 50 entries, ordered by first failure time and then entry ID. previous and next are page numbers or undefined. Invalid or non-positive page numbers select page 1. Deleted entries are excluded; unrecoverable entries remain visible. Both this endpoint and m.filestore.health enforce administrator access and return {error, eacces} for unauthorized callers.

The direct Erlang API m_filestore:mark_unrecoverable(Id, Context) is used by the admin postback. It requires user 1 and a writable context, and atomically checks that the error is older than 24 hours. It returns ok, {error, eacces}, {error, badarg}, or {error, not_eligible}. It is not a public model POST path.

Available Model API Paths

MethodPath patternDescription
get/prolonged_errors/+page/...Return admin-only pages of 50 unresolved read errors older than 24 hours, oldest first. Includes entry IDs, relative file paths, service, last error, consecutive failure count, first failure time, retry eligibility and unrecoverable status. Marked unrecoverable entries remain listed.
get/health/...Return admin-only remote read attempts, failures, high-error-rate flag, and unresolved/prolonged error counts.
get/stats/...Return admin-only filestore totals: archived media count/size, queued upload count, queued move/delete counts, cloud-stored count/size, and estimated local count/size.
get/service/...Return the configured filestore backend service identifier from filestore_config:service/1 (admin-only).
get/s3url/...Return the configured S3, FTP/FTPS or WebDAV base URL used for remote object location resolution (admin-only).
get/s3region/...Return the S3 signing region; empty selects Signature V2 (admin-only).
get/s3key/...Return the configured S3 access key or FTP/WebDAV username for filestore credentials (admin-only).
get/s3secret/...Return the configured S3 secret key or FTP/WebDAV password only when caller is admin and filestore config is not locked.
get/is_config_locked/...Return whether filestore credential/config values are locked (non-editable/hidden) in this site instance (admin-only).
get/is_read_only/...Return the effective download-only restriction (admin-only). Global and site-file restrictions cannot be overridden by database settings.
get/is_upload_enabled/...Return whether background upload/offload from local files storage to remote filestore is enabled (admin-only).
get/is_local_keep/...Return whether local files are retained after successful remote storage, instead of being scheduled for deletion (admin-only).
get/delete_interval/...Return the configured extra delay before deleting files marked for remote deletion (admin-only).

/+name marks a variable path segment. A trailing /... means extra path segments are accepted for further lookups.

Edit on GitHub