Skip to main content

Advanced Configuration

External tool integration, hash worker settings, network timeouts, and startup optimizations.

External Tools

External tools generate thumbnails for videos and office documents.

FFmpeg (Video Thumbnails)

FFmpeg generates thumbnails from video files.

./mahresources -ffmpeg-path=/usr/bin/ffmpeg -db-type=SQLITE -db-dsn=./db.sqlite -file-save-path=./files

Or with environment variables:

FFMPEG_PATH=/usr/bin/ffmpeg

If not specified, FFmpeg is auto-detected from your PATH.

LibreOffice (Office Document Thumbnails)

LibreOffice generates thumbnails for Word documents, spreadsheets, and presentations.

./mahresources -libreoffice-path=/usr/bin/soffice -db-type=SQLITE -db-dsn=./db.sqlite -file-save-path=./files

Or with environment variables:

LIBREOFFICE_PATH=/usr/bin/soffice

Auto-detected from your PATH (soffice or libreoffice) if not specified.

macOS

On macOS, LibreOffice is typically at:

/Applications/LibreOffice.app/Contents/MacOS/soffice

Hash Worker Configuration

A background worker calculates perceptual hashes for images, enabling visual similarity search.

Worker Settings

FlagEnv VariableDefaultDescription
-hash-worker-countHASH_WORKER_COUNT4Number of concurrent workers
-hash-batch-sizeHASH_BATCH_SIZE500Resources processed per batch
-hash-poll-intervalHASH_POLL_INTERVAL1mTime between batch cycles
-hash-similarity-thresholdHASH_SIMILARITY_THRESHOLD10Maximum Hamming distance for similarity
-hash-ahash-thresholdHASH_AHASH_THRESHOLD5Max AHash Hamming distance for the secondary similarity check; 0 disables it
-hash-worker-disabledHASH_WORKER_DISABLED=1falseDisable the hash worker entirely
-hash-cache-sizeHASH_CACHE_SIZE100000Max entries in hash similarity LRU cache

Tuning for Your Hardware

High-performance server:

./mahresources \
-hash-worker-count=8 \
-hash-batch-size=1000 \
-hash-poll-interval=30s \
...

Resource-constrained environment:

./mahresources \
-hash-worker-count=1 \
-hash-batch-size=100 \
-hash-poll-interval=5m \
...

Disable entirely:

./mahresources -hash-worker-disabled ...

Similarity Threshold

The -hash-similarity-threshold controls how similar images must be to be considered matches:

  • Lower values (e.g., 5): Stricter matching, finds near-duplicates only
  • Higher values (up to the maximum of 11): Looser matching, finds more variations. Pairs are only stored up to distance 11, so a larger value has no additional effect and the runtime setting refuses it
  • Default (10): Good balance for finding similar images

Thumbnail Worker Configuration

A background worker generates thumbnails for video files using FFmpeg. It runs in batch cycles, similar to the hash worker.

FlagEnv VariableDefaultDescription
-thumb-worker-countTHUMB_WORKER_COUNT2Concurrent thumbnail workers
-thumb-worker-disabledTHUMB_WORKER_DISABLED=1falseDisable the thumbnail worker entirely
-thumb-batch-sizeTHUMB_BATCH_SIZE10Videos processed per backfill cycle
-thumb-poll-intervalTHUMB_POLL_INTERVAL1mTime between backfill cycles
-thumb-backfillTHUMB_BACKFILL=1falseBackfill thumbnails for existing videos

Enable backfill to generate thumbnails for videos that were uploaded before FFmpeg was configured:

./mahresources \
-thumb-backfill \
-thumb-worker-count=4 \
-thumb-batch-size=50 \
...

Video Thumbnail Settings

Fine-tune individual video thumbnail generation:

