Skip to content

System settings

Server-wide settings live in the Command Center. Select Settings in the sidebar, then open the area you need. Only administrators see these sections; everyone else sees just their own preferences.

This page walks through the server settings area by area. Each setting also has a key in the config file, shown in brackets where it helps.

Every settings page edits one shared draft. You can change things on several pages and save them together.

  • Review changes lists every change with its page, the saved value and the new value. Save changes saves them all at once.
  • Discard returns every page to the saved settings. Reset this page puts that page’s defaults into the draft; they’re applied when you save.
  • Pages with unsaved changes are marked in the settings list. Leaving with unsaved changes asks whether to keep editing or discard them.
  • Reloading the tab brings the draft back, except passwords, keys and addresses that contain credentials. Those are never stored in the browser.
  • If another administrator saves while you’re editing, your draft is kept. Changes to different settings are carried onto theirs and you save again. If you both changed the same setting, the page shows the saved value and yours side by side: keep your changes on top of the latest settings, or discard your draft and load the latest.
  • Actions that do something straight away, such as sending a test email or unlinking all OAuth accounts, run on their own. Sending a test email also saves the email settings, and nothing else.

Server & updates, then Configuration transfer lets you review, copy, import or export the saved settings:

  • Export as JSON and Copy to clipboard leave out passwords, secrets and keys.
  • Import from JSON puts the file’s settings into your draft so you can review them before saving. Settings this server doesn’t have are listed and ignored, and credentials in the file are never applied.

If you’d rather manage settings from a file on disk, see Config file.

Change history lists every change saved from the settings pages, including credential changes, newest first. Each entry shows the administrator who saved it, the time, and each setting before and after. It’s kept on the server, so every administrator sees the same list of the latest 50 saves. Credentials only ever appear as replaced or cleared.

The OAuth client secret and the SMTP password are write-only. Their rows show Stored or Not set, never the value itself.

  • Replace credential opens a dialog with a single field. The value is sent once, checked like any other change (a new SMTP password is tested against the mail server, for example), and cleared from the dialog when it closes.
  • Clear removes the stored value after you confirm.
  • Saving any other setting, copying, exporting or importing never carries a credential.
  • A stored secret never follows a change of server. Saving a different mail server host or username clears the SMTP password, and saving a different OAuth issuer URL clears the client secret. Replace the credential for the new server afterwards.
  • Send test email uses the stored SMTP password as long as the server, port, username and security settings on the page match the saved ones.
  • Every replacement or removal is written to the server log by credential name and administrator, never by value.

Scripts can use GET /api/admin/config/credentials to see which credentials are stored, and PUT or DELETE /api/admin/config/credentials/{name} to replace or clear one. While a config file manages the settings, credentials come from that file and can’t be changed in the Command Center.

Section What it holds
Originals & folder structure The storage template, which decides how originals are named and arranged on disk, and the switch for physical deduplication
Physical deduplication Preview and apply plans that store identical files once. See Physical deduplication
Trash & retention Whether deleted items go to the trash, and for how many days
User Settings Delete delay: days before a deleted account and its files are removed
Move or export your library See Move to a new server
Setting What it does Default
Trash on (trash.enabled) Deleted photos and videos go to the trash first On
Number of days (trash.days) How long items stay in the trash before they’re permanently deleted 30

You can turn the trash off, but we don’t recommend it: everything deleted after that is removed permanently, straight away.

When you delete an account, it’s disabled at once and permanently removed after the Delete delay (user.deleteDelay, default 7 days). The deletion job runs at midnight and picks up changes to this setting on its next run. See Users.

Database backups sets the schedule and how many backups to keep. See Backup and restore.

Turn individual features on or off here, for example smart search or face recognition, and point the server at your machine learning containers.

URL (machineLearning.urls) defaults to the built-in container, http://immich-machine-learning:3003. You can add more. With several URLs, the server tries each in order until one answers, and skips ones that don’t respond until they come back. To use a more powerful computer, see Remote machine learning.

Feature Settings Defaults
Smart search Model ViT-B-16-SigLIP-384__webli
Duplicate detection Maximum detection distance, from 0.001 to 0.1. Higher finds more duplicates but may give false matches 0.01
Face recognition Model, minimum detection score, maximum recognition distance, minimum recognised faces buffalo_l, 0.7, 0.5, 3
Text recognition (OCR) Model, minimum detection and recognition scores, maximum resolution PP-OCRv5_mobile, 0.5, 0.8, 736
Image descriptions and tags Writes searchable descriptions and tags. Your own descriptions are kept, and generated tags aren’t duplicated On
NSFW detection Classifies images with a safety model and can hide flagged items behind your Locked PIN Off

Larger smart search models usually give better results but need more processing power and memory. After you change the model, run the smart search job on all photos again. Downloading a new model needs an internet connection; after that, Frameleaf doesn’t need to go online for it.

