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.
Saving changes
Section titled “Saving changes”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.
Configuration transfer
Section titled “Configuration transfer”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
Section titled “Change history”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.
Server credentials
Section titled “Server credentials”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.
Storage & originals
Section titled “Storage & originals”| 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.
Delete delay
Section titled “Delete delay”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.
Import & protection
Section titled “Import & protection”Database backups sets the schedule and how many backups to keep. See Backup and restore.
Search & intelligence
Section titled “Search & intelligence”Machine Learning Settings
Section titled “Machine Learning Settings”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.
Editing & playback
Section titled “Editing & playback”Image previews
Section titled “Image previews”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.
Video playback proxies
Section titled “Video playback proxies”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.
Libraries
Section titled “Libraries”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 |
Library care
Section titled “Library care”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.
Compute & jobs
Section titled “Compute & jobs”Job manager
Section titled “Job manager”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 work & model cache
Section titled “Nightly work & model cache”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.
Frameleaf Cloud
Section titled “Frameleaf Cloud”Account & link, Plan, Licence, Remote access, Cloud processing and Cloud backup. Everything here is optional; the server works fully without it. See Frameleaf Cloud.
Public server URL
Section titled “Public server URL”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.
Access & security
Section titled “Access & security”| 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.
Notifications
Section titled “Notifications”Email delivery connects the server to a mail server, and Email Templates changes the text of the emails. See Email.
Server & updates
Section titled “Server & updates”Server identity
Section titled “Server identity”| 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 |
Local network discovery
Section titled “Local network discovery”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.
Branding & client compatibility
Section titled “Branding & client compatibility”Custom CSS (theme.customCss) is loaded in the web app for everyone, so you can change fonts, colours and other styles:
p { color: green;}Versions & compatibility
Section titled “Versions & compatibility”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.
Logs & diagnostics
Section titled “Logs & diagnostics”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.
Maps & geography
Section titled “Maps & geography”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.
Setting up a new server
Section titled “Setting up a new server”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:
- On its web page. The first-run page asks for the code with the administrator’s name, email and password.
- 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.
- 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.