FlagEnv VariableDefaultDescription
-video-thumb-timeoutVIDEO_THUMB_TIMEOUT30sTimeout for a single FFmpeg thumbnail job
-video-thumb-lock-timeoutVIDEO_THUMB_LOCK_TIMEOUT60sTimeout waiting for a thumbnail lock
-video-thumb-concurrencyVIDEO_THUMB_CONCURRENCY4Max concurrent video thumbnail jobs

Network Timeouts

Configure timeouts for downloading remote resources:

FlagEnv VariableDefaultDescription
-remote-connect-timeoutREMOTE_CONNECT_TIMEOUT30sTimeout for establishing connection
-remote-idle-timeoutREMOTE_IDLE_TIMEOUT60sTimeout when no data is received
-remote-overall-timeoutREMOTE_OVERALL_TIMEOUT30mMaximum total download time
-remote-user-agentREMOTE_USER_AGENTbrowser-likeUser-Agent the server's own fetches send

For Slow Networks

./mahresources \
-remote-connect-timeout=60s \
-remote-idle-timeout=120s \
-remote-overall-timeout=1h \
...

For Large Files

./mahresources \
-remote-overall-timeout=2h \
...

MRQL Query Timeout

Limits the maximum execution time for MRQL (Mahresources Query Language) queries:

FlagEnv VariableDefaultDescription
-mrql-query-timeoutMRQL_QUERY_TIMEOUT10sMaximum execution time for a single MRQL query
# Allow longer-running MRQL queries
./mahresources -mrql-query-timeout=30s ...

Inline MRQL Page Query Budget

Bounds how many distinct MRQL queries a single page render may execute through inline [mrql] shortcodes:

FlagEnv VariableDefaultDescription
-mrql-page-query-budgetMRQL_PAGE_QUERY_BUDGET200Maximum distinct inline [mrql] queries per page render; 0 disables

Because a category's Custom* templates render once per card, an entity-scoped [mrql] in a CustomSummary runs one query per card -- so a list page of many cards can execute many queries. Identical queries within a render are deduplicated by a per-page cache (free); each cache miss consumes one unit of budget. Once the budget is spent, further distinct queries render the standard MRQL error box ("inline query budget exceeded (N per page)…") instead of executing, and one warning per page is written to the activity log (entity type mrql).

The default of 200 is generous -- a three-query summary on a 20-card page is only 60. Raise it if a legitimately dense page trips the limit, or set 0 to disable entirely (deployments with millions of resources are the motivation for keeping it on).

# Raise the per-page inline-MRQL budget
./mahresources -mrql-page-query-budget=500 ...

MRQL Natural-Language Generation

MRQL generation is optional and configured with environment variables only. There are no CLI flags for the provider credentials in v1.

Env VariableDefaultDescription
DEEPSEEK_API_KEY(disabled)DeepSeek API key for /mrql natural-language generation
DEEPSEEK_MODELdeepseek-v4-proDeepSeek model used to draft MRQL
DEEPSEEK_TIMEOUT20sTimeout for one DeepSeek MRQL generation call. Invalid duration values fail startup
DEEPSEEK_API_KEY=sk-...
DEEPSEEK_MODEL=deepseek-v4-pro
DEEPSEEK_TIMEOUT=20s

For the /mrql editor the server sends only the prompt text entered there plus syntax-only MRQL instructions. It does not send local tag lists, categories, saved queries, or database contents to the provider.

DEEPSEEK_API_KEY also enables template generation in the Category, Resource Category and Note Type editors, which additionally sends the Meta JSON Schema being authored and one sample entity's metadata. See Custom Templates.

Deferred Render Signing Key

The [lazy], [details] and [reload] shortcodes defer part of a template and hand the browser a sealed token to open it with. The key that seals those tokens is configured with an environment variable only.

Env VariableDefaultDescription
TEMPLATE_SIGNING_KEY(per-boot random)Secret used to seal the [lazy], [details] and [reload] deferred-render tokens

When it is unset, each process generates a random key at boot, so a deferred region rendered by one process cannot be opened by another. Set it to a shared value across every process in a multi-process or load-balanced deployment. See Shortcodes.