NSFW tags are searchable labels and shouldn’t be treated as a security boundary. The private NSFW flag is what hides items. See Private content and AI descriptions.

Categories & smart albums and Metadata Settings

Section titled “Categories & smart albums and Metadata Settings”

Categories & smart albums controls the rules that sort photos into categories. Metadata Settings includes whether faces stored in files’ metadata are imported (metadata.faces.import, off by default). See AI descriptions and smart albums.

Frameleaf makes three smaller versions of every photo: a blurred placeholder, a thumbnail for the timeline and albums, and a preview for the photo viewer and machine learning.

Setting What it does Default
Thumbnail format WebP files are smaller than JPEG but slower to make WebP
Thumbnail resolution Used when viewing groups of photos 250
Preview format As above, for the single-photo view JPEG
Preview resolution Used for the single-photo view and machine learning 1440
Quality 1 to 100. Higher looks better but makes larger files 80
Prefer wide gamut Use Display P3 so vivid photos keep their colour. sRGB photos stay sRGB. Very old browsers may show colours differently On
Prefer embedded preview Use the preview built into RAW files as the starting point. Can give more accurate colour, but quality depends on the camera Off
Full-size image Also make a full-size JPEG for formats browsers can’t show Off

Higher resolutions keep more detail but take longer, use more space and can make the apps feel slower. To save space, you can lower the preview resolution from 1440 to 1080 or 720.

For videos, Frameleaf samples several frames before it picks the thumbnail. On longer videos it prefers frames at least 30 seconds in, and it skips black, blown-out or flat frames.

These settings control when Frameleaf makes an extra, easy-to-play copy of a video. Streams that aren’t transcoded are left exactly as they were. Video transcoding covers every option and hardware encoding in depth.

Setting What it does Default
Transcode policy (ffmpeg.transcode) Which videos get a playback copy (see below) required
Video codec (ffmpeg.targetVideoCodec) h264, hevc, vp9 or av1 h264
Audio codec (ffmpeg.targetAudioCodec) mp3, aac or opus aac
Target resolution (ffmpeg.targetResolution) The longest side is scaled down to this, keeping the shape. Videos are never scaled up 720
Preset (ffmpeg.preset) How much effort goes into encoding, using the H.264 preset names ultrafast
Accepted containers (ffmpeg.acceptedContainers) Videos in any other container are repackaged as MP4, even when nothing needs transcoding mov, ogg, webm
Accepted video codecs Codecs that don’t need transcoding h264
Accepted audio codecs Codecs that don’t need transcoding aac, mp3, opus
Constant rate factor (ffmpeg.crf) Quality level. Lower is better quality and larger files 23
Max bitrate (ffmpeg.maxBitrate) Used by the bitrate policy. 0 means no limit 0

The required policy only transcodes videos that aren’t in an accepted format, such as HDR videos or codecs browsers can’t play. The other policies (bitrate, optimal, all and disabled) are explained in Video transcoding.

Video and audio are decided separately: if only the video needs transcoding, the audio is copied as it is.

External Library holds the scan settings for external libraries:

Setting What it does Default
Periodic Scanning Rescan every external library on a schedule. Choose a preset or write a cron expression On, every night at midnight (0 0 * * *)
Library watching [EXPERIMENTAL] Import changed files as soon as the operating system reports them. Doesn’t work for network drives Off

Media health & integrity holds the integrity check schedules. Missing-file, untracked-file and checksum checks each run every night at 3 am by default. See System integrity and Library Care.

Concurrency, meaning how many of each kind of job run at once, is set in the Job manager’s concurrency dialog and saved through the same review draft. Higher concurrency gets more done per hour but doesn’t make any single action faster. Smart search, face detection, face recognition and video transcoding are heavy, so raise them carefully.

Job Default concurrency
Thumbnail generation 3
Metadata extraction 5
Video conversion 1
Face detection 2
Smart search 2
Text recognition (OCR) 1
Library, sidecar, search, migration, notifications, background tasks 5 each

Face recognition always runs one at a time, because the clustering it uses isn’t parallel. See Jobs and queues for what each queue does.

Workers, workload destinations, render workers and hardware are covered in Workers and where jobs run and Hardware acceleration.

Nightly tasks start at 00:00 by default (nightlyTasks.startTime). Each can be turned off: database clean-up, generating memories, syncing storage quota usage, making missing thumbnails and grouping new faces.

Account & link, Plan, Licence, Remote access, Cloud processing and Cloud backup. Everything here is optional; the server works fully without it. See Frameleaf Cloud.

The address the server puts in shared links, emails, maintenance sign-in links and sign-in callbacks is set in Frameleaf Cloud, then Remote access, then Public server URL (server.externalDomain). It’s saved with your other changes, doesn’t need a cloud link, and shouldn’t end with a slash. Without it, emails are sent without links. See Email.

Section What it holds
Sign-in methods Password login and your own OAuth provider. See Sign-in and OAuth
Sign in with Frameleaf Sign-in with Frameleaf accounts once the server is linked

Each person’s own password, Locked PIN, devices and API keys are in the same area.

Email delivery connects the server to a mail server, and Email Templates changes the text of the emails. See Email.

Setting What it does Default
Server name (server.name) Shown in the Command Center and the apps’ server picker. Leave empty to show the server’s address Empty
Welcome message (server.loginPageMessage) A message on the sign-in page, shown to everyone Empty
Public Users (server.publicUsers) When on, everyone sees all users’ names and emails when sharing albums. When off, only administrators see the list On
Local network discovery (server.lanDiscovery) Lets the Frameleaf apps on the same Wi-Fi find the server without typing an address On

While it’s on, the server advertises one DNS-SD (Bonjour/mDNS) service on your network:

Field Value
Service type _frameleaf._tcp
Port The server’s HTTP port (FRAMELEAF_PORT, 2283 by default)
Service name The server name, or Frameleaf server when none is set
TXT id The Frameleaf Cloud instance ID while linked, otherwise a stable local ID
TXT name The server name
TXT setup needed while the server has no administrator, otherwise complete
TXT linked true while linked to Frameleaf Cloud, otherwise false
TXT cloud available when FRAMELEAF_CLOUD_URL is set, otherwise unavailable

The same identity is returned by the unauthenticated GET /api/server/ping, so an app can confirm it reached the server it expects. Nothing about users, content or the setup code is advertised.

The server only advertises when it can see a network interface on your LAN. Inside a container on a Docker bridge network it usually can’t, so nothing is advertised; use host networking if you want discovery from a container. Anyone on the network can see the server name, so pick one that doesn’t reveal a person’s name. Turning discovery off doesn’t change direct connections or sign-in.

Custom CSS (theme.customCss) is loaded in the web app for everyone, so you can change fonts, colours and other styles:

p {
color: green;
}

With Check for updates on, the server asks Frameleaf’s release feed for a new version, daily or weekly (Check frequency), and administrators see an announcement linking to the release notes. If the feed can’t answer, it asks Frameleaf’s own GitHub releases instead. No other service is contacted, and no library data or server identifier is sent.

Setting Options Default
Check for updates (newVersionCheck.enabled) On or off Off
Release channel (newVersionCheck.channel) stable, or beta to include release candidates stable
Check frequency (newVersionCheck.frequency) daily or weekly daily

Checking never installs anything. You can also check at any time with Check for updates, even when automatic checks are off. See Upgrading.

The log level defaults to log (often called “info”). Choose verbose or debug for more detail when troubleshooting, or warn or error for less. Telemetry is permanently off in Frameleaf. See Monitoring and logs.

Choose the light and dark map styles (map.lightStyle, map.darkStyle), or turn the map off. Reverse geocoding (reverseGeocoding.enabled, on by default) turns GPS coordinates into place names using data from the GeoNames geographical database.

A new server has no administrator. Until it has one, it prints a setup code of eight letters and digits, shown as XXXX-XXXX, on its console and in its log every time it starts, along with a QR code for the Frameleaf app to scan. The code proves you control the server: whoever reaches it first can’t claim it without the code.

Where to find it

  • With Docker Compose: docker compose logs immich-server, or print it again with:

    Terminal window
    docker compose exec immich-server frameleaf-admin setup-code
  • On Unraid, TrueNAS or Synology: the container’s log.

How it behaves

  • A new code is made every time the server starts. After five wrong tries a new code is shown and the old one stops working.
  • It only works from your home network, never over remote access. A request counts as home when it comes from a private address, or through a trusted local reverse proxy that passes the visitor’s address in X-Forwarded-For. Tries are limited per address.
  • It stops working once an administrator exists.
  • It’s printed to the console whatever the log level, so it’s only as private as the console and log. Once the server is set up, it’s worthless.
  • For a server that isn’t on your home network, such as a rented server, connect through an SSH tunnel or add your network to FRAMELEAF_TRUSTED_LAN_CIDRS.
  • For automated installs and tests you can pin the code with FRAMELEAF_SETUP_CODE. A pinned code isn’t replaced after wrong tries; it locks until the next start instead, so anyone on the network could lock it. Don’t pin it on a server people use.

Three ways to claim a server, each needing the code:

  1. On its web page. The first-run page asks for the code with the administrator’s name, email and password.
  2. In the Frameleaf app, with a Frameleaf account. The server links itself to your account, and your first Sign in with Frameleaf creates the administrator, with no server password. Only that account can become the first administrator.
  3. In the Frameleaf app, with a password. The app creates the administrator with an email and password, for a server without Frameleaf Cloud.

Setting FRAMELEAF_LINK_TOKEN needs no code, because whoever can set it already controls the host. See Frameleaf Cloud account.