Immich 自架需要多少 RAM?安全升級與修復
Immich 官方最低需求為 6 GB RAM,並說明 port 2283 如何放在 HTTPS 後方、exit 137 記憶體終止原因,以及 Immich v3 無法啟動 pgvecto.rs 資料庫的還原步驟。
您要建置的內容
Immich 是一項自架的相片與影片備份服務,可真正取代 Google Photos。它提供手機應用程式,可在背景上傳相機膠卷,並具備時間軸、相簿、人臉辨識與機器學習搜尋功能。即使您從未建立任何標籤,也能搜尋「海灘」或特定人物。您可以在自己的 VPS 上執行 Immich,原始檔案會留在您的磁碟上,也不會有人掃描這些檔案來向您投放商品廣告。如果您仍在 Immich 與另一個明顯的候選方案之間評估,我們的 PhotoPrism 與 Immich 比較會並列比較兩者的最低 RAM 需求、手機應用程式與備份指令。
安裝內容是專案提供的 Docker Compose 檔案所定義的 4 個容器。這部分只需 10 分鐘。真正複雜的是後續工作:在小型主機上,機器學習容器會大量消耗記憶體;原始檔案會快速佔滿磁碟;行動應用程式需要完全正確的伺服器 URL;在服務離開您的網路前,您還需要在前方設定 HTTPS。此外,Immich 經常發布可能造成相容性問題的變更,粗心的 docker compose pull 可能讓伺服器無法啟動。請嚴格處理這 4 項問題,Immich 就能穩定執行。忽略這些問題,您可能會因此損失一個週末。
先決條件與必須注意的限制
- RAM:官方文件指出最低需要 6 GB,建議 8 GB;請將 4 GB 加上 swap 視為絕對下限。
immich-server和 Postgres 容器的資源需求不高。immich-machine-learning容器最耗用資源,會將 CLIP 與臉部辨識模型載入 RAM,以建立搜尋索引;在 2 GB 的主機上,kernel 會將其終止。即使只有 4 GB RAM,也請加入 swap。如果您打算以中文搜尋相片,預設的 CLIP 模型多半找不到「海邊」或「貓」這類查詢,改用多語模型時也需要重新估算記憶體;Immich 中文搜尋與 CLIP 模型指南會依官方中文基準比較各模型的記憶體與準確率,並說明如何開啟 OCR 搜尋相片中的繁體中文字。 - 磁碟:請按照完整資料庫,再預留一些空間。 原始檔案會完整複製,Immich 也會產生縮圖與預覽圖片,額外約占 10–20%。200 GB 的相片資料庫需要 300 GB 的 volume。相比之下,Postgres 占用空間很小。
- CPU:任何現代 KVM VPS 都可以,但在 CPU 上執行 ML 的速度很慢。 大量匯入資料的智慧搜尋索引可能會在背景執行數小時。這是正常現象,不需要 GPU。影片轉碼同樣由 CPU 負責:如果 iPhone 拍攝的 HEVC 影片在 Immich 上要等很久才開始播放,原因通常是 VPS 正在以軟體轉碼,而不是網路太慢;Immich 影片播放緩慢的轉碼設定與排查會比較各種轉碼政策的代價,並說明如何分辨線路與反向代理造成的問題。
- 指向 VPS 的網域名稱。 行動應用程式偏好使用 HTTPS endpoint,前方也需要配置反向代理。這與 使用 Docker、TLS 與備份自架 Nextcloud 的架構相同;Immich 是該檔案伺服器的相片版本。
- 已安裝 Docker 與 Compose plugin,也就是從 Docker 自己的 apt repository 安裝 Docker Engine 與 Compose v2 plugin,具體方式請參閱我們的 Docker Compose 基礎指南。
步驟 1:先新增 swap
在小型 VPS 上,Immich 最常見的故障是 ML 容器因 OOM 而遭到終止。先為 kernel 提供可用的緩衝空間。
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
free -hfree -h 現在應顯示一行 Swap:,其值為 4.0Gi。這不會讓 ML 執行得更快。它是緩衝機制,不是保證,但可大幅降低容器在 4 GB 機器上於索引過程中停止的機率。
步驟 2:下載官方 compose 與 env,使用官方檔案,不要使用副本
Immich 會在其釋出的檔案中固定服務版本,尤其是資料庫映像檔的版本。請勿將部落格中的 compose 檔案(包括本教學的檔案)直接貼上,作為唯一依據。請下載 release 資產:
sudo mkdir -p /opt/immich && cd /opt/immich
sudo wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
sudo wget -O .env https://github.com/immich-app/immich/releases/latest/download/example.env這些檔案來自標記的 release,因此映像檔參照會相互對應。compose 檔案定義了 4 個服務。在進行任何操作前,先了解各服務的用途:
immich-server(ghcr.io/immich-app/immich-server,容器immich_server)提供 API 與 Web UI,監聽連接埠2283。它會將您的上傳內容掛載至/data。immich-machine-learning(ghcr.io/immich-app/immich-machine-learning,容器immich_machine_learning)提供 CLIP 搜尋與臉部辨識功能。它會將下載的模型快取在model-cachevolume 中。這是最耗用記憶體的服務。database(容器immich_postgres)執行搭載 VectorChord 向量擴充功能的 Postgres,供相似度搜尋使用。映像檔標籤會直接在 compose 檔案中以 digest 固定,例如ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:...。較舊的設定使用pgvecto.rs;Immich v3.0 已移除對它的支援,因此目前安裝的版本都會使用 VectorChord。請勿手動修改此標籤。redis(容器immich_redis)執行 Valkey/Redis 執行個體,供工作佇列使用。
步驟 3:設定 .env,照片與資料庫儲存於此
開啟 .env 並設定以下 4 項。標記行以下的所有內容維持不變。
# Where original uploads are stored on the host
UPLOAD_LOCATION=/opt/immich/library
# Where the Postgres data lives. NEVER put this on an NFS/network share.
DB_DATA_LOCATION=/opt/immich/postgres
# "v3" is a floating tag that tracks the latest v3.x. Pin a full tag like
# v3.0.2 instead; then you upgrade on purpose, not by surprise.
IMMICH_VERSION=v3.0.2
# Change this to a long random string. Letters and digits only.
DB_PASSWORD=REPLACE_WITH_A_LONG_RANDOM_STRING
# Set your timezone so timestamps and "on this day" line up
TZ=Europe/London
###################################################################################
DB_USERNAME=postgres
DB_DATABASE_NAME=immich以下 2 項規則能避免許多問題。UPLOAD_LOCATION 應指向大型磁碟;如果之後會掛載資料磁碟區,請從一開始就將此值設為其掛載路徑,因為事後搬移不僅需要移動縮圖,還要更新資產路徑。DB_DATA_LOCATION 則必須位於本機磁碟:Postgres 在 NFS 或 SMB 共用上執行會造成資料損毀,文件也明確如此說明。DB_PASSWORD 僅使用英文字母與數字,可避免一類連線字串逸脫錯誤。
步驟 4:首次執行並建立管理員使用者
cd /opt/immich
sudo docker compose up -d
sudo docker compose ps正確結果應為 4 個容器,全部處於 running 狀態,之後最終都會變成 healthy:
NAME STATUS
immich_machine_learning Up (healthy)
immich_postgres Up (healthy)
immich_redis Up (healthy)
immich_server Up (healthy)第一次執行 up 時會下載數 GB 的映像檔,因此請耐心等候。使用 sudo docker compose logs -f immich-server 監看進度;伺服器就緒後,日誌會記錄其正在監聽連接埠 2283。現在在瀏覽器中開啟 http://YOUR_SERVER_IP:2283。首次造訪時會顯示 開始使用 精靈;建立的第一個帳戶就是管理員帳戶。請設定強密碼;此帳戶可管理伺服器設定、使用者管理,以及稍後會用到的 ML 設定。
步驟 5:行動應用程式與背景備份
從 App Store 或 Play Store 安裝「Immich」。在登入畫面中,系統會要求輸入 Server Endpoint URL。輸入包含 scheme 的完整 URL,例如 https://photos.example.com(應用程式會自行附加 /api)。使用剛建立的帳戶登入,然後開啟應用程式的 Backup 畫面,選取要保護的相簿(通常是 Camera 和 Screenshots),並啟用 Background backup。iOS 會限制背景備份的頻率;前景上傳一律會執行,背景上傳則會在作業系統允許時執行。
這正是許多人卡住的地方,因此請先閱讀步驟 6,再處理應用程式的問題。
步驟 6:透過反向代理提供 HTTPS,以及完整 URL 規則
行動應用程式離開家用網路後,通常需要使用 HTTPS。請在連接埠 2283 前方設定反向代理,並在代理端終止 TLS。若您已執行多個容器,使用自動 TLS 為多個 Docker 應用程式提供服務的 Traefik 是最整齊的選項。只要一個標籤區塊,就能將 photos.example.com 路由至 immich-server 容器,並代您取得憑證。若偏好 nginx,使用 Certbot 與 nginx 設定 Let's Encrypt 指南會協助您取得憑證與 proxy_pass http://127.0.0.1:2283; 區塊。建立代理後,新增下一項服務通常只需建立新的子網域。因此,像 Halcyon,Jellyfin 的 90 年代錄影帶出租店介面 這類媒體前端,就能與 Immich 共存於同一台主機。自行代管的 HarnessRouter,讓 Codex 與 Claude Code 共用單一 API 也是相同情況。它刻意繫結至 loopback,只有在代理於前方終止 TLS 後才可連線。因此,將子網域指向它之前,請先變更預設登入資訊。不過,並非每個容器都需要公開主機名稱。像 自行代管的 open-kritt 安全掃描器 這類僅供管理用途的工具,最好完全不要放在代理後方。只有偶爾開啟其 UI 時,再透過 SSH tunnel 存取即可。其他服務則完全不使用代理,因為它們根本不使用 HTTP。自行代管的 RustDesk relay server 就是最明顯的例子。它會監聽數個原始 TCP 與 UDP 連接埠,需要設定防火牆規則,而不是建立子網域。Immich 有一項代理設定需要注意:請提高上傳大小上限,因為手機影片通常很大。在 nginx 中,請在 server block 內設定 client_max_body_size 50000M;。預設的 1 MB 會以 413 Request Entity Too Large 拒絕影片上傳。如果您的代理也會回應 Let's Encrypt 的 HTTP-01 challenge,請確認 /.well-known/immich 仍然路由至 Immich,而不是 challenge handler。
應用程式強制執行的規則是:端點必須能以您輸入的完整 URL 存取。應用程式接受純 http://YOUR_SERVER_IP:2283(其登入提示為 http://your-server-ip:port),但任何會經過網際網路的連線都應使用 HTTPS。通訊協定錯誤,或直接使用未包含連接埠的 IP 位址,就會導致「應用程式無法連線至伺服器」。以下會以具名故障說明這種情況。
步驟 7:External libraries 與 uploads,匯入現有相片目錄
相片進入 Immich 有兩種方式,兩者並不相同。
- Uploads 是由 Immich 管理的資產。應用程式或網頁上傳器會將檔案複製到
UPLOAD_LOCATION。Immich 可以重新命名、移動及刪除這些檔案。 - External libraries 是唯讀匯入,來源是伺服器資料夾、舊有的
Pictures目錄或 NAS 匯出中已存在的檔案。Immich 會在原位置建立索引,並將檔案顯示在時間軸中,但不會修改或刪除原始檔案。
若要匯入現有目錄,請將它以唯讀方式掛載到 server container。編輯 immich-server: 下的 docker-compose.yml,並加入 volume:
immich-server:
volumes:
- ${UPLOAD_LOCATION}:/data
- /etc/localtime:/etc/localtime:ro
- /srv/photos:/mnt/media/photos:ro:ro 可確保 Immich 永遠無法碰觸原始檔案。使用 sudo docker compose up -d 重新建立 container,然後在網頁 UI 中前往你的頭像 → Administration → External Libraries → Create Library,選取擁有者使用者,按一下 Folders 下的 Add,並輸入 container 路徑 /mnt/media/photos,不要輸入 host 路徑 /srv/photos。按一下 Scan。使用 host 路徑而非 container 路徑,是 External Library 最常見的錯誤;掃描不會找到任何內容,並回報資產數為 0。
Immich 要求的升級規範
這是讓 Immich 正常運作與導致其故障的分界。Immich 發布速度快,且不會回移修正,也不支援降級。浮動的 v3 標籤是官方支援的版本追蹤方式。Immich 也盡量將重大變更保留在 major 版本中,但每次 pull 都會執行升級,無論你是否已閱讀版本說明;未經規劃的升級無法回復。對主機上每個長期運作的容器,都值得採用「固定版本後再閱讀版本說明」的習慣。因此,自架的 KiroCrew agent 會固定在一個已知可正常運作的標籤,而不是任由它在下一次重新啟動時自行變更。規範如下:
- 固定版本。 將
IMMICH_VERSION設為具體標籤,例如v3.0.2,不要使用總是拉取最新 v3.x 的浮動v3。 - 每次升級前都要閱讀版本說明。 其中會列出重大變更,尤其是資料庫或向量擴充功能的變更。v3.0 版本就是明顯的例子:該版本直接移除 pgvecto.rs,因此仍使用舊擴充功能的使用者,必須先完成 VectorChord 遷移(早在 v1.133 就已引入),才能升級。
- 先備份資料庫(Step 9)。任何時候都應如此;版本說明提到資料庫時,更要確實執行。
- 同時取得新的 compose 檔案。
IMMICH_VERSION只會固定 server 與 ML 映像檔。Postgres 映像檔是在docker-compose.yml內部 以 digest 固定,因此需要較新資料庫擴充功能的版本會隨附新的 compose 檔案。重新下載兩個 release 資產,重新套用你的.env值,然後再升級。 - 先更新行動版用戶端。 server 只支援相符的 major 版本,而 app 通常與目前及前一個 major 版本相容。當 server 比 app 新時,目前版本(v3.3.1,檢查日期為 2026-10-10)會在手機上顯示 App update is available 通知,並提供 Update 按鈕。Immich 建議先升級所有行動版用戶端,再升級 server。
將新檔案放置就緒後,實際執行的命令如下:
cd /opt/immich
sudo docker compose pull
sudo docker compose up -d
sudo docker image prune步驟 9:備份資料庫傾印與原始檔案,並進行測試
Immich 的備份包含兩部分,缺一不可。資料庫儲存相簿結構、人臉、搜尋索引,以及資產對應檔案的關係。原始檔案目錄儲存實際相片。只還原其中一部分,結果不是只有相片卻沒有整理結構,就是只剩指向遺失檔案的空殼。這種兩部分的結構不只是 Immich 的特性:自架 Chatwoot 支援服務台同樣需要 Postgres 傾印檔與上傳目錄的配對,否則還原的收件匣會遺失所有附件。將 Postgres 資料目錄直接複製成檔案樹,看似可以繞過傾印步驟,但不能作為可用的備份;完整的 Immich 備份與還原流程會說明這個陷阱,以及還原失敗後只剩空白時間軸的情況。
在 Postgres 容器內使用 pg_dump 傾印資料庫,指定 immich 資料庫,不要傾印整個叢集:
sudo docker exec -t immich_postgres pg_dump --clean --if-exists \
--dbname=immich --username=postgres | gzip > /opt/immich/immich-db-$(date +%F).sql.gz接著使用 restic、rsync 或 borg,將 UPLOAD_LOCATION,也就是完整的 /opt/immich/library 樹狀目錄,尤其是其中的 library/、upload/ 與 profile/ 子目錄,備份到另一台機器或物件儲存。無論由 cron 項目還是 systemd 計時器排程這項工作,都必須有失敗通知管道。將 systemd OnFailure= 單元指向你自己的 ntfy 推播伺服器,傾印失敗時就能在當晚將訊息送到手機,而不是等到還原時才發現。先備份資料庫,再備份檔案,讓傾印檔不會參照到檔案備份尚未複製的相片。外部資料庫請在其實際來源另行備份;Immich 不負責管理這些資料。
接下來是所有人都會跳過的部分:測試還原。 還原必須在全新的 stack 上執行,該 stack 的 server 從未啟動過;同時,Postgres image 的 vector extension 必須與傾印檔相容。因此,絕不能臨時自行決定 DB image tag。在使用相同 compose 與 .env 的測試主機上,清除所有舊狀態,只啟動資料庫,然後載入傾印檔:
cd /opt/immich
sudo docker compose down -v
sudo docker compose pull
sudo docker compose create
sudo docker start immich_postgres
sleep 10
gunzip --stdout immich-db-2026-07-15.sql.gz |
sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" |
sudo docker exec -i immich_postgres psql --dbname=immich --username=postgres --single-transaction --set ON_ERROR_STOP=on
sudo docker compose up -d在 VectorChord 資料庫中,sed 對 search_path 的重寫不是可選步驟。省略後,還原會在中途中止。將原始檔案放回原位並重新啟動 stack 後,開啟 Web UI:如果能看到相片與相簿,表示備份可用。如果從未執行過這項測試,就沒有備份,只有希望。
錯誤情況與實際看到的訊息
ML container 被 OOM-killed。 sudo docker compose logs immich-machine-learning 會突然終止,docker compose ps 顯示為 Restarting,退出代碼則是 137。sudo dmesg | grep -i oom 會進一步確認:Out of memory: Killed process ... (python3)。接著,搜尋與臉部辨識工作會停滯。原因是模型所需的 RAM 不足。請依序採取以下處理方式:增加 swap(Step 1);為 VPS 增加 RAM;如果確實無法增加,開啟 Administration → Settings → Machine Learning Settings,關閉最上層的 machine learning 開關,這會一次停用所有 ML 功能。只關閉 Smart Search 與 Facial Recognition 並不足夠,因為 OCR 與其他模型類型預設仍會啟用。備份與相簿仍會保留,但會失去依內容搜尋的功能。從 compose 檔案移除 immich-machine-learning service 也會產生相同效果。
升級後 Immich server 無法啟動。 Postgres container 可能正常執行;實際上是 immich_server 在啟動時檢查 vector extension 版本並拒絕啟動,而其 log 會反覆出現類似 The database currently has VectorChord 0.5.3 activated, but the Postgres instance only has 0.4.2 available. This most likely means the extension was downgraded. 的內容;在較舊的 stack 上,則可能出現 The pgvecto.rs extension is not available in this Postgres instance.。原因是 database image 的 extension 版本早於資料升級後所需的版本。這幾乎總是因為手動修改 image tag,或將較新的 dump 還原至較舊的 image。請使用相符的 Postgres image,從與資料庫相符的 release 取得 compose 檔案。不要降級,且只能還原至相容的 image。
mobile app 無法連線至 server。 輸入 URL 後,登入畫面會顯示類似 Could not connect to server 的連線錯誤。常見原因包括:輸入 http://,但 proxy 只提供 https://;直接連線至 backend 卻省略 port,因此系統嘗試連線至 example.com(port 443),而不是 example.com:2283;reverse proxy 未轉送 /api;或處理 Let's Encrypt HTTP-01 challenge 的 proxy 將 /.well-known/immich 路由至 Immich 以外的位置。請輸入完整的 https://photos.example.com URL,並先確認手機瀏覽器可以載入該 URL。如果瀏覽器可以連線,但 app 無法連線,可能是 proxy 移除了 path 或錯誤路由 /.well-known/immich;也可能是憑證為 self-signed,app 會以 handshake error 拒絕該憑證,除非在設定中啟用 self-signed certificate 支援。
匯入過程中磁碟空間耗盡。 Upload 會開始失敗,縮圖變成空白,log 會顯示 ENOSPC: no space left on device;Postgres 則可能顯示 could not extend file ... No space left on device。df -h 顯示 UPLOAD_LOCATION volume 已達 100%。因此,在匯入大型媒體庫前,應先規劃足夠的磁碟空間。處理方式是附加較大的 volume、停止 stack、將 UPLOAD_LOCATION 移至該 volume、更新 .env,再重新啟動;如果 provider 支援,也可以擴充現有磁碟。Postgres 在磁碟填滿時可能會卡住,因此請先清出空間並重新啟動 database container,再判斷是否發生資料損毀。
FAQ
Immich 需要多少 RAM 與磁碟空間?
Immich 的官方需求是至少 6 GB RAM,建議 8 GB。對小型媒體庫而言,4 GB 搭配 swap 是實際可行的下限。不論如何都應設定 swap,因為 machine-learning container 最容易出現資源尖峰。磁碟空間則應以完整媒體庫大小為基準,另外預留約 10–20% 用於產生縮圖與預覽,並使用本機儲存。Postgres data directory 絕對不要放在網路分享上。若你仍在決定還要執行哪些服務,2026 年自架服務指南會將 Immich 的資源占用與其他服務並列比較。
可以在沒有 GPU 的情況下執行 Immich 嗎?
可以。machine-learning container 在 CPU 上即可正常執行。GPU 只會加快智慧搜尋索引建立,以及在使用正確的 image variant 時加快影片轉碼。在 CPU 上,大型媒體庫的初始索引可能需要在背景執行數小時,但不會阻礙備份或瀏覽。如果主機太小,無法執行 ML,也可以在管理設定中使用頂層切換選項,完全關閉 machine learning,其他功能仍可保留。
如何安全升級 Immich?
將 IMMICH_VERSION 固定為具體 tag,例如 v3.0.2。每次升級前都應閱讀 release notes,並先備份資料庫。由於 Postgres image 是固定在 docker-compose.yml 內,而不是透過 IMMICH_VERSION 固定,因此請從目標 release 重新下載 compose file 與 example.env,重新套用你的設定值,然後執行 docker compose pull && docker compose up -d。絕對不要讓版本在無人管理的情況下浮動。Immich 不支援降級,因此未閱讀相關資訊就執行的升級無法復原。
我究竟需要備份哪些內容?
需要一併備份兩項內容:immich 資料庫的 pg_dump,以及完整的 UPLOAD_LOCATION originals directory。資料庫包含相簿、人臉與資產對檔案的對應關係;該目錄則包含實際相片。還原時需要這兩者,以及具備相容 vector extension 的資料庫 image。先執行資料庫傾印,再複製檔案,並至少在測試主機上測試一次還原。未經測試的備份不能算是備份。
如何匯入現有的相片資料夾?
將資料夾以唯讀方式作為額外 volume 掛載到 immich-server container,例如 - /srv/photos:/mnt/media/photos:ro,重新建立 container,然後在 Administration → External Libraries 中建立 library,並加入 container 路徑 /mnt/media/photos。Immich 會直接在原位置建立檔案索引,不會修改或刪除檔案。最常見的錯誤是輸入 host path,而不是 container path,導致掃描找不到任何內容。