Upload and Request Size Limits

Bound the size of request bodies the server accepts:

FlagEnv VariableDefaultDescription
-max-upload-sizeMAX_UPLOAD_SIZE2147483648 (2 GiB)Maximum per-upload body size in bytes for resource and version uploads; 0 = unlimited
-max-import-sizeMAX_IMPORT_SIZE10737418240 (10 GiB)Maximum group-import tar upload size in bytes
-max-json-bodyMAX_JSON_BODY0 (unlimited)Maximum application/json request body size in bytes; 0 disables the limit
-max-user-tokensMAX_USER_TOKENS100Maximum API tokens a single user may hold; 0 disables the cap
Harden JSON limits under -auth

-max-json-body defaults to 0 (unlimited) to preserve the historical unbounded behaviour. When -auth is enabled, any authenticated user can POST JSON, so setting an explicit limit is recommended. The limit keys on Content-Type, so multipart uploads (bounded by -max-upload-size) are unaffected.

Background Jobs and Exports

FlagEnv VariableDefaultDescription
-max-job-concurrencyMAX_JOB_CONCURRENCY6Concurrency budget for the shared background job manager
-export-retentionEXPORT_RETENTION24hHow long completed group-export tars stay on disk before cleanup

Server Binding

Configure the server address and port:

# Listen on all interfaces, port 8181
./mahresources -bind-address=:8181 ...

# Listen on localhost only
./mahresources -bind-address=127.0.0.1:8181 ...

# Custom port
./mahresources -bind-address=:3000 ...

Startup Optimizations

On large databases, certain startup operations can be slow. These flags reduce startup time:

Disables full-text search index initialization:

./mahresources -skip-fts ...

Use this if you do not need text search functionality.

Skip Version Migration

Skips the resource version migration at startup:

./mahresources -skip-version-migration ...

Useful after the initial migration has completed on a large database.

Limit Database Connections

For SQLite under concurrent load (like E2E tests):

./mahresources -max-db-connections=2 ...

Reduces lock contention at the cost of throughput under heavy load.

Share Server

A separate share server can expose notes publicly. It is disabled by default and only starts when a port is configured.

Default Bind Address

The share server binds to 0.0.0.0 (all interfaces) by default. If you only want the share server accessible locally, set -share-bind-address=127.0.0.1.

FlagEnv VariableDefaultDescription
-share-portSHARE_PORT(disabled)Port for the share server. Must be set to enable sharing.
-share-bind-addressSHARE_BIND_ADDRESS0.0.0.0Bind address for the share server
-share-public-urlSHARE_PUBLIC_URL(unset)Externally-routable base URL for shared notes (e.g. https://share.example.com). When unset, the share UI shows a warning and the relative /s/<token> path instead of a bind-address fallback.

Example

# Enable share server on port 8282 (accessible on all interfaces)
./mahresources -share-port=8282 ...

# Enable share server on localhost only
./mahresources -share-port=8282 -share-bind-address=127.0.0.1 ...

Contextual links in the app point to the published documentation site. These are runtime-editable via /admin/settings.

FlagEnv VariableDefaultDescription
-docs-site-base-urlDOCS_SITE_BASE_URLhttps://egeozcan.github.io/mahresourcesBase URL used for contextual documentation links.
-docs-links-disabledDOCS_LINKS_DISABLED=1falseHide all contextual external documentation links in the app.

Log Cleanup

Automatically delete old log entries on startup:

FlagEnv VariableDefaultDescription
-cleanup-logs-daysCLEANUP_LOGS_DAYS0 (disabled)Delete log entries older than N days on startup

Example

# Delete logs older than 90 days on each startup
./mahresources -cleanup-logs-days=90 ...

Plugin Configuration

Plugins extend Mahresources through sandboxed Lua scripts. See Plugin System for full details.

FlagEnv VariableDefaultDescription
-plugin-pathPLUGIN_PATH./pluginsDirectory to scan for plugin subdirectories
-plugins-disabledPLUGINS_DISABLED=1falseDisable the plugin system entirely

Each plugin lives in a subdirectory of the plugin path and must contain a plugin.lua file. Plugins are discovered at startup but must be explicitly enabled through the management UI or API.

# Custom plugin directory
./mahresources -plugin-path=/opt/mahresources/plugins ...

# Disable all plugins
./mahresources -plugins-disabled ...

Configuration Reference

FlagEnv VariableDefaultDescription
-bind-addressBIND_ADDRESS-Server address:port
-ffmpeg-pathFFMPEG_PATHauto-detectPath to FFmpeg binary
-libreoffice-pathLIBREOFFICE_PATHauto-detectPath to LibreOffice binary
-hash-worker-countHASH_WORKER_COUNT4Concurrent hash workers
-hash-batch-sizeHASH_BATCH_SIZE500Resources per batch
-hash-poll-intervalHASH_POLL_INTERVAL1mTime between batches
-hash-similarity-thresholdHASH_SIMILARITY_THRESHOLD10Max Hamming distance
-hash-ahash-thresholdHASH_AHASH_THRESHOLD5Secondary AHash Hamming distance check; 0 disables
-hash-worker-disabledHASH_WORKER_DISABLED=1falseDisable hash worker
-hash-cache-sizeHASH_CACHE_SIZE100000Hash similarity LRU cache size
-thumb-worker-countTHUMB_WORKER_COUNT2Concurrent thumbnail workers
-thumb-worker-disabledTHUMB_WORKER_DISABLED=1falseDisable thumbnail worker
-thumb-batch-sizeTHUMB_BATCH_SIZE10Videos per backfill cycle
-thumb-poll-intervalTHUMB_POLL_INTERVAL1mTime between backfill cycles
-thumb-backfillTHUMB_BACKFILL=1falseBackfill thumbnails for existing videos
-video-thumb-timeoutVIDEO_THUMB_TIMEOUT30sTimeout per FFmpeg thumbnail job
-video-thumb-lock-timeoutVIDEO_THUMB_LOCK_TIMEOUT60sThumbnail lock timeout
-video-thumb-concurrencyVIDEO_THUMB_CONCURRENCY4Max concurrent video thumbnail jobs
-remote-connect-timeoutREMOTE_CONNECT_TIMEOUT30sConnection timeout
-remote-idle-timeoutREMOTE_IDLE_TIMEOUT60sIdle timeout
-remote-overall-timeoutREMOTE_OVERALL_TIMEOUT30mTotal download timeout
-remote-user-agentREMOTE_USER_AGENTbrowser-likeUser-Agent for the server's own fetches
-mrql-query-timeoutMRQL_QUERY_TIMEOUT10sMaximum MRQL query execution time
-skip-ftsSKIP_FTS=1falseSkip full-text search initialization
-skip-version-migrationSKIP_VERSION_MIGRATION=1falseSkip version migration
-max-db-connectionsMAX_DB_CONNECTIONS0 (no limit)Connection pool limit
-share-portSHARE_PORT(disabled)Share server port
-share-bind-addressSHARE_BIND_ADDRESS0.0.0.0Share server bind address
-share-public-urlSHARE_PUBLIC_URL(unset)Externally-routable base URL for shared notes
-docs-site-base-urlDOCS_SITE_BASE_URLhttps://egeozcan.github.io/mahresourcesBase URL for contextual documentation links
-docs-links-disabledDOCS_LINKS_DISABLED=1falseHide contextual documentation links
-cleanup-logs-daysCLEANUP_LOGS_DAYS0 (disabled)Delete old logs on startup
-plugin-pathPLUGIN_PATH./pluginsPlugin directory
-plugins-disabledPLUGINS_DISABLED=1falseDisable plugin system