Environment variables
Most Frameleaf settings live in the web app. A few are set as environment variables instead, usually in the .env file next to your docker-compose.yml. This page lists them all.
In the tables, Containers says which container reads the variable: the server, the machine learning container or the database. If you split the server into separate api and microservices workers, give each the variables it needs.
The basics
Section titled “The basics”These are used by docker-compose.yml itself and don’t reach the containers directly.
| Variable | What it does | Default |
|---|---|---|
UPLOAD_LOCATION |
Folder on the host where your photos and videos are stored | ./library in the example file |
DB_DATA_LOCATION |
Folder on the host for the database. Network shares aren’t supported | ./postgres in the example file |
FRAMELEAF_VERSION |
Which image tag to run. Release bundles pin this to their version | release |
The Compose files use ${FRAMELEAF_VERSION:-${IMMICH_VERSION:-release}}, so an older .env with IMMICH_VERSION still picks the tag when FRAMELEAF_VERSION isn’t set.
General
Section titled “General”| Variable | What it does | Default | Containers |
|---|---|---|---|
TZ |
Time zone, for example Etc/UTC. Used for log times, scheduled jobs, and photos whose metadata has no time zone |
server | |
FRAMELEAF_ENV |
production or development |
production |
server, machine learning |
FRAMELEAF_LOG_LEVEL |
verbose, debug, log, warn or error |
log |
server, machine learning |
FRAMELEAF_LOG_FORMAT |
console or json |
console |
server |
FRAMELEAF_MEDIA_LOCATION |
Media folder inside the container. You almost certainly shouldn’t set this | /data |
server |
FRAMELEAF_CONFIG_FILE |
Path to a config file inside the container | server | |
FRAMELEAF_HELMET_FILE |
Path to a JSON file of security header options. true uses the built-in file, false turns it off |
false |
server |
NO_COLOR |
Set to true to turn off coloured log output |
false |
server, machine learning |
CPU_CORES |
Number of CPU cores available to the server | detected | server |
FRAMELEAF_PROCESS_INVALID_IMAGES |
When true, make thumbnails for images that fail validation |
server | |
FRAMELEAF_TRUSTED_PROXIES |
Comma-separated IPs of reverse proxies to trust | server | |
FRAMELEAF_IGNORE_MOUNT_CHECK_ERRORS |
Start even when the storage folder checks fail. Only for troubleshooting | server | |
FRAMELEAF_IMPORT_ROOTS |
Comma-separated folders administrators may import Google Photos Takeout exports from | server | |
FRAMELEAF_ALLOW_SETUP |
Set to false to turn off the admin sign-up and start-restore endpoints |
true |
server |
Set UPLOAD_LOCATION, not FRAMELEAF_MEDIA_LOCATION. The second is the path inside the container, and pointing it at a host folder will break things.
| Variable | What it does | Default | Containers |
|---|---|---|---|
FRAMELEAF_HOST |
Address to listen on | 0.0.0.0 |
server, machine learning |
FRAMELEAF_PORT |
Port to listen on | 2283 (server), 3003 (machine learning) |
server, machine learning |
Database
Section titled “Database”| Variable | What it does | Default | Containers |
|---|---|---|---|
DB_URL |
Full connection string. Replaces the separate values below | server | |
DB_HOSTNAME |
Database host | database |
server |
DB_PORT |
Database port | 5432 |
server |
DB_USERNAME |
Database user | postgres |
server, database |
DB_PASSWORD |
Database password. Use only letters and numbers | postgres |
server, database |
DB_DATABASE_NAME |
Database name | immich |
server, database |
DB_SSL_MODE |
Database SSL mode | server | |
DB_VECTOR_EXTENSION |
vectorchord or pgvector. Detected automatically when not set |
server | |
DB_SKIP_MIGRATIONS |
Skip database migrations at startup, for restores | false |
server |
DB_STORAGE_TYPE |
Set to HDD if the database isn’t on an SSD |
SSD |
database |
DB_USERNAME, DB_PASSWORD and DB_DATABASE_NAME are passed to the database container as POSTGRES_USER, POSTGRES_PASSWORD and POSTGRES_DB. The database is still called immich by default, so existing installs keep working.
DB_URL looks like postgresql://user:password@host:port/database. Add ?sslmode=require to require SSL, or ?sslmode=require&uselibpqcompat=true to require SSL without checking the certificate. When DB_URL is set, DB_HOSTNAME, DB_PORT, DB_USERNAME, DB_PASSWORD and DB_DATABASE_NAME are ignored.
DB_STORAGE_TYPE mainly controls how many disk reads Postgres makes at once. We recommend keeping the database on an SSD where possible. All DB_ variables must be given to every server worker.
| Variable | What it does | Default |
|---|---|---|
REDIS_URL |
Full Redis address: ioredis:// followed by base64-encoded JSON configuration |
|
REDIS_SOCKET |
Redis socket | |
REDIS_HOSTNAME |
Redis host | redis |
REDIS_PORT |
Redis port | 6379 |
REDIS_USERNAME |
Redis username | |
REDIS_PASSWORD |
Redis password | |
REDIS_DBINDEX |
Redis database index | 0 |
When REDIS_URL or REDIS_SOCKET is set, the other Redis variables are ignored. All REDIS_ variables must be given to every server worker. For Redis Sentinel, encode JSON like this as base64:
{ "sentinels": [ { "host": "redis-sentinel-node-0", "port": 26379 }, { "host": "redis-sentinel-node-1", "port": 26379 }, { "host": "redis-sentinel-node-2", "port": 26379 } ], "name": "redis-sentinel"}Frameleaf Cloud
Section titled “Frameleaf Cloud”| Variable | What it does | Default |
|---|---|---|
FRAMELEAF_CLOUD_URL |
Set to https://api.frameleaf.cloud to use Frameleaf Cloud. Left unset, nothing is ever contacted |
|
FRAMELEAF_PUSH_URL |
Set to https://push.frameleaf.cloud for push notifications to the Frameleaf apps |
|
FRAMELEAF_IDENTITY_DIR |
Folder holding the server’s identity key. Must be persistent storage | <media>/frameleaf/identity |
FRAMELEAF_LINK_TOKEN |
Single-use token (fll_…) that links the server to your Frameleaf account at startup, without a browser |
|
FRAMELEAF_SETUP_CODE |
Pins the setup code a new server asks for, for automated installs and tests | |
FRAMELEAF_EDGE_PORT |
Port for direct remote access | 2443 |
FRAMELEAF_EDGE_BIND |
Address the direct remote access listener binds to | 0.0.0.0 |
FRAMELEAF_ACME_DIRECTORY_URL |
Where certificates come from. Only for Let’s Encrypt staging or a test certificate authority | Let’s Encrypt |
FRAMELEAF_TRUSTED_LAN_CIDRS |
Extra networks, as comma-separated CIDRs, that count as home besides private ranges | |
FRAMELEAF_EDGE_SECRET |
Shared secret between the server and the remote access listener. Set it only when the listener runs in another container, to the same value in both | generated each start |
FRAMELEAF_LOCAL_URL |
The server’s address on your home network, offered to visitors on the same network |
Create a link token in your Frameleaf account under Servers, then Add server. It works once and expires within an hour. Remove it from .env once the server shows as linked. A malformed token, port or network stops the server at startup. See Frameleaf Cloud account.
Library Care
Section titled “Library Care”| Variable | What it does | Default |
|---|---|---|
FRAMELEAF_RECOVERY_ROOTS |
Folders Library Care may search for exact copies of missing files, as Label=/path;Label=/path. Only ever read |
Each entry is an absolute path inside the container, optionally labelled. A copy found there is copied into library storage before the item is relinked to it.
App releases
Section titled “App releases”These let your server offer its own signed builds of the Frameleaf apps.
| Variable | What it does |
|---|---|
FRAMELEAF_ANDROID_RELEASE_URL |
HTTPS folder holding your signed Android APKs. {version} is replaced with the server version |
FRAMELEAF_ANDROID_APP_ID |
Android package ID the APKs are signed as |
FRAMELEAF_ANDROID_SIGNING_SHA256 |
SHA-256 fingerprint of the signing certificate, shown before people install |
FRAMELEAF_IOS_APP_URL |
HTTPS App Store or TestFlight page of the iPhone app |
FRAMELEAF_ANDROID_STORE_URL |
HTTPS store listing of the Android app, offered next to the APKs |
The folder must contain app-arm64-v8a-release.apk, app-armeabi-v7a-release.apk, app-x86_64-release.apk and app-release.apk. Android downloads and Obtainium setup are only offered when all three Android variables are set, and a value that’s set but invalid stops the server at startup. Include {version} in the folder so Obtainium recognises each new release.
Help links
Section titled “Help links”| Variable | What it does |
|---|---|
FRAMELEAF_DOCS_URL |
HTTPS address of your installation’s documentation |
FRAMELEAF_SUPPORT_URL |
HTTPS address where people get help with your installation |
FRAMELEAF_BUG_FEATURE_URL |
HTTPS address for reporting problems and requesting features |
FRAMELEAF_SOURCE_URL |
HTTPS address of the source code your installation runs |
Help, settings and sign-in pages only show these links when they’re set. A value that isn’t an HTTPS address, or that contains a user name or password, stops the server at startup. The older IMMICH_THIRD_PARTY_DOCUMENTATION_URL, IMMICH_THIRD_PARTY_SUPPORT_URL, IMMICH_THIRD_PARTY_BUG_FEATURE_URL and IMMICH_THIRD_PARTY_SOURCE_URL still work when the Frameleaf name isn’t set, but only an HTTPS value is used.
Workers
Section titled “Workers”| Variable | What it does |
|---|---|
FRAMELEAF_WORKERS_INCLUDE |
Only run these workers |
FRAMELEAF_WORKERS_EXCLUDE |
Don’t run these workers |
See Workers and where jobs run.
Stopping
Section titled “Stopping”| Variable | What it does | Default |
|---|---|---|
FRAMELEAF_SHUTDOWN_GRACE_SECONDS |
How long running jobs and requests get to finish when the server stops. Jobs still running then go back to waiting | 5 |
FRAMELEAF_SHUTDOWN_DEADLINE_SECONDS |
When the server exits, whatever is still running. Must be greater than the grace period | 9 |
Both must be positive, and the grace period must end before the deadline, or the server won’t start. Docker kills the container when its stop timeout ends, so stop_grace_period in docker-compose.yml must be longer than the deadline. The supplied Compose files and NAS packages use 10 seconds, which fits the defaults.
Machine learning
Section titled “Machine learning”| Variable | What it does | Default |
|---|---|---|
MACHINE_LEARNING_MODEL_TTL |
Seconds of inactivity before a model is unloaded from memory. 0 or less turns this off |
300 |
MACHINE_LEARNING_MODEL_TTL_POLL_S |
Seconds between checks of the model TTL | 10 |
MACHINE_LEARNING_CACHE_FOLDER |
Folder models are downloaded to | /cache |
MACHINE_LEARNING_MODEL_SOURCE_URL |
Where smart search, face and text recognition models download from | https://models.frameleaf.cloud |
MACHINE_LEARNING_MODEL_SOURCE_TOKEN |
Token sent to a custom model source that needs one. Never logged | |
MACHINE_LEARNING_REQUEST_THREADS |
Threads handling requests. Start here when tuning | number of CPU cores |
MACHINE_LEARNING_MODEL_INTER_OP_THREADS |
Model operations run in parallel | 1 |
MACHINE_LEARNING_MODEL_INTRA_OP_THREADS |
Threads for each model operation | 2 |
MACHINE_LEARNING_WORKERS |
Worker processes. Each one loads its own copy of the models, so only raise this with plenty of memory | 1 |
MACHINE_LEARNING_HTTP_KEEPALIVE_TIMEOUT_S |
HTTP keep-alive time in seconds | 2 |
MACHINE_LEARNING_WORKER_TIMEOUT |
Seconds a worker may be unresponsive before it’s restarted | 300 (900 with ROCm) |
MACHINE_LEARNING_PRELOAD__CLIP__TEXTUAL |
Smart search text models to load at startup, comma-separated | |
MACHINE_LEARNING_PRELOAD__CLIP__VISUAL |
Smart search image models to load at startup | |
MACHINE_LEARNING_PRELOAD__FACIAL_RECOGNITION__RECOGNITION |
Face recognition models to load at startup | |
MACHINE_LEARNING_PRELOAD__FACIAL_RECOGNITION__DETECTION |
Face detection models to load at startup | |
MACHINE_LEARNING_PRELOAD__OCR__RECOGNITION |
Text recognition models to load at startup | |
MACHINE_LEARNING_PRELOAD__OCR__DETECTION |
Text detection models to load at startup | |
MACHINE_LEARNING_DEVICE_IDS |
GPU IDs to use on a multi-GPU machine. Needs MACHINE_LEARNING_WORKERS above 1; each worker gets one device in turn |
0 |
MACHINE_LEARNING_MAX_BATCH_SIZE__FACIAL_RECOGNITION |
Faces processed at once | none (1 with OpenVINO) |
MACHINE_LEARNING_MAX_BATCH_SIZE__OCR |
Text boxes processed at once | 6 |
MACHINE_LEARNING_MODEL_ARENA |
Pre-allocates CPU memory to avoid fragmentation | true |
MACHINE_LEARNING_ANN |
Use ARM NN acceleration if supported | True |
MACHINE_LEARNING_ANN_FP16_TURBO |
Faster, less precise FP16 maths (ARM NN only) | False |
MACHINE_LEARNING_ANN_TUNING_LEVEL |
ARM NN GPU tuning: 1 rapid, 2 normal, 3 exhaustive |
2 |
MACHINE_LEARNING_RKNN |
Use RKNN acceleration if supported | True |
MACHINE_LEARNING_RKNN_THREADS |
RKNN runtime threads | 1 |
MACHINE_LEARNING_OPENVINO_PRECISION |
FP16 for faster, less accurate OpenVINO inference, or FP32 |
FP32 |
HF_ENDPOINT |
Your own model mirror. Also used for AI description and NSFW models | |
HF_HUB_OFFLINE |
Set to 1 to stop downloads once you’ve filled the model cache yourself |
Only the smart search text model is needed for searching. If first searches are slow because uploads load the other models at the same moment, preload the image, face and text models as well, if you have the memory.
Where models come from
Section titled “Where models come from”Smart search, face and text recognition models download from MACHINE_LEARNING_MODEL_SOURCE_URL if it’s set, otherwise from HF_ENDPOINT if that’s set, otherwise from Frameleaf’s model mirror at https://models.frameleaf.cloud. The container logs which source it uses at startup. The source uses the Hugging Face folder layout, so you can point it at your own mirror or an offline copy. If the source doesn’t have a model you choose, loading fails with an error naming the model and the source; it never falls back to another host. A Hugging Face token (HF_TOKEN) is only sent to huggingface.co.
AI description and NSFW detection models download from huggingface.co unless you set HF_ENDPOINT. To keep them off huggingface.co, point HF_ENDPOINT at your own mirror, or fill the model cache yourself and set HF_HUB_OFFLINE=1.
No usage statistics are sent to any host.
Keep secrets in files
Section titled “Keep secrets in files”DB_HOSTNAME, DB_DATABASE_NAME, DB_USERNAME, DB_PASSWORD, DB_URL and REDIS_PASSWORD can be read from files instead, using Docker secrets or systemd credentials. Either:
- add
_FILEto the name, for exampleDB_PASSWORD_FILE, and set it to the path of a file that contains the value, or - set
CREDENTIALS_DIRECTORYto a folder of files named after the variables. With Docker secrets,CREDENTIALS_DIRECTORY=/run/secretsuses every secret present.
No telemetry
Section titled “No telemetry”Telemetry and metrics are permanently disabled in Frameleaf. IMMICH_TELEMETRY_INCLUDE, IMMICH_TELEMETRY_EXCLUDE, IMMICH_API_METRICS_PORT and IMMICH_MICROSERVICES_METRICS_PORT are accepted so old .env files still start, but they do nothing and open no port. OTEL_* variables can’t turn telemetry back on either.
Old IMMICH_ names
Section titled “Old IMMICH_ names”Each old IMMICH_ variable that still does something has a FRAMELEAF_ name, and the old name keeps working as an alias. An .env written for Immich keeps working after you switch images. See Moving from Immich.
- If both names are set to different values, the server (or machine learning container, or CLI) refuses to start and names the pair.
- At startup, one warning lists the old names in use with their new names.
- An empty value counts as unset.
- The old names keep working for the whole of the current major version, and stop working in the next major release. No date is set for that release.
| Old name | Use instead |
|---|---|
IMMICH_VERSION |
FRAMELEAF_VERSION |
IMMICH_ENV |
FRAMELEAF_ENV |
IMMICH_LOG_LEVEL |
FRAMELEAF_LOG_LEVEL |
IMMICH_LOG_FORMAT |
FRAMELEAF_LOG_FORMAT |
IMMICH_MEDIA_LOCATION |
FRAMELEAF_MEDIA_LOCATION |
IMMICH_CONFIG_FILE |
FRAMELEAF_CONFIG_FILE |
IMMICH_HELMET_FILE |
FRAMELEAF_HELMET_FILE |
IMMICH_TRUSTED_PROXIES |
FRAMELEAF_TRUSTED_PROXIES |
IMMICH_IGNORE_MOUNT_CHECK_ERRORS |
FRAMELEAF_IGNORE_MOUNT_CHECK_ERRORS |
IMMICH_PROCESS_INVALID_IMAGES |
FRAMELEAF_PROCESS_INVALID_IMAGES |
IMMICH_ALLOW_SETUP |
FRAMELEAF_ALLOW_SETUP |
IMMICH_WORKERS_INCLUDE |
FRAMELEAF_WORKERS_INCLUDE |
IMMICH_WORKERS_EXCLUDE |
FRAMELEAF_WORKERS_EXCLUDE |
IMMICH_HOST |
FRAMELEAF_HOST |
IMMICH_PORT |
FRAMELEAF_PORT |
IMMICH_IMPORT_ROOTS |
FRAMELEAF_IMPORT_ROOTS |
IMMICH_ALLOW_EXTERNAL_PLUGINS |
FRAMELEAF_ALLOW_EXTERNAL_PLUGINS |
IMMICH_PLUGINS_INSTALL_FOLDER |
FRAMELEAF_PLUGINS_INSTALL_FOLDER |
IMMICH_BUILD, IMMICH_BUILD_URL, IMMICH_BUILD_IMAGE, IMMICH_BUILD_IMAGE_URL, IMMICH_BUILD_DATA |
The same names starting FRAMELEAF_ |
IMMICH_REPOSITORY, IMMICH_REPOSITORY_URL, IMMICH_SOURCE_REF, IMMICH_SOURCE_COMMIT |
The same names starting FRAMELEAF_ |
IMMICH_SOURCE_URL |
FRAMELEAF_SOURCE_COMMIT_URL |
IMMICH_MACHINE_LEARNING_ENABLED |
FRAMELEAF_MACHINE_LEARNING_ENABLED |
IMMICH_MACHINE_LEARNING_URL |
FRAMELEAF_MACHINE_LEARNING_URL |
IMMICH_MEDIA_VALIDATION_TIMEOUT_MS |
FRAMELEAF_MEDIA_VALIDATION_TIMEOUT_MS |
IMMICH_ICLOUD_BRIDGE_URL, IMMICH_ICLOUD_BRIDGE_TOKEN_FILE, IMMICH_ICLOUD_KEY_FILE, IMMICH_ICLOUD_CA_FILE, IMMICH_ICLOUD_STAGING_PATH, IMMICH_ICLOUD_FREE_SPACE_BYTES, IMMICH_ICLOUD_MAX_CONCURRENCY, IMMICH_ICLOUD_MAX_STAGING_BYTES |
The same names starting FRAMELEAF_ |
IMMICH_ML_AUTH_TOKEN (machine learning container) |
FRAMELEAF_ML_AUTH_TOKEN |
FRAMELEAF_SOURCE_URL isn’t the new name of IMMICH_SOURCE_URL; it’s the help link to your source code. The CLI’s old names are listed on API and CLI.