The height of the search results element was unrestricted, which meant that the
asset visibility calculations were completely incorrect. The consequence of
this is that assets which should not have been visible, were. In practical
terms, all assets below the viewport were rendered when they shouldn't have
been which is terrible for performance. Limiting the height of the viewport
fixes that calculation and assets are correctly hidden.
The consequence of limiting the height of the viewport is that the intersector
then incorrectly thought the scroll position was always at the end. This has
been fixed by calculating the position of sliding window against the calculated
asset layout container height.
Co-authored-by: Alex <alex.tran1502@gmail.com>
The thumbhash had a z-index setting which meant it would cover the search bar,
and would always cause weird animations when scrolling up in search results.
This is fixable by removing the z-index and moving it in front the other
elements to get a naturally higher higher z-index preference.
The contents of search results are slightly offset by the search bar, search
terms and spacing (margins/padding), and needs to be factored in when
calculating whether an asset is visible or not. The offset was 0, which
meant that assets were removed from view too early.
The timeline has been quite aggressive with scrolling to assets, even if they
were right in the middle of the page. If the asset is visible, then we
shouldn't scroll to it. It's really confusing when assets jump around after
being viewed.
* feat: use drift for logging
* fix: tests
* feat: use the truncate limit from constants.ts as default
* chore: move setupAll to top level and restructure
* chore: code review changes
* fix: inherits
* feat: raise log line limit to 2000
* limit getAll to 250 lines
* delete DLog and make LogRepository not a singleton
* fix: drift build settings and `make migration`
* fix: tests
* remove sensitive log
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
The search results page can become unstable with large amounts of assets, and
has therefore been limited to displaying just 5000 assets. This limit is
arbitrary and may be too restrictive.
fix video thumbnail generation for short videos
ffmpeg gives conversion failed with error 234 for short mp4 files (less
than 10s) that where converted from m2ts. Longer videos work fine.
It looks like ffmpeg has no frames left to use for generating a
thumbnail.
This change fixes this issue and seems to not change the behaviour for
other mp4 files (same thumbnail before and after change)
This might also fix all mts file thumbnail generation.
* feat: remove from album in asset viewer bar
* chore: move button to bottom bar instead of bottom sheet
* move back to bottom sheet
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
* fix: expand sheet when album search is focused
* convert GeneralBottomSheet to ConsumerStatefulWidget
* fix: cleaning up
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
* fix(mobile): disable memory lane when memories are disabled
* Update main_timeline.page.dart
* fix: formatting
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
* fix: use storageIndicator setting for beta timeline
* fix: reactively update the storage indicator icons when setting is changed
* Update drift_trash.page.dart
* override to bool for storageIndicator
- App will now kick off hashing after local sync if the lifecycle is in resumed or active state
- We now wait for hashing to complete before we kick off the upload process
* fix_Exlif_Metadata_Rating_Rounding_to_Interger
Rounding Exlif Rating Interger
Images support having numbers other than integers for the rating metadata in EXLIF. The database expects it to be an integer though. Trying to upload an image that has a rating other than an integer results in it failing to parse the image and defaulting to showing a corrupted file icon.
Rather than changing the database type, I would like to round the rating to the nearest integer so that Immich works with images that have a rating like this in their metadata.
* Changing Metadata validateRange to always round.
* Update server/src/services/metadata.service.ts
Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
---------
Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
* feat: drift edit time and date action
* feat: add edit button on asset viewer bottom sheet
* update localDateTime column in addition to createdAt to keep consistency
* fix: dont update local dateTime
Server calcs this anyway and it will be synced when the change is applied. We don't use localDateTime on mobile so there is no reason to update this value
* fix: padding around edit icon in ListTile
Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>
* chore: format
* fix: hide date edit control when asset does not have a remote
* fix: pull timezones correctly from image
---------
Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>
* fix(download): handle completed downloads and refresh albums
* fix(download): remove use of outdated AlbumService
---------
Co-authored-by: Peter Ombodi <peter.ombodi@gmail.com>
* fix user icons in album view
* revert updateUsersV1 change
* fix: UserDto merge issues
* fix: update user entity
* revert what I thought were merge issues
turns out drift cant figure out when it needs to gen a file...
* fix removed line
* handle defaults for older servers
* feat: checkpoint migrations
* fix: use parenthesis instead of brackets
* Update 1753800911775-ProfileImageCheckpointRemoval.ts
* fix: sync stream updateUsersV1
Fix the calculation for the date group width, so there's never a scenario where photos will be hidden. On mobile devices, photos in the second row can sometimes have a top of <100px, which throws off the calculation of the date group width.
feat: Support config via Systemd Credentials
See https://systemd.io/CREDENTIALS/. This is used as a fallback, so will
only be used if the `$*_FILE` var is empty. This could also be used to
implicitly use Docker Secrets by settings
`CREDENTIALS_DIRECTORY=/run/secrets` rather than setting individual
`$_*FILE` environment variables.
* fix: android widget updates
* ensure periodic work is queued when we receive an update
This will not "reset the clock" on the periodic work since we are using ExistingPeriodicWorkPolicy.UPDATE. This is needed since existing widgets have already been asked to queue their workers. If those periodic workers were overwritten by a widget update request from the app, there is no way to queue them again. onReceive gets run when the app requests a widget update so the periodic workers will get queued again.
* Clarify in log why reverse geocoding may return nothing
* Decrease log level for empty reverse geocoding response from warn to log
* Use a named constant for 25km
* Mention fallback to countries in the message
* Improve natural earth log message
* Decrease log level for empty reverse geocoding response from natural earth countries
* chore: fix typo 'make_build' -> 'make build'
* chore: add missing 'make pigeon' instruction
Turns out I was getting bit by forgetting to run `make pigeon`, which
also generates files. Perhaps it would be better to make it part of
`make build`?
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
I ran into this while testing out
<https://github.com/immich-app/immich/pull/19830>. When I add, change,
or remove a client certificate under Immich's advanced settings, the
change wouldn't take effect until some mysterious point in the future.
For example:
1. Add a client certificate. It doesn't get used.
2. Remove certificate. *Now* the client certificate from step 1) is used.
3. Restart application. Now no client certificate is used.
This all boils down to some missing `await`s. The user would change the
cert, and we'd start asynchronously saving it to the store, and while
the save is still happening, [`HttpSSLOptions` pulls the "old" value out of
`SSLClientCertStoreVal`](https://github.com/immich-app/immich/blob/v1.136.0/mobile/lib/utils/http_ssl_options.dart#L30).
With the appropriate `await`s, this behaves much more sanely.
* show only local assets from albums selected for backup
# Conflicts:
# mobile/lib/infrastructure/repositories/db.repository.drift.dart
* ignore backup selection
* fix: backup album ownerId
* fix: backup album ownerId
* only show local only assets that are selected for backup
* add index on visibility and backup selection
* fix: video not playing in search view
* remove safe area from bottom bar
* refactor stack count with a CTE and local asset with a SELECT
* fix lint
* remove redundant COALESCE
* remove stack count from main timeline query
---------
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
Co-authored-by: Alex <alex.tran1502@gmail.com>
* remove safe area from bottom bar
* fix: video not playing in search view
* stop foreground / background back on migration
---------
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
* - add component
- update server's StackCreateDto for merge parameter
- Update stackRepo to only merge stacks when merge=true (default)
- update web action handlers to show stack changes
* - make open-api
* lint & format
* - Add proper icon to 'remove from stack'
- change web unstack icon to image-off-outline
* - cleanup
* - format & lint
* - make open-api: StackCreateDto merge optional
* initial addition of new endpoint
* remove stack endpoint
* - fix up remove stack endpoint
- open-api
* - Undo stackCreate merge parameter
* - open-api typescript
* open-api dart
* Tests:
- add tests
- update assetStub.imageFrom2015 to have required stack attributes to include it with tests
* update event name
* Fix event name in test
* remove asset_update check
* - merge stack.removeAsset params into one object
- refactor asset existence check (no need for asset fetch)
- fix tests
* Don't return updated stack
* Create specialized stack id & primary asset fetch for asset removal checks
* Correct new permission names
* make sql
* - fix open-api
* - cleanup
* show beta sync stats
* show status next to jobs
* use drift devtools reset database impl
* dcm fixes
* fix: hash count
* styling
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
* feat: add fileName to downloadOriginal response
* test: add fileName to ImmichFileResponse for downloadOriginal
* lint: use single quotes for fileName string in test
* wip
* wip widgets
* more wip changes
* latest changes
* working random widget
* cleanup
* add configurable widget
* add memory widget and cleanup of codebase
* album name handling
* add deeplinks
* finish minor refactoring and add some polish :)
* fix single shot type on random widget
Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>
* switch to ExposedDropdownMenuBox for random configure activity
* handle empty album and no connection edge cases
* android project cleanup
* fix proguard and gson issues
* fix deletion handling
* fix proguard stripping for widget model classes/enums
* change random configuration activity close to a checkmark on right side
---------
Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>
* feat: add toggle to switch between Isar and Sqlite
* reset sqlite on beta
* start sync on app open in new timeline
* fix lint
* migrate hashes when new timeline is selected
* migrate hashes immediately after beta is enabled
* show loading indicator in change timeline page
* some stylings
* fix some styling issue
* release resources on isolate close
* replace route and styling
* handle migration back to old timeline
* check if a provider is mounted before calling dispose on it
* styling
* styling and button
---------
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
* fix: _shouldUseLocalAsset check
* show storage indicators in local album view
* update local thumb provider to work with remote asset
* update checks
* do not show upload button when selection is only merged assets
---------
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
Co-authored-by: Alex <alex.tran1502@gmail.com>
* prevent flashing white background in dark mode on page load/reload, tested with Safari and Chrome on macOS
* integrate into existing FOUC-prevention
---------
Co-authored-by: Evan <evan@MacBook-Pro.local>
* improvements to error handling, ability to select "Favorites" as a virtual album, fix widgets not showing image when tinting homescreen
* dont include isFavorite all the time
* remove check for if the album exists
this will never run because we default to Album.NONE and its impossible to distinguish between no album selected and album DNE (we dont know what the store ID is, only what iOS gives)
chore(deps): update dependency vite to v7 (#19657)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
* feat(mobile): drift place page
* merge main
* feat(mobile): drift place detail page (#19915)
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
* feat(mobile): hide storage indicator outside main timeline
* fix: lint
* set default as false
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
* image thumbnail refactor
* minor const-ification in new thumbnail tile
* underscore helper classes
---------
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
* cache the last image an ios widget fetched and use if a fetch fails in a future timeline build
* code review fixes
* downgrade pbx for flutter
* use cache in snapshots
* feat: video player
* use remote asset id in local query
* fix: error from pre-caching beyond total assets
* fix: flipped local videos
* incorrect aspect ratio on iOS
* ignore other storage id during equals check
---------
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
* initial attempt at new guard
* do not resolve the route when replaced
* Update gallery_guard.dart comment
---------
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
* feat(mobile): drift local albums page
* fix: lint
* refactor: use AsyncValue
* fix: lint
* local album thumbnail
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
* feat(mobile): drift archive page
* fix: lint
* feat: include local indicator
* remove join in bucket
* remove showing local indicator in bucket
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
Co-authored-by: alex <alex@localhost-live.localdomain>
* reduce timeline rebuilds
* feat: adds bottom sheet map and actions (#19692)
* adds bottom sheet map and actions
* PR feedbacks
* only reload the asset viewer if asset is changed
* styling tweak
---------
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
Co-authored-by: Alex <alex.tran1502@gmail.com>
* rename singleton and remove event prefix
* adds bottom sheet map and actions
* PR feedbacks
* refactor: use provider for viewer state
* feat: adds top and bottom app bar
* add safe area to bottom app bar
* change app and bottom bar color
* viewer - always have black background
* use the full width for the bottom sheet on landscape as well
* constraint the bottom sheet to not expand all the way
* add padding for location details in landscape
---------
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
Co-authored-by: Alex <alex.tran1502@gmail.com>
* add full image provider and refactor thumb providers
* photo_view updates
* wip: asset-viewer
* fix controller dispose on page change
* wip: bottom sheet
* fix interactions
* more bottomsheet changes
* generate schema
* PR feedback
* refactor asset viewer
* never rotate and fix background on page change
* use photoview as the loading builder
* precache after delay
* claude: optimizing rebuild of image provider
* claude: optimizing image decoding and caching
* use proper cache for new full size image providers
* chore: load local HEIC fullsize for iOS
* make controller callbacks nullable
* remove imageprovider cache
* do not handle drag gestures when zoomed
* use loadOriginal setting for HEIC / larger images
* preload assets outside timer
* never use same controllers in photo-view gallery
* fix: cannot scroll down once swipe with bottom sheet
---------
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
Co-authored-by: Alex <alex.tran1502@gmail.com>
* feat(server): check additional exif date tags
- Add support for UTC date tags (GPSDateTime, DateTimeUTC, GPSDateStamp, SonyDateTime2)
- This matches tags that exiftool-vendored uses for tzSource in extractTzOffsetFromUTCOffset()
* Review comments
* nit
* review comments
* lots of tests for exif datetime
* missed
* format
* format again
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
* feat(mobile): add album asset sync
* add SyncAlbumToAssetDeleteV1 to openapi-spec
* update delete queries to use where in statements
* clear remote album when clear remote data
* fix: bad merge
* fix: bad merge
* fix: _SyncAckV1 return type
---------
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
Co-authored-by: wuzihao051119 <wuzihao051119@outlook.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
wip: fix album asset exif and some other refactorings
feat: add album assets sync
feat: album to assets relation sync
Co-authored-by: Zack Pollard <zackpollard@ymail.com>
* feat: sliver appbar
* feat: snapping segment
* Date label font size
* lint
* fix: scrollController reinitialize multiple times
* feat: tab navigation
* chore: refactor to private widget
* feat: new control bottom app bar
* bad merge
* feat: sliver control bottom app bar
Exit slideshow when exiting fullscreen.
Browsers do not send a keyboard event when exiting fullscreen, so if
the user exits fullscreen with the escape key, the slideshow
remains open, requiring another escape key press to close it. Fix this
by listening for the fullscreenchange event and closing the slideshow
when exiting fullscreen.
* fix: devcontainer perms
* Fix host based auth
* use path tricks to get to volume mount, but remain compat with current meaning of variables
* eureka, i think
* bit of cleanup
* feat: working widgets
* chore/feat: cleaned up API, added album picker to random widget
* album filtering for requests
* check album and throw if not found
* fix app IDs and project configuration
* switch to repository/service model for updating widgets
* fix: remove home widget import
* revert info.plist formatting changes
* ran swift-format on widget code
* more formatting changes (this time run from xcode)
* show memory on widget picker snapshot
* fix: dart changes from code review
* fix: swift code review changes (not including task groups)
* fix: use task groups to run image retrievals concurrently, get rid of do catch in favor of if let
* chore: cleanup widget service in dart app
* chore: format swift
* fix: remove comma
why does xcode not freak out over this >:(
* switch to preview size for thumbnail
* chore: cropped large image
* fix: properly resize widgets so we dont OOM
* fix: set app group on logout
happens on first install
* fix: stupid app ids
* fix: revert back to thumbnail
we are hitting OOM exceptions due to resizing, once we have on-the-fly resizing on server this can be upgraded
* fix: more memory efficient resizing method, remove extraneous resize commands from API call
* fix: random widget use 12 entries instead of 24 to save memory
* fix: modify duration of entries to 20 minutes and only generate 10 at a time to avoid OOM
* feat: toggle to show album name on random widget
* Podfile lock
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
* - create constants for thet asset-viewer stack thumbnail sizes
- use 2x selected thumbnail size to set the max-height of the stack-slideshow container.
* - increase the stack-slideshow max-height as it's scrolled
* Revert "- increase the stack-slideshow max-height as it's scrolled"
This reverts commit da4614547a.
* change asset stack veritcal scroll to horizontal scroll
* Fix fade in for video-native-viewer.
The previous implementation never actually faded in the video element.
Fix this by ensuring the video element is only added to the DOM after
mounting, so Svelte can handle the fade-in transition correctly.
* Refactor asset viewing in memory page.
Split photo and video viewing into separate components to ensure they
work similarly to the assets viewer. The previous implementation faded
out the assets, while the assets-viewer only fades assets in. For
images, add a spinner while waiting for the image to load, before adding
the image to the DOM. For videos, add the video to the DOM after
mounting the component. In both cases, the assets fade in smoothly, like
the regular assets viewer.
* fix: styling
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
* re-write localization service and add translation extension
* Revert "re-write localization service and add translation extension"
This reverts commit fdd7386020.
* fix can't use context for easy_localization
* fix lint
* update new translate context
* handle context null
* revert main file
* Revert "revert main file"
This reverts commit 16faca46d0.
* remove fix nested MaterialApp
* change use t extenstion and remove translation utils
* update function call similar for consistently
---------
Co-authored-by: dvbthien <dvbthien@gmail.com>
* Match fade transition timing between photo-viewer and memory-viewer.
* Fix blank page after refreshing memory page.
If the user refreshed in the browser while on the memory page, the page
would show a blank page. This was caused by skipping initialization in
afterNavigate. Fix by always initializing the memory page in
afterNavigate.
* WIP: adding screen reader support to mobile
* implemented getAltText
* implemented alt text solution that stores the alt text in the DB, which isn't really great
* moved alt text computation to immich_thumbnail.dart
* added unit tests
* revert unintended changes
* Added text to remaining buttons in Photo page
* fixed import
* Fixed issue of easy_localization not parsing select blocks
* Transferred the new screen reader help to web frontend
* remove unused property
* npm run format:fix
* code review
* revert unwanted change
* dart fmt
* revert web changes
---------
Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
* Update synology.md
Make sure to change example.env to .env, this is not trivial for non-Docker experts.
* Update synology.md
Wrapped file names in code tags
* chore: linting
---------
Co-authored-by: Jason Rasmussen <jason@rasm.me>
* feat(mobile): Add Scrollbar for vertical scrolling on the actions button of a selected asset.
* fixed error scroll position and add more space for the scrollbar
* revert scrollbar change and display always 5.5 icons button
* minWidth set to 5.5 and used
* fix: logic and fine tuning
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
* refactor: timeline manager renames
* refactor(web): improve timeline manager naming consistency
- Rename AddContext → GroupInsertionCache for clearer purpose
- Rename TimelineDay → DayGroup for better clarity
- Rename TimelineMonth → MonthGroup for better clarity
- Replace all "bucket" references with "monthGroup" terminology
- Update all component props, method names, and variable references
- Maintain consistent naming patterns across TypeScript and Svelte files
* refactor(web): rename buckets to months in timeline manager
- Rename TimelineManager.buckets property to months
- Update all store.buckets references to store.months
- Use 'month' shorthand for monthGroup arguments (not method names)
- Update component templates and test files for consistency
- Maintain API-related 'bucket' terminology (bucketHeight, getTimeBucket)
* refactor(web): rename assetStore to timelineManager and update types
- Rename assetStore variables to timelineManager in all .svelte files
- Update parameter names in actions.ts and asset-utils.ts functions
- Rename AssetStoreLayoutOptions to TimelineManagerLayoutOptions
- Rename AssetStoreOptions to TimelineManagerOptions
- Move assets-store.spec.ts to timeline-manager.spec.ts
* refactor(web): rename intersectingAssets to viewerAssets and fix property references
- Rename intersectingAssets to viewerAssets in DayGroup and MonthGroup classes
- Update arrow function parameters to use viewerAsset/viewAsset shorthand
- Rename topIntersectingBucket to topIntersectingMonthGroup
- Fix dateGroups references to dayGroups in asset-utils.ts and album page
- Update template loops and variable names in Svelte components
* refactor(web): rename #initializeTimeBuckets to #initializeMonthGroups and bucketDateFormatted to monthGroupTitle
* refactor(web): rename monthGroupHeight to height
* refactor(web): rename bucketCount to assetsCount, bucketsIterator to monthGroupIterator, and related properties
* refactor(web): rename count to assetCount in TimelineManager
* refactor(web): rename LiteBucket to ScrubberMonth and update scrubber variables
- Rename LiteBucket type to ScrubberMonth
- Rename bucketDateFormattted to title in ScrubberMonth type
- Rename bucketPercentY to monthGroupPercentY in scrubber component
- Rename scrubBucket to scrubberMonth and scrubBucketPercent to scrubberMonthPercent
* fix remaining refs to bucket
* reset submodule to correct commit
* reset submodule to correct commit
* refactor(web): extract TimelineManager internals into separate modules
- Move search-related functions to internal/search-support.svelte.ts
- Extract websocket event handling into WebsocketSupport class
- Move utility functions (updateObject, isMismatched) to internal/utils.svelte.ts
- Update imports in tests to use new module structure
* refactor(web): extract intersection logic from TimelineManager
- Create intersection-support.svelte.ts with updateIntersection and calculateIntersecting functions
- Remove private intersection methods from TimelineManager
- Export findMonthGroupForAsset from search-support for reuse
- Update TimelineManager to use the extracted intersection functions
* refactor(web): rename a few methods in intersecting
* refactor(web): rename a few methods in intersecting
* refactor(web): extract layout logic from TimelineManager
- Create layout-support.svelte.ts with updateGeometry and layoutMonthGroup functions
- Remove private layout methods from TimelineManager
- Update TimelineManager to use the extracted layout functions
- Remove unused UpdateGeometryOptions import
* refactor(web): extract asset operations from TimelineManager
- Create operations-support.svelte.ts with addAssetsToMonthGroups and runAssetOperation functions
- Remove private asset operation methods from TimelineManager
- Update TimelineManager to use extracted operation functions with proper AssetOrder handling
- Rename getMonthGroupIndexByAssetId to getMonthGroupByAssetId for consistency
- Move utility functions from utils.svelte.ts to internal/utils.svelte.ts
- Fix method name references in asset-grid.svelte and tests
* refactor(web): extract loading logic from TimelineManager
- Create load-support.svelte.ts with loadFromTimeBuckets function
- Extract time bucket loading, album asset handling, and error logging
- Simplify TimelineManager's loadMonthGroup method to use extracted function
* refresh timeline after archive keyboard shortcut
* remove debugger
* rename
* Review comments - remove shadowed var
* reduce indents - early return
* review comment
* refactor: simplify asset filtering in addAssets method
Replace for loop with filter operation for better readability
* fix: bad merge
* refactor(web): simplify timeline layout algorithm
- Replace rowSpaceRemaining array with direct cumulative width tracking
- Invert logic from tracking remaining space to tracking used space
- Fix spelling: cummulative to cumulative
- Rename lastRowHeight to currentRowHeight for clarity
- Remove confusing lastRow variable and simplify final height calculation
- Add explanatory comments for clarity
- Rename loop variable assetGroup to dayGroup for consistency
* simplify assetsIterator usage
* merge/lint
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
The first step was missing—it's probably obvious for those already
familiar with Immich.
After I added the external library, no photos showed up anywhere and
all interfaces indicated that I had no photos
Eventually I found this "Scan" button, and after clicking it photos
started to appear. This is a necessary step before photos from the
library actually show up anywhere, so point it out explicitly.
* - updated dtos
- added inAlbums to search builder
- only check isNotInAlbum if albumIds is blank/empty
* - consider inAlbums as OR
* - make open-api-dart
* - lint & format
* - remove inAlbums groupBy clause
* - merge main open-api
* - make open-api
* - inAlbums filter AND instead of OR
* fix handling historical timezones in web client
* honor dst when calculating the timezone offset
* fix variable used to construct timezones list to honor dst
* remove unused variable. fix lint
* initial cast framework complete and mocked cast dialog working
* wip casting
* casting works!
just need to add session key check and remote video controls
* cleanup of classes
* add session expiration checks
* cast dialog now shows connected device at top of list with a list header. Discovered devices are also cached for app session.
* cast video player finalized
* show fullsize assets on casting
* translation already happens on the text element
* remove prints
* fix lintings
* code review changes from @shenlong-tanwen
* fix connect method override
* fix alphabetization
* remove important
* filter chromecast audio devices
* fix some disconnect command ordering issues and unawaited futures
* remove prints
* only disconnect if we are connected
* don't try to reconnect if its the current device
* add cast button to top bar
* format sessions api
* more formatting issues fixed
* add snack bar to tell user that we cannot cast an asset that is not uploaded to server
* make casting icon change to primary color when casting is active
* only show casting snackbar if we are casting
* dont show cast button if asset is remote and we are not casting
* stop playing media if we seek to an asset that is not remote
* remove https check since it works with local http IP addresses
* remove unneeded imports
* fix recasting when socket closes
* fix info plist formatting
* only show cast button if there is an active websocket connection (ie the server is accessible)
* add device capability bitmask checks
* small comment about bitmask
* - Add set primary primary asset button to asset viewer
* - Cleanup
- change AssetAction to contain a StackResponseDto
- Properly update displayed stack at bottom of the asset viewer
* - update the assetStore with the changed stack
* - Cleanup
* fix(mobile): remove dialog wrapper around share asset
* removed from multiple share and delete share dialog class
* Revert change to ShareDialog and useRootNavigator: false for showDialog
* Add a user setting for default album sort order.
Add a user setting under "Features" to control the initial sort order
when creating an album. Default to the existing behavior of
"newest first".
* chore: patch openapi
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
* fix: regression: sort day by fileCreatedAt again
* lint
* e2e test
* inline function
* e2e
* Address comments. Drop dayGroup and timezone in favor of localOffsetMinutes
* lint and some api-doc
* lint, more api-doc
* format
* Move minutes to fractional hours
* make sql
* merge/conflict
* merge fallout, review comments
* spelling
* drop offset from returned date
* move description into decorator where possible, regen api
* refactor: asset-store
* Potential fix for code scanning alert no. 152: Prototype-polluting function
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
---------
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
* feat: display number of likes
* fix: properly decrement like count on unlike
Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
* chore: pr feedback
* chore: updated related test
* chore: formatter run
* chore: force numberOfLikes to null in album context to pass lint
* chore: open-api updated
* fix: use undefined, not null
* styling tweaks
* chore: updated sql
---------
Co-authored-by: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com>
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
* feat(mobile): add album description functionality
- Introduced a new optional `description` field in the `Album` entity.
- Updated `AlbumViewerPageState` to manage `editDescriptionText`.
- Created `AlbumDescription` and `AlbumViewerEditableDescription` widgets for displaying and editing album descriptions.
- Enhanced `CreateAlbumPage` to include a description input field.
- Implemented backend support for updating album descriptions in `AlbumApiRepository` and `AlbumService`.
- Updated sync logic to handle album descriptions during data synchronization.
- Adjusted UI components to accommodate the new description feature.
* fix dart analysis error
* remove comment that shouldn't be there
* Album header styling
* fix: disable edit after album creation
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
* feat(mobile): add bulk download functionality and update UI messages
- Added `downloadAll` method to `IDownloadRepository` and its implementation in `DownloadRepository` to handle multiple asset downloads.
- Implemented `downloadAllAsset` in `DownloadStateNotifier` to trigger bulk downloads.
- Updated `DownloadService` to create download tasks for all selected assets.
- Enhanced UI with new download success and failure messages in `en.json`.
- Added download button to `ControlBottomAppBar` and integrated download functionality in `MultiselectGrid`.
* translations use i18n method t()
* Update mobile/lib/services/download.service.dart
Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>
* fix(mobile): update download logic in DownloadService
- Changed the download method to utilize downloadAll for handling multiple tasks.
- Simplified remoteId check by removing unnecessary condition.
* sort i18n keys
* remove the download signature from interface and logic as we use the downloadAll now
---------
Co-authored-by: shenlong <139912620+shenlong-tanwen@users.noreply.github.com>
fix(mobile): prevent upload intent replacement in splash screen
- Added a check in the SplashScreenPage to ensure that the route is only replaced when it's not a share intent
- Added lifecycle event to reset the isUpload.value when minimize the app
* improve language ui
* fix lint
* add search language, add safe area, fix button in dark
* hide apply button when search not found
---------
Co-authored-by: dvbthien <dvbthien@gmail.com>
* wip
* added user metadata key
* wip
* restructure onboarding system and add initial locale
* update language card and fix translation updating
* remove prints
* new card formattings
* fix cursed unmount effect
* add OAuth route onboarding
* remove required admin auth for onboarding
* delete the hotwire button
* update open-api files
* delete import
* fix failing oauth onboarding fields
* fix e2e test
* fix web e2e test
* add onboarding to user registration e2e test
* remove todo
this was a holdover during dev and didn't get deleted
* fix server small tests
* use onDestroy to save settings rather than a bind:this
* change to false for isOnboarded
* fix other auth small test
* provide type annotation in user factory metadata field
* remove onboardingCompelted from UserDto
* move translations to onboarding steps array and mark as derived so they update
* break language selector out into its own component as per @danieldietzler suggestion
* remove hello header on card
* fix flixkering on server privacy card
* label/id fixes
* openapi
---------
Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
* remove import and referenced file
* first pass at replacing all CircleIconButtons
* fix linting issues
* fix combobox formatting issues
* fix button context menu coloring
* remove circle icon button from search history box
* use theme switcher from UI lib
* dark mode force the asset viewer icons
* fix forced dark mode icons
* dark mode memory viewer icons
* fix: back button in memory viewer
---------
Co-authored-by: Alex <alex.tran1502@gmail.com>
* Add a new setting to toggle autoplay when showing the slideshow.
* Fix an issue where the slideshow would restart automatically when
navigating after it was paused.
* Add a keyboard shortcut 's' to start the slideshow from the asset
viewer.
* Add a keyboard shortcut ' ' to toggle the slideshow play/paused.
* Change the timeout for hiding the slideshow controls from 10 to 2.5
seconds.
* Add English translation for the 'autoplay_slideshow' setting.
Co-authored-by: Alex <alex.tran1502@gmail.com>
* Fix an issue where clicking the zoom-button after having zoomed in
would not zoom completely out, but leave the image in the zoomed-in
state. The new behavior properly zoomes the image completely out after
clicking the zoom-button.
* Revert to the default setting for `wheelZoomRatio` as the previous
setting of 0.2 was borderline unusable on a trackpad. This could
probably be moved to a user setting if needed.
* Add a keyboard shortcut 'z' to toggle image zoom.
* fix(docs): update the cli upload usage
The cli upload usage is missing some options compared to what is the current
output of `immich upload --help`. Update the docs accordingly.
Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com>
* feat(cli): add --json-output option to upload command
Add an option that allows retrieving per-file information about the
upload process. The output includes the newFiles, duplicates and
newAssets lists, but could accommodate more information later if needed.
One use case this allows for is using --dry-run to get a list of all the
files that would be uploaded, and checking them manually before an
upload. This can be particularly useful when a curated subset of images
have already been uploaded to immich and we want to double check for
some stragglers without uploading everything to immich.
The upload command has a few lines of logging, so to get an actually
parsable json one needs to strip those lines:
immich upload --dry-run * | tail -n +4 | jq .newFiles[]
Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com>
---------
Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com>
* Add automatic OpenID Connect login by using parameter `autoLaunch=1`
By launching Immich with `/auth/login?autoLaunch=1` an OpenID Connect login attempt is directly initated on installations where OAuth Auto Launch is not enabled. The intended use for this parameter is to enable Immich to be launched from e.g. Nextcloud using the _External sites_ app and the _oids_ OpenID Connect provider app so as to enable the user to directly interact with Immich without the need to press the `Login with ...` button.
* Add documentation for autolaunch by navigating to `/auth/login?autoLaunch=1`
* Look ma, no braces!
_This could be a single line_
And now it is, as is its predecessor.
* Change formatting to satisfy _prettier_
* if (condition) return true -> return condition
* More _prettier_ reformatting
* Look ma, braces!
* Update locked folder text and remove unused translations
* uppercase Locked folder in Menu
* convert some translates to icu and improve
* add iOS debug info translations for background processes
* fix lint
---------
Co-authored-by: dvbthien <dvbthien@gmail.com>
2025-05-29 15:06:08 -05:00
2285 changed files with 170138 additions and 63158 deletions
-f body="This issue has automatically been closed as it is likely a duplicate. We get a lot of duplicate threads each day, which is why we ask you in the template to confirm that you searched for duplicates before opening one." \
-f body="This discussion has automatically been closed as it is likely a duplicate. We get a lot of duplicate threads each day, which is why we ask you in the template to confirm that you searched for duplicates before opening one." \
@@ -150,12 +150,10 @@ for more info read the [release notes](https://github.com/immich-app/immich/rele
- Preview images (small thumbnails and large previews) for each asset and thumbnails for recognized faces.
- Stored in `UPLOAD_LOCATION/thumbs/<userID>`.
- **Encoded Assets:**
- Videos that have been re-encoded from the original for wider compatibility. The original is not removed.
- Stored in `UPLOAD_LOCATION/encoded-video/<userID>`.
- **Postgres**
- The Immich database containing all the information to allow the system to function properly.
**Note:** This folder will only appear to users who have made the changes mentioned in [v1.102.0](https://github.com/immich-app/immich/discussions/8930) (an optional, non-mandatory change) or who started with this version.
- Stored in `DB_DATA_LOCATION`.
@@ -201,7 +199,6 @@ When you turn off the storage template engine, it will leave the assets in `UPLO
- Temporarily located in `UPLOAD_LOCATION/upload/<userID>`.
- Transferred to `UPLOAD_LOCATION/library/<userID>` upon successful upload.
- **Postgres**
- The Immich database containing all the information to allow the system to function properly.
**Note:** This folder will only appear to users who have made the changes mentioned in [v1.102.0](https://github.com/immich-app/immich/discussions/8930) (an optional, non-mandatory change) or who started with this version.
- Stored in `DB_DATA_LOCATION`.
@@ -219,3 +216,10 @@ When you turn off the storage template engine, it will leave the assets in `UPLO
Do not touch the files inside these folders under any circumstances except taking a backup. Changing or removing an asset can cause untracked and missing files.
You can think of it as App-Which-Must-Not-Be-Named, the only access to viewing, changing and deleting assets is only through the mobile or browser interface.
:::
## Backup ordering
A backup of Immich should contain both the database and the asset files. When backing these up it's possible for them to get out of sync, potentially resulting in broken assets after you restore.
The best way of dealing with this is to stop the immich-server container while you take a backup. If nothing is changing then the backup will always be in sync.
If stopping the container is not an option, then the recommended order is to back up the database first, and the filesystem second. This way, the worst case scenario is that there are files on the filesystem that the database doesn't know about. If necessary, these can be (re)uploaded manually after a restore. If the backup is done the other way around, with the filesystem first and the database second, it's possible for the restored database to reference files that aren't in the filesystem backup, thus resulting in broken assets.
When a new asset is uploaded it kicks off a series of jobs, which include metadata extraction, thumbnail generation, machine learning tasks, and storage template migration, if enabled. To view the status of a job navigate to the Administration -> Jobs page.
Additionally, some jobs run on a schedule, which is every night at midnight. This schedule, with the exception of [External Libraries](/docs/features/libraries) scanning, cannot be changed.
Additionally, some jobs (such as memories generation) run on a schedule, which is every night at midnight by default. To change when they run or enable/disable a job navigate to System Settings -> [Nightly Tasks Settings](https://my.immich.app/admin/system-settings?isOpen=nightly-tasks).
@@ -20,7 +20,6 @@ Immich supports 3rd party authentication via [OpenID Connect][oidc] (OIDC), an i
Before enabling OAuth in Immich, a new client application needs to be configured in the 3rd-party authentication server. While the specifics of this setup vary from provider to provider, the general approach should be the same.
1. Create a new (Client) Application
1. The **Provider** type should be `OpenID Connect` or `OAuth2`
2. The **Client type** should be `Confidential`
3. The **Application** type should be `Web`
@@ -29,7 +28,6 @@ Before enabling OAuth in Immich, a new client application needs to be configured
2. Configure Redirect URIs/Origins
The **Sign-in redirect URIs** should include:
-`app.immich:///oauth-callback` - for logging in with OAuth from the [Mobile App](/docs/features/mobile-app.mdx)
-`http://DOMAIN:PORT/auth/login` - for logging in with OAuth from the Web Client
-`http://DOMAIN:PORT/user-settings` - for manually linking OAuth in the Web Client
@@ -37,21 +35,17 @@ Before enabling OAuth in Immich, a new client application needs to be configured
Redirect URIs should contain all the domains you will be using to access Immich. Some examples include:
Mobile
-`app.immich:///oauth-callback` (You **MUST** include this for iOS and Android mobile apps to work properly)
Localhost
-`http://localhost:2283/auth/login`
-`http://localhost:2283/user-settings`
Local IP
-`http://192.168.0.200:2283/auth/login`
-`http://192.168.0.200:2283/user-settings`
Hostname
-`https://immich.example.com/auth/login`
-`https://immich.example.com/user-settings`
@@ -68,8 +62,9 @@ Once you have a new OAuth client application configured, Immich can be configure
| Scope | string | openid email profile | Full list of scopes to send with the request (space delimited) |
| Signing Algorithm | string | RS256 | The algorithm used to sign the id token (examples: RS256, HS256) |
| Storage Label Claim | string | preferred_username | Claim mapping for the user's storage label**¹** |
| Role Claim | string | immich_role | Claim mapping for the user's role. (should return "user" or "admin")**¹** |
| Storage Quota Claim | string | immich_quota | Claim mapping for the user's storage**¹** |
| Default Storage Quota (GiB) | number | 0 | Default quota for user without storage quota claim (Enter 0 for unlimited quota) |
| Default Storage Quota (GiB) | number | 0 | Default quota for user without storage quota claim (empty for unlimited quota) |
| Button Text | string | Login with OAuth | Text for the OAuth button on the web |
| Auto Register | boolean | true | When true, will automatically register a user the first time they sign in |
| [Auto Launch](#auto-launch) | boolean | false | When true, will skip the login page and automatically start the OAuth login process |
@@ -93,6 +88,7 @@ The `.well-known/openid-configuration` part of the url is optional and will be a
## Auto Launch
When Auto Launch is enabled, the login page will automatically redirect the user to the OAuth authorization url, to login with OAuth. To access the login screen again, use the browser's back button, or navigate directly to `/auth/login?autoLaunch=0`.
Auto Launch can also be enabled on a per-request basis by navigating to `/auth/login?authLaunch=1`, this can be useful in situations where Immich is called from e.g. Nextcloud using the _External sites_ app and the _oidc_ app so as to enable users to directly interact with a logged-in instance of Immich.
## Mobile Redirect URI
@@ -110,6 +106,89 @@ Immich has a route (`/api/oauth/mobile-redirect`) that is already configured to
## Example Configuration
<details>
<summary>Authelia Example</summary>
### Authelia Example
Here's an example of OAuth configured for Authelia:
This assumes there exist an attribute `immichquota` in the user schema, which is used to set the user's storage quota in Immich.
The configuration concerning the quota is optional.
```yaml
authentication_backend:
ldap:
# The LDAP server configuration goes here.
# See: https://www.authelia.com/c/ldap
attributes:
extra:
immichquota:# The attribute name from LDAP
name:'immich_quota'
multi_valued:false
value_type:'integer'
identity_providers:
oidc:
## The other portions of the mandatory OpenID Connect 1.0 configuration go here.
When installing a new version of VectorChord, you will need to manually update the extension by connecting to the Immich database and running `ALTER EXTENSION vchord UPDATE;`.
When installing a new version of VectorChord, you will need to manually update the extension and reindex by connecting to the Immich database and running:
```
ALTER EXTENSION vchord UPDATE;
REINDEX INDEX face_index;
REINDEX INDEX clip_index;
```
## Migrating to VectorChord
@@ -76,6 +82,8 @@ Support for pgvecto.rs will be dropped in a later release, hence we recommend al
The easiest option is to have both extensions installed during the migration:
<details>
<summary>Migration steps (automatic)</summary>
1. Ensure you still have pgvecto.rs installed
2. Install `pgvector` (`>= 0.7.0, < 1.0.0`). The easiest way to do this is on Debian/Ubuntu by adding the [PostgreSQL Apt repository][pg-apt] and then running `apt install postgresql-NN-pgvector`, where `NN` is your Postgres version (e.g., `16`)
3. [Install VectorChord][vchord-install]
@@ -89,8 +97,12 @@ The easiest option is to have both extensions installed during the migration:
11. Restart the Postgres database
12. Uninstall pgvecto.rs (e.g. `apt-get purge vectors-pg14` on Debian-based environments, replacing `pg14` as appropriate). `pgvector` must remain installed as it provides the data types used by `vchord`
</details>
If it is not possible to have both VectorChord and pgvecto.rs installed at the same time, you can perform the migration with more manual steps:
<details>
<summary>Migration steps (manual)</summary>
1. While pgvecto.rs is still installed, run the following SQL command using psql or your choice of database client. Take note of the number outputted by this command as you will need it later
```sql
@@ -123,14 +135,20 @@ ALTER TABLE face_search ALTER COLUMN embedding SET DATA TYPE vector(512);
5. Start Immich and let it create new indices using VectorChord
</details>
### Migrating from pgvector
<details>
<summary>Migration steps</summary>
1. Ensure you have at least 0.7.0 of pgvector installed. If it is below that, please upgrade it and run the SQL command `ALTER EXTENSION vector UPDATE;` using psql or your choice of database client
2. Follow the Prerequisites to install VectorChord
3. If Immich does not have superuser permissions, run the SQL command `CREATE EXTENSION vchord CASCADE;`
4. Remove the `DB_VECTOR_EXTENSION=pgvector` environmental variable as it will make Immich still use pgvector if set
5. Start Immich and let it create new indices using VectorChord
</details>
Note that VectorChord itself uses pgvector types, so you should not uninstall pgvector after following these steps.
Users can deploy a custom reverse proxy that forwards requests to Immich. This way, the reverse proxy can handle TLS termination, load balancing, or other advanced features. All reverse proxies between Immich and the user must forward all headers and set the `Host`, `X-Real-IP`, `X-Forwarded-Proto` and `X-Forwarded-For` headers to their appropriate values. Additionally, your reverse proxy should allow for big enough uploads. By following these practices, you ensure that all custom reverse proxies are fully compatible with Immich.
:::note
The Repair page can take a long time to load. To avoid server timeouts or errors, we recommend specifying a timeout of at least 10 minutes on your proxy server.
:::
:::caution
Immich does not support being served on a sub-path such as `location /immich {`. It has to be served on the root path of a (sub)domain.
Dev Containers provide a consistent, reproducible development environment using Docker containers. With a single click, you can get started with an Immich development environment on Mac, Linux, Windows, or in the cloud using GitHub Codespaces.
Get started fast!
[](https://codespaces.new/immich-app/immich/)
[Learn more about Dev Containers](https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/adding-a-dev-container-configuration/introduction-to-dev-containers)
| Server & Web | `immich-server` | Runs both API server and web frontend in development mode | 2283 (API)<br/>3000 (Web)<br/>9230 (Workers Debug)<br/>9231 (API Debug) |
The immich dev containers read environment variables from your shell environment, not from `.env` files. This allows them to work in cloud environments without pre-configuration.
:::important Configuration
When running locally, and if you want to create (or use an existing) DB and/or photo storage folder, you must set the `UPLOAD_LOCATION` variable in your shell environment before launching the Dev Container. This determines where uploaded files are stored and also where the DB stores it data.
Immich development makes extensive use of specialized [base images](https://github.com/immich-app/base-images) for its docker-compose based development. For this reason, you won't be able to use VSCode's **_Clone Repository in a Container Volume_** command.
:::
#### Using VS Code UI:
1. Open the cloned repository in VS Code
2. Press `F1` or `Ctrl/Cmd+Shift+P` to open the command palette
3. Type and select "Dev Containers: Rebuild and Reopen in Container"
4. Select "Immich - Backend, Frontend and ML" from the list
5. Wait for the container to build and start (this may take several minutes on first run)
#### Using VS Code Quick Actions:
1. Open the repository in VS Code
2. You should see a popup asking if you want to reopen in a container
3. Click "Reopen in Container"
#### Using Command Line:
```bash
# Using the DevContainer CLI
devcontainer up --workspace-folder .
```
## Environment Variable Details
### How Dev Containers Handle Environment Variables
Unlike the Immich developer setup based on Docker Compose which uses `.env` files, Immich Dev Containers read environment variables from your shell environment. This is configured in `.devcontainer/devcontainer.json`:
Add these to your shell profile (`~/.bashrc`, `~/.zshrc`, `~/.bash_profile`, etc.):
```bash
# Required
exportUPLOAD_LOCATION=./Library # or absolute path
# Optional (only if using non-default values)
exportDB_PASSWORD=your_password
exportDB_USERNAME=your_username
exportDB_DATABASE_NAME=your_database
```
Remember to reload your shell configuration:
```bash
source ~/.bashrc # or ~/.zshrc, etc.
```
## Git Configuration
### SSH Keys and Authentication
To use your SSH keys for GitHub access inside the Dev Container:
1.**Start SSH Agent** on your host machine:
```bash
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa # or your key path
```
2. **VS Code automatically forwards your SSH agent** to the container
For detailed instructions, see the [VS Code guide on sharing Git credentials](https://code.visualstudio.com/remote/advancedcontainers/sharing-git-credentials).
### Commit Signing
To use your SSH key for commit signing, see the [GitHub guide on SSH commit signing](https://docs.github.com/en/authentication/managing-commit-signature-verification/telling-git-about-your-signing-key#telling-git-about-your-ssh-key).
@@ -38,6 +38,19 @@ Run all server checks with `npm run check:all`
You can use `npm run __:fix` to potentially correct some issues automatically for `npm run format` and `lint`.
:::
## Mobile Checks
The following commands must be executed from within the mobile app directory of the codebase.
- [ ]`make build` (auto-generate files using build_runner)
- [ ]`make analyze` (static analysis via Dart Analyzer and DCM)
- [ ]`make format` (formatting via Dart Formatter)
- [ ]`make test` (unit tests)
:::info Auto Fix
You can use `dart fix --apply` and `dcm fix lib` to potentially correct some issues automatically for `make analyze`.
:::
## OpenAPI
The OpenAPI client libraries need to be regenerated whenever there are changes to the `immich-openapi-specs.json` file. Note that you should not modify this file directly as it is auto-generated. See [OpenAPI](/docs/developer/open-api.md) for more details.
Folder view provides an additional view besides the timeline that is similar to a file explorer. It allows you to navigate through the folders and files in the library. This feature is handy for a highly curated and customized external library or a nicely configured storage template.
You can enable this feature under [`Account Settings > Features > Folder View`](https://my.immich.app/user-settings?isOpen=feature+folders)
You can enable this feature under [`Account Settings > Features > Folders`](https://my.immich.app/user-settings?isOpen=feature+folders)
@@ -56,9 +56,9 @@ Internally, Immich uses the [glob](https://www.npmjs.com/package/glob) package t
### Automatic watching (EXPERIMENTAL)
This feature - currently hidden in the config file - is considered experimental and for advanced users only. If enabled, it will allow automatic watching of the filesystem which means new assets are automatically imported to Immich without needing to rescan.
This feature is considered experimental and for advanced users only. If enabled, it will allow automatic watching of the filesystem which means new assets are automatically imported to Immich without needing to rescan.
If your photos are on a network drive, automatic file watching likely won't work. In that case, you will have to rely on a periodic library refresh to pull in your changes.
If your photos are on a network drive, automatic file watching likely won't work. In that case, you will have to rely on a [periodic library refresh](#set-custom-scan-interval) to pull in your changes.
#### Troubleshooting
@@ -72,7 +72,9 @@ In rare cases, the library watcher can hang, preventing Immich from starting up.
### Nightly job
There is an automatic scan job that is scheduled to run once a day. This job also cleans up any libraries stuck in deletion. It is possible to trigger the cleanup by clicking "Scan all libraries" in the library management page.
There is an automatic scan job that is scheduled to run once a day. Its schedule is configurable, see [Set Custom Scan Interval](#set-custom-scan-interval).
This job also cleans up any libraries stuck in deletion. It is possible to trigger the cleanup by clicking "Scan all libraries" in the library management page.
## Usage
@@ -91,7 +93,7 @@ The `immich-server` container will need access to the gallery. Modify your docke
@@ -112,12 +114,15 @@ _Remember to run `docker compose up -d` to register the changes. Make sure you c
These actions must be performed by the Immich administrator.
- Click on Administration -> Libraries
- Click on Create External Library
- Click on your avatar in the upper right corner
- Click on Administration -> External Libraries
- Click on Create an external library…
- Select which user owns the library, this can not be changed later
- Enter `/mnt/media/christmas-trip` then click Add
- Click on Save
- Click the drop-down menu on the newly created library
- Click on Scan
- Click the drop-down menu on the newly created library
- Click on Rename Library and rename it to "Christmas Trip"
NOTE: We have to use the `/mnt/media/christmas-trip` path and not the `/mnt/nas/christmas-trip` path since all paths have to be what the Docker containers see.
@@ -156,9 +161,7 @@ Within seconds, the assets from the old-pics and videos folders should show up i
Folder view provides an additional view besides the timeline that is similar to a file explorer. It allows you to navigate through the folders and files in the library. This feature is handy for a highly curated and customized external library or a nicely configured storage template.
You can enable this feature under [`Account Settings > Features > Folder View`](https://my.immich.app/user-settings?isOpen=feature+folders)
The UI is currently only available for the web; mobile will come in a subsequent release.
You can enable this feature under [`Account Settings > Features > Folders`](https://my.immich.app/user-settings?isOpen=feature+folders)
@@ -88,9 +88,9 @@ It will only reflect files you add.
:::
If the same asset is in more than one album it will only sync to the first album it's in, after that it won't sync again even if the user clicks sync albums manually.
To overcome this limitation, the files must be removed from the blacklist by
To overcome this limitation, the files must be removed from the ignore list by
Cleaning duplicate assets from the list will cause all the previously uploaded duplicate files to be re-uploaded, the files will not actually be uploaded and will be rejected on the server side (due to duplication) but will be synchronized to the album and at the end will be added to the black list again at the end of the synchronization.
Cleaning duplicate assets from the list will cause all the previously uploaded duplicate files to be re-uploaded, the files will not actually be uploaded and will be rejected on the server side (due to duplication) but will be synchronized to the album and at the end will be added to the ignore list again at the end of the synchronization.
Because of the underlying properties of docker bind mounts, it is not recommended to mount the `upload/` and `library/` folders as separate bind mounts if they are on the same device.
For this reason, we mount the HDD or the network storage (NAS) to `/usr/src/app/upload` and then mount the folders we want to access under that folder.
For this reason, we mount the HDD or the network storage (NAS) to `/data` and then mount the folders we want to access under that folder.
The `thumbs/` folder contains both the small thumbnails displayed in the timeline and the larger previews shown when clicking into an image. These cannot be separated.
# For deduplicating backup programs such as Borg or Restic, compressing the content can increase backup size by making it harder to deduplicate. If you are using a different program or still prefer to compress, you can use the following command instead:
| `IMMICH_MEDIA_LOCATION` | Media location inside the container ⚠️**You probably shouldn't set this**<sup>\*2</sup>⚠️ | `./upload`<sup>\*3</sup> | server | api, microservices |
| `IMMICH_MEDIA_LOCATION` | Media location inside the container ⚠️**You probably shouldn't set this**<sup>\*2</sup>⚠️ | `/data` | server | api, microservices |
| `IMMICH_CONFIG_FILE` | Path to config file | | server | api, microservices |
| `NO_COLOR` | Set to `true` to disable color-coded log output | `false` | server, machine learning | |
| `CPU_CORES` | Number of cores available to the Immich server | auto-detected CPU core count | server | |
@@ -49,9 +49,6 @@ These environment variables are used by the `docker-compose.yml` file and do **N
\*2: This path is where the Immich code looks for the files, which is internal to the docker container. Setting it to a path on your host will certainly break things, you should use the `UPLOAD_LOCATION` variable instead.
\*3: With the default `WORKDIR` of `/usr/src/app`, this path will resolve to `/usr/src/app/upload`.
It only needs to be set if the Immich deployment method is changing.
## Workers
| Variable | Description | Default | Containers |
@@ -72,22 +69,25 @@ Information on the current workers can be found [here](/docs/administration/jobs
| `DB_VECTOR_EXTENSION`<sup>\*2</sup> | Database vector extension (one of [`vectorchord`, `pgvector`, `pgvecto.rs`]) | | server |
| `DB_SKIP_MIGRATIONS` | Whether to skip running migrations on startup (one of [`true`, `false`]) | `false` | server |
| `DB_STORAGE_TYPE` | Optimize concurrent IO on SSDs or sequential IO on HDDs ([`SSD`, `HDD`])<sup>\*3</sup> | `SSD` | server |
\*1: The values of `DB_USERNAME`, `DB_PASSWORD`, and `DB_DATABASE_NAME` are passed to the Postgres container as the variables `POSTGRES_USER`, `POSTGRES_PASSWORD`, and `POSTGRES_DB` in `docker-compose.yml`.
\*2: If not provided, the appropriate extension to use is auto-detected at startup by introspecting the database. When multiple extensions are installed, the order of preference is VectorChord, pgvecto.rs, pgvector.
\*3: Uses either [`postgresql.ssd.conf`](https://github.com/immich-app/base-images/blob/main/postgres/postgresql.ssd.conf) or [`postgresql.hdd.conf`](https://github.com/immich-app/base-images/blob/main/postgres/postgresql.hdd.conf) which mainly controls the Postgres `effective_io_concurrency` setting to allow for concurrenct IO on SSDs and sequential IO on HDDs.
:::info
All `DB_` variables must be provided to all Immich workers, including `api` and `microservices`.
@@ -199,12 +199,11 @@ Additional machine learning parameters can be tuned from the admin UI.
| `IMMICH_TELEMETRY_INCLUDE` | Collect these telemetries. List of `host`, `api`, `io`, `repo`, `job`. Note: You can also specify `all` to enable all | | server | api, microservices |
| `IMMICH_TELEMETRY_EXCLUDE` | Do not collect these telemetries. List of `host`, `api`, `io`, `repo`, `job` | | server | api, microservices |
## Docker Secrets
## Secrets
The following variables support the use of [Docker secrets][docker-secrets] for additional security.
The following variables support reading from files, either via [Systemd Credentials][systemd-creds] or [Docker secrets][docker-secrets] for additional security.
To use any of these, replace the regular environment variable with the equivalent `_FILE` environment variable. The value of
the `_FILE` variable should be set to the path of a file containing the variable value.
To use any of these, either set `CREDENTIALS_DIRECTORY` to a directory that contains files whose name is the “regular variable” name, and whose content is the secret. If using Docker Secrets, setting `CREDENTIALS_DIRECTORY=/run/secrets` will cause all secrets present to be used. Alternatively, replace the regular variable with the equivalent `_FILE` environment variable as below. The value of the `_FILE` variable should be set to the path of a file containing the variable value.
@@ -25,7 +25,7 @@ When you're all done, you should have the following:
-`./docker/immich-app/postgres`
-`./docker/immich-app/library`
Download [`docker-compose.yml`](https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml) and [`example.env`](https://github.com/immich-app/immich/releases/latest/download/example.env) to your computer. Upload the files to the `./docker/immich-app` directory.
Download [`docker-compose.yml`](https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml) and [`example.env`](https://github.com/immich-app/immich/releases/latest/download/example.env) to your computer. Upload the files to the `./docker/immich-app` directory, and rename `example.env` to `.env`.
## Step 2 - Populate the .env file with custom values
@@ -9,211 +12,324 @@ This is a community contribution and not officially supported by the Immich team
Community support can be found in the dedicated channel on the [Discord Server](https://discord.immich.app/).
**Please report app issues to the corresponding [Github Repository](https://github.com/truenas/charts/tree/master/community/immich).**
**Please report app issues to the corresponding [GitHub Repository](https://github.com/truenas/apps/tree/master/trains/community/immich).**
:::
:::warning
This guide covers the installation of Immich on TrueNAS Community Edition 24.10.2.2 (Electric Eel) and later.
We recommend keeping TrueNAS Community Edition and Immich relatively up to date with the latest versions to avoid any issues.
If you are using an older version of TrueNAS, we ask that you upgrade to the latest version before installing Immich. Check the [TrueNAS Community Edition Release Notes](https://www.truenas.com/docs/softwarereleases/) for more information on breaking changes, new features, and how to upgrade your system.
:::
Immich can easily be installed on TrueNAS Community Edition via the **Community** train application.
Consider reviewing the TrueNAS [Apps resources](https://apps.truenas.com/getting-started/) if you have not previously configured applications on your system.
TrueNAS Community Edition makes installing and updating Immich easy, but you must use the Immich web portal and mobile app to configure accounts and access libraries.
## First Steps
The Immich app in TrueNAS Community Edition installs, completes the initial configuration, then starts the Immich web portal.
When updates become available, TrueNAS alerts and provides easy updates.
Before installing the Immich app in TrueNAS, review the [Environment Variables](#environment-variables) documentation to see if you want to configure any during installation.
You may also configure environment variables at any time after deploying the application.
### Setting up Storage Datasets
Before beginning app installation, [create the datasets](https://www.truenas.com/docs/scale/scaletutorials/storage/datasets/datasetsscale/) to use in the **Storage Configuration** section during installation.
You can organize these as one parent with seven child datasets, for example `/mnt/tank/immich/library`, `/mnt/tank/immich/upload`, and so on.
In TrueNAS, Immich requires 2 datasets for the application to function correctly: `data` and `pgData`. You can set the datasets to any names to match your naming conventions or preferences.
You can organize these as one parent with two child datasets, for example `/mnt/tank/immich/data` and `/mnt/tank/immich/pgData`.
The **pgData** dataset must be owned by the user `netdata` (UID 999) for postgres to start. The other datasets must be owned by the user `root` (UID 0) or a group that includes the user `root` (UID 0) for immich to have the necessary permissions.
:::info Datasets Permissions
If the **library** dataset uses ACL it must have [ACL mode](https://www.truenas.com/docs/core/coretutorials/storage/pools/permissions/#access-control-lists) set to `Passthrough` if you plan on using a [storage template](/docs/administration/storage-template.mdx) and the dataset is configured for network sharing (its ACL type is set to `SMB/NFSv4`). When the template is applied and files need to be moved from **upload** to **library**, Immich performs `chmod` internally and needs to be allowed to execute the command. [More info.](https://github.com/immich-app/immich/pull/13017)
The **pgData** dataset must be owned by the user `netdata` (UID 999) for Postgres to start.
The `data` dataset must have given the **_modify_** permission to the user who will run Immich.
Since TrueNAS Community Edition 24.10.2.2 and later, Immich can be run as any user and group, the default user being `apps` (UID 568) and the default group being `apps` (GID 568). This user, either `apps` or another user you choose, must have **_modify_** permissions on the **data** dataset.
For an easy setup:
- Create the parent dataset `immich` keeping the default **Generic** preset.
- Select `Dataset Preset`**Apps** instead of **Generic** when creating the `data` dataset. This will automatically give the correct permissions to the dataset. If you want to use another user for Immich, you can keep the **Generic** preset, but you will need to give the **_modify_** permission to that other user.
- For the `pgData` dataset, you can keep the default preset **Generic** as permissions can be set during the installation of the Immich app (See [Storage Configuration](#storage-configuration) section).
:::
:::tip
To improve performance, Immich recommends using SSDs for the database. If you have a pool made of SSDs, you can create the `pgData` dataset on that pool.
Thumbnails can also be stored on the SSDs for faster access. This is an advanced option and not required for Immich to run. More information on how you can use multiple datasets to manage Immich storage in a finer-grained manner can be found in the [Advanced: Multiple Datasets for Immich Storage](#advanced-multiple-datasets-for-immich-storage) section below.
:::
:::warning
If you just created the datasets using the **Apps** preset, you can skip this warning section.
If the **data** dataset uses ACL it must have [ACL mode](https://www.truenas.com/docs/scale/scaletutorials/datasets/permissionsscale/) set to `Passthrough` if you plan on using a [storage template](/docs/administration/storage-template.mdx) and the dataset is configured for network sharing (its ACL type is set to `SMB/NFSv4`). When the template is applied and files need to be moved from **upload** to **library** (internal folder created by Immich within the **data** dataset), Immich performs `chmod` internally and must be allowed to execute the command. [More info.](https://github.com/immich-app/immich/pull/13017)
To change or verify the ACL mode, go to the **Datasets** screen, select the **library** dataset, click on the **Edit** button next to **Dataset Details**, then click on the **Advanced Options** tab, scroll down to the **ACL Mode** section, and select `Passthrough` from the dropdown menu. Click **Save** to apply the changes. If the option is greyed out, set the **ACL Type** to `SMB/NFSv4` first, then you can change the **ACL Mode** to `Passthrough`.
:::
## Installing the Immich Application
To install the **Immich** application, go to **Apps**, click **Discover Apps**, either begin typing Immich into the search field or scroll down to locate the **Immich** application widget.
To install the **Immich** application, go to **Apps**, click **Discover Apps**, and either begin typing Immich into the search field or scroll down to locate the **Immich** application widget.
Click **Install** to open the Immich application configuration screen.
<br/><br/>
</div>
Application configuration settings are presented in several sections, each explained below.
To find specific fields click in the **Search Input Fields** search field, scroll down to a particular section or click on the section heading on the navigation area in the upper-right corner.
To find specific fields, click in the **Search Input Fields** search field, scroll down to a particular section, or click on the section heading on the navigation area in the upper-right corner.
The **Timezone** is set to the system default, which usually matches your local timezone. You can change it to another timezone if you prefer.
**Enable Machine Learning** is enabled by default. It allows Immich to use machine learning features such as face recognition, image search, and smart duplicate detection. Untick this option if you do not want to use these features.
Select the **Machine Learning Image Type** based on the hardware you have. More details here: [Hardware-Accelerated Machine Learning](/docs/features/ml-hardware-acceleration.md)
**Database Password** should be set to a custom value using only the characters `A-Za-z0-9`. This password is used to secure the Postgres database.
**Redis Password** should be set to a custom value using only the characters `A-Za-z0-9`. Preferably, use a different password from the database password.
Keep the **Log Level** to the default `Log` value.
Leave **Hugging Face Endpoint** blank. (This is used to download ML models from a different source.)
Set **Database Storage Type** to the type of storage (**HDD** or **SSD**) that the pool where the **pgData** dataset is located uses.
**Additional Environment Variables** can be left blank.
Accept the default value in **Timezone** or change to match your local timezone.
**Timezone** is only used by the Immich `exiftool` microservice if it cannot be determined from the image metadata.
These are used to add custom configuration options or to enable specific features.
More information on available environment variables can be found in the **[environment variables documentation](/docs/install/environment-variables/)**.
Untick **Enable Machine Learning** if you will not use face recognition, image search, and smart duplicate detection.
:::info
Some environment variables are not available for the TrueNAS Community Edition app as they can be configured through GUI options in the [Edit Immich screen](#edit-app-settings).
Accept the default option or select the **Machine Learning Image Type** for your hardware based on the [Hardware-Accelerated Machine Learning Supported Backends](/docs/features/ml-hardware-acceleration.md#supported-backends).
Some examples are: `IMMICH_VERSION`, `UPLOAD_LOCATION`, `DB_DATA_LOCATION`, `TZ`, `IMMICH_LOG_LEVEL`, `DB_PASSWORD`, `REDIS_PASSWORD`.
:::
Immich's default is `postgres` but you should consider setting the **Database Password** to a custom value using only the characters `A-Za-z0-9`.
</details>
The **Redis Password** should be set to a custom value using only the characters `A-Za-z0-9`.
### User and Group Configuration
Accept the **Log Level** default of **Log**.
Application in TrueNAS runs as a specific user and group. Immich uses the default user `apps` (UID 568) and the default group `apps` (GID 568).
Leave **Hugging Face Endpoint** blank. (This is for downloading ML models from a different source.)
Leave **Additional Environment Variables** blank or see [Environment Variables](#environment-variables) to set before installing.
- **User ID**: Keep the default value `apps` (UID 568) or define a different one if needed.
- **Group ID**: Keep the default value `apps` (GID 568) or define a different one if needed.
:::warning
If you change the user or group, make sure that the datasets you created for Immich data storage have the correct permissions set for that user and group as specified in the [Setting up Storage Datasets](#setting-up-storage-datasets) section above.
Accept the default port `30041` in **WebUI Port**or enter a custom port number.
:::info Allowed Port Numbers
Only numbers within the range 9000-65535 may be used on TrueNAS versions below TrueNAS Community Edition 24.10 Electric Eel.
- **Port Bind Mode**: This lets you expose the port to the host system, allowing you to access Immich from outside the TrueNAS system. Keep the default **_Publish port on the host for external access_** value unless you have a specific reason to change it.
Regardless of version, to avoid port conflicts, don't use [ports on this list](https://www.truenas.com/docs/solutions/optimizations/security/#truenas-default-ports).
:::
- **Port Number**: Keep the default port `30041` or enter a custom port number.
- **Host IPs**: Leave the default blank value.
### Storage Configuration
Immich requires seven storage datasets.
<img
src={require('./img/truenas07.webp').default}
width="20%"
alt="Configure Storage ixVolumes"
className="border rounded-xl"
/>
:::note Default Setting (Not recommended)
The default setting for datasets is **ixVolume (dataset created automatically by the system)** but this results in your data being harder to access manually and can result in data loss if you delete the immich app. (Not recommended)
:::danger Default Settings (Not recommended)
The default setting for datasets is **ixVolume (dataset created automatically by the system)**. This is not recommended as this results in your data being harder to access manually and can result in data loss if you delete the immich app. It is also harder to manage snapshots and replication tasks. It is recommended to use the **Host Path (Path that already exists on the system)** option instead.
:::
For each Storage option select **Host Path (Path that already exists on the system)** and then select the matching dataset [created before installing the app](#setting-up-storage-datasets): **Immich Library Storage**: `library`, **Immich Uploads Storage**: `upload`, **Immich Thumbs Storage**: `thumbs`, **Immich Profile Storage**: `profile`, **Immich Video Storage**: `video`, **Immich Backups Storage**: `backups`, **Postgres Data Storage**: `pgData`.
The storage configuration section allows you to set up the storage locations for Immich data. You can select the datasets created in the previous step.
For the Data Storage, select **Host Path (Path that already exists on the system)** and then select the dataset you created for Immich data storage, for example, `data`.
The Machine Learning cache can be left with default _Temporary_
For the Postgres Data Storage, select **Host Path (Path that already exists on the system)** and then select the dataset you created for Postgres data storage, for example, `pgData`.
:::info
**Postgres Data Storage**
Once **Host Path** is selected, a checkbox appears with **_Automatic Permissions_**. If you have not set the ownership of the **pgData** dataset to `netdata` (UID 999), tick this box as it will set the user ownership to `netdata` (UID 999) and the group ownership to `docker` (GID 999) automatically. If you have set the ownership of the **pgData** dataset to `netdata` (UID 999), you can leave this box unticked.
:::
### Additional Storage (Advanced Users)
<details>
<summary>External Libraries</summary>
:::danger Advanced Users Only
This feature should only be used by advanced users. If this is your first time installing Immich, then DO NOT mount an external library until you have a working setup. Also, your mount path MUST be something unique and should NOT be your library or upload location or a Linux directory like `/lib`. The picture below shows a valid example.
This feature should only be used by advanced users. If this is your first time installing Immich, then DO NOT mount an external library until you have a working setup.
alt="Add External Libraries with Additional Storage"
className="border rounded-xl"
/>
You may configure [External Libraries](/docs/features/libraries) by mounting them using **Additional Storage**.
The **Mount Path** is the location you will need to copy and paste into the External Library settings within Immich.
The **Host Path** is the location on the TrueNAS Community Edition server where your external library is located.
You may configure [external libraries](/docs/features/libraries) by mounting them using **Additional Storage**.
<!-- A section for Labels would go here but I don't know what they do. -->
The dataset that contains your external library files must at least give **read** access to the user running Immich (Default: `apps` (UID 568), `apps` (GID 568)).
If you want to be able to delete files or edit metadata in the external library using Immich, you will need to give the **modify** permission to the user running Immich.
- **Mount Path** is the location you will need to copy and paste into the external library settings within Immich.
- **Host Path** is the location on the TrueNAS Community Edition server where your external library is located.
- **Read Only** is a checkbox that you can tick if you want to prevent Immich from modifying the files in the external library. This is useful if you want to use Immich to view and search your external library without modifying it.
:::warning
Each mount path MUST be something unique and should NOT be your library or upload location or a Linux directory like `/lib`.
A general recommendation is to mount any external libraries to a path beginning with `/mnt` or `/media` followed by a unique name, such as `/mnt/external-libraries` or `/media/my-external-libraries`. If you plan to mount multiple external libraries, you can use paths like `/mnt/external-libraries/library1`, `/mnt/external-libraries/library2`, etc.
:::
</details>
<details>
<summary>Multiple Datasets for Immich Storage</summary>
:::danger Advanced Users Only
This feature should only be used by advanced users.
:::
Immich can use multiple datasets for its storage, allowing you to manage your data more granularly, similar to the old storage configuration. This is useful if you want to separate your data into different datasets for performance or organizational reasons. There is a general guide for this [here](/docs/guides/custom-locations), but read on for the TrueNAS guide.
Each additional dataset has to give the permission **_modify_** to the user who will run Immich (Default: `apps` (UID 568), `apps` (GID 568))
As described in the [Setting up Storage Datasets](#setting-up-storage-datasets) section above, you have to create the datasets with the **Apps** preset to ensure the correct permissions are set, or you can set the permissions manually after creating the datasets.
Immich uses 6 folders for its storage: `library`, `upload`, `thumbs`, `profile`, `encoded-video`, and `backups`. You can create a dataset for each of these folders or only for some of them.
To mount these datasets:
1. Add an **Additional Storage** entry for each dataset you want to use.
2. Select **Type** as **Host Path (Path that already exists on the system)**.
3. Enter the **Mount Path** with `/data/<folder-name>`. The `<folder-name>` is the name of the folder you want to mount, for example, `library`, `upload`, `thumbs`, `profile`, `encoded-video`, or `backups`.
:::danger Important
You have to write the full path, including `/data/`, as Immich expects the data to be in that location.
If you do not include this path, Immich will not be able to find the data and will not write the data to the location you specified.
:::
4. Select the **Host Path** as the dataset you created for that folder, for example, `/mnt/tank/immich/library`, `/mnt/tank/immich/upload`, etc.
Accept the default **CPU** limit of `2` threads or specify the number of threads (CPUs with Multi-/Hyper-threading have 2 threads per core).
- **CPU**: Depending on your system resources, you can keep the default value of `2` threads or specify a different number. Immich recommends at least `8` threads.
Specify the **Memory** limit in MB of RAM. Immich recommends at least 6000 MB (6GB). If you selected **Enable Machine Learning** in **Immich Configuration**, you should probably set this above 8000 MB.
-**Memory**: Limit in MB of RAM. Immich recommends at least 6000 MB (6GB). If you selected **Enable Machine Learning** in **Immich Configuration**, you should probably set this above 8000 MB.
:::info Older TrueNAS Versions
Before TrueNAS Community Edition version 24.10 Electric Eel:
Both **CPU** and **Memory** are limits, not reservations. This means that Immich can use up to the specified amount of CPU threads and RAM, but it will not reserve that amount of resources at all times. The system will allocate resources as needed, and Immich will use less than the specified amount most of the time.
The **CPU** value was specified in a different format with a default of `4000m` which is 4 threads.
- Enable **GPU Configuration** options if you have a GPU or CPU with integrated graphics that you will use for [Hardware Transcoding](/docs/features/hardware-transcoding) and/or [Hardware-Accelerated Machine Learning](/docs/features/ml-hardware-acceleration.md).
The **Memory** value was specified in a different format with a default of `8Gi` which is 8 GiB of RAM. The value was specified in bytes or a number with a measurement suffix. Examples: `129M`, `123Mi`, `1000000000`
:::
Enable **GPU Configuration** options if you have a GPU that you will use for [Hardware Transcoding](/docs/features/hardware-transcoding) and/or [Hardware-Accelerated Machine Learning](/docs/features/ml-hardware-acceleration.md). More info: [GPU Passthrough Docs for TrueNAS Apps](https://apps.truenas.com/managing-apps/installing-apps/#gpu-passthrough)
The process for NVIDIA GPU passthrough requires additional steps.
More details here: [GPU Passthrough Docs for TrueNAS Apps](https://apps.truenas.com/managing-apps/installing-apps/#gpu-passthrough)
### Install
Finally, click **Install**.
The system opens the **Installed Applications** screen with the Immich app in the **Deploying** state.
When the installation completes it changes to **Running**.
When the installation completes, it changes to **Running**.
Click **Web Portal** on the **Application Info** widget to open the Immich web interface to set up your account and begin uploading photos.
Click **Web Portal** on the **Application Info** widget, or go to the URL `http://<your-truenas-ip>:30041` in your web browser to open the Immich web interface. This will show you the onboarding process to set up your first user account, which will be an administrator account.
After that, you can start using Immich to upload and manage your photos and videos.
:::tip
For more information on how to use the application once installed, please refer to the [Post Install](/docs/install/post-install.mdx) guide.
@@ -228,23 +344,6 @@ For more information on how to use the application once installed, please refer
- Click **Update** at the very bottom of the page to save changes.
- TrueNAS automatically updates, recreates, and redeploys the Immich container with the updated settings.
## Environment Variables
You can set [Environment Variables](/docs/install/environment-variables) by clicking **Add** on the **Additional Environment Variables** option and filling in the **Name** and **Value**.
<img
src={require('./img/truenas11.webp').default}
width="40%"
alt="Environment Variables"
className="border rounded-xl"
/>
:::info
Some Environment Variables are not available for the TrueNAS Community Edition app. This is mainly because they can be configured through GUI options in the [Edit Immich screen](#edit-app-settings).
Some examples are: `IMMICH_VERSION`, `UPLOAD_LOCATION`, `DB_DATA_LOCATION`, `TZ`, `IMMICH_LOG_LEVEL`, `DB_PASSWORD`, `REDIS_PASSWORD`.
:::
## Updating the App
:::danger
@@ -261,3 +360,116 @@ To update the app to the latest version:
- You may view the Changelog.
- Click **Upgrade** to begin the process and open a counter dialog that shows the upgrade progress.
- When complete, the update badge and buttons disappear and the application Update state on the Installed screen changes from Update Available to Up to date.
## Migration
:::danger
Perform a backup of your Immich data before proceeding with the migration steps below. This is crucial to prevent any data loss if something goes wrong during the migration process.
The migration should also be performed when the Immich app is not running to ensure no data is being written while you are copying the data.
:::
### Migration from Old Storage Configuration
There are two ways to migrate from the old storage configuration to the new one, depending on whether you want to keep the old multiple datasets or if you want to move to a double dataset configuration with a single dataset for Immich data storage and a single dataset for Postgres data storage.
:::note Old TrueNAS Versions Permissions
If you were using an older version of TrueNAS (before 24.10.2.2), the datasets, except the one for **pgData** had only to be owned by the `root` user (UID 0). You might have to add the **modify** permission to the `apps` user (UID 568) or the user you want to run Immich as, to all of them, except **pgData**. The steps to add or change ACL permissions are described in the [TrueNAS documentation](https://www.truenas.com/docs/scale/scaletutorials/datasets/permissionsscale/).
:::
<Tabs groupId="truenas-migration-tabs">
<TabItem value="migrate-new-dataset" label="Migrate data to a new dataset (recommended)" default>
To migrate from the old storage configuration to the new one, you will need to create a new dataset for the Immich data storage and copy the data from the old datasets to the new ones. The steps are as follows:
1.**Stop the Immich app** from the TrueNAS web interface to ensure no data is being written while you are copying the data.
2.**Create a new dataset** for the Immich data storage, for example, `data`. As described in the [Setting up Storage Datasets](#setting-up-storage-datasets) section above, create the dataset with the **Apps** preset to ensure the correct permissions are set.
3.**Copy the data** from the old datasets to the new dataset. We advise using the `rsync` command to copy the data, as it will preserve the permissions and ownership of the files. The following commands are examples:
Make sure to replace `/mnt/tank/immich/` with the correct path to your old datasets and `/mnt/tank/immich/data/` with the correct path to your new dataset.
:::tip
If you were using **ixVolume (dataset created automatically by the system)** for Immich data storage, the path to the data should be `/mnt/.ix-apps/app_mounts/immich/`. You have to use this path instead of `/mnt/tank/immich/` in the `rsync` command above, for example:
If you were also using an ixVolume for Postgres data storage, you also should, first create the pgData dataset, as described in the [Setting up Storage Datasets](#setting-up-storage-datasets) section above, and then you can use the following command to copy the Postgres data:
Make sure that for each folder, the `.immich` file is copied as well, as it contains important metadata for Immich. If for some reason the `.immich` file is not copied, you can copy it manually with the `rsync` command, for example:
Replace `library` with the name of the folder where you are copying the file.
:::
4.**Update the permissions** as the permissions of the data that have been copied has been preserved, to ensure that the `apps` user (UID 568) has the correct permissions on all the copied data. If you just created the dataset with the **Apps** preset, from the TrueNAS web interface, go to the **Datasets** screen, select the **data** dataset, click on the **Edit** button next to **Permissions**, tick the "Apply permissions recursively" checkbox, and click **Save**. This will apply the correct permissions to all the copied data.
5.**Update the Immich app** to use the new dataset:
- Go to the **Installed Applications** screen and select Immich from the list of installed applications.
- Click **Edit** on the **Application Info** widget.
- In the **Storage Configuration** section, untick the **Use Old Storage Configuration (Deprecated)** checkbox.
- For the **Data Storage**, select **Host Path (Path that already exists on the system)** and then select the new dataset you created for Immich data storage, for example, `data`.
- For the **Postgres Data Storage**, verify that it is still set to the dataset you created for Postgres data storage, for example, `pgData`.
- Click **Update** at the bottom of the page to save changes.
6.**Start the Immich app** from the TrueNAS web interface.
This will recreate the Immich container with the new storage configuration and start the app.
If everything went well, you should now be able to access Immich with the new storage configuration. You can verify that the data has been copied correctly by checking the Immich web interface and ensuring that all your photos and videos are still available. You may delete the old datasets, if you no longer need them, using the TrueNAS web interface.
If you were using **ixVolume (dataset created automatically by the system)** or folders for Immich data storage, you can delete the old datasets using the following commands:
```bash
rm -r /mnt/.ix-apps/app_mounts/immich/library
rm -r /mnt/.ix-apps/app_mounts/immich/uploads
rm -r /mnt/.ix-apps/app_mounts/immich/thumbs
rm -r /mnt/.ix-apps/app_mounts/immich/profile
rm -r /mnt/.ix-apps/app_mounts/immich/video
rm -r /mnt/.ix-apps/app_mounts/immich/backups
```
</TabItem>
<TabItem value="migrate-old-dataset" label="Keep the existing datasets">
To migrate from the old storage configuration to the new one without creating new datasets.
1.**Stop the Immich app** from the TrueNAS web interface to ensure no data is being written while you are updating the app.
2.**Update the datasets permissions**: Ensure that the datasets used for Immich data storage (`library`, `upload`, `thumbs`, `profile`, `video`, `backups`) have the correct permissions set for the user who will run Immich. The user should have ***modify*** permissions on these datasets. The default user for Immich is `apps` (UID 568) and the default group is `apps` (GID 568). If you are using a different user, make sure to set the permissions accordingly. You can do this from the TrueNAS web interface by going to the **Datasets** screen, selecting each dataset, clicking on the **Edit** button next to **Permissions**, and adding the user with ***modify*** permissions.
3.**Update the Immich app** to use the existing datasets:
- Go to the **Installed Applications** screen and select Immich from the list of installed applications.
- Click **Edit** on the **Application Info** widget.
- In the **Storage Configuration** section, untick the **Use Old Storage Configuration (Deprecated)** checkbox.
- For the **Data Storage**, you can keep the **ixVolume (dataset created automatically by the system)** as no data will be directly written to it. We recommend selecting **Host Path (Path that already exists on the system)** and then select a **new** dataset you created for Immich data storage, for example, `data`.
- For the **Postgres Data Storage**, keep **Host Path (Path that already exists on the system)** and then select the existing dataset you used for Postgres data storage, for example, `pgData`.
- Following the instructions in the [Multiple Datasets for Immich Storage](#additional-storage-advanced-users) section, you can add, **for each old dataset**, a new Additional Storage with the following settings:
- **Type**: `Host Path (Path that already exists on the system)`
Make sure to replace `<folder-name>` with the actual name of the folder used by Immich: `library`, `upload`, `thumbs`, `profile`, `encoded-video`, and `backups`. Also, replace `<your-pool-name>` and `<dataset-name>` with the actual names of your pool and dataset.
:::
- **Read Only**: Keep it unticked as Immich needs to write to these datasets.
- Click **Update** at the bottom of the page to save changes.
4.**Start the Immich app** from the TrueNAS web interface. This will recreate the Immich container with the new storage configuration and start the app. If everything went well, you should now be able to access Immich with the new storage configuration. You can verify that the data is still available by checking the Immich web interface and ensuring that all your photos and videos are still accessible.
@@ -75,7 +75,6 @@ alt="Select Plugins > Compose.Manager > Add New Stack > Label it Immich"
5. Click "**Save Changes**", you will be prompted to edit stack UI labels, just leave this blank and click "**Ok**"
6. Select the cog ⚙️ next to Immich, click "**Edit Stack**", then click "**Env File**"
7. Paste the entire contents of the [Immich example.env](https://github.com/immich-app/immich/releases/latest/download/example.env) file into the Unraid editor, then **before saving** edit the following:
-`UPLOAD_LOCATION`: Create a folder in your Images Unraid share and place the **absolute** location here > For example my _"images"_ share has a folder within it called _"immich"_. If I browse to this directory in the terminal and type `pwd` the output is `/mnt/user/images/immich`. This is the exact value I need to enter as my `UPLOAD_LOCATION`
-`DB_DATA_LOCATION`: Change this to use an Unraid share (preferably a cache pool, e.g. `/mnt/user/appdata/postgresql/data`). This uses the `appdata` share. Do also create the `postgresql` folder, by running `mkdir /mnt/user/{share_location}/postgresql/data`. If left at default it will try to use Unraid's `/boot/config/plugins/compose.manager/projects/[stack_name]/postgres` folder which it doesn't have permissions to, resulting in this container continuously restarting.
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.