Backup và restore Immich trên VPS đúng cách
Biết backup Immich cần file gốc, SQL dump Postgres và file stack; tránh lỗi copy data directory khiến restore xong timeline trống dù disk vẫn đầy.
Nội dung bắt buộc của một bản backup Immich
Một bản backup Immich gồm 3 phần được ghi lại tại cùng một thời điểm: các file gốc trong UPLOAD_LOCATION, SQL dump của database Postgres, và .env cùng docker-compose.yml mô tả stack. Khôi phục nghĩa là nạp lại dump đó vào một database mới trong khi Immich server đã dừng, rồi chỉ khởi động phần còn lại của stack sau khi hoàn tất. Nếu thực hiện sai thứ tự, bạn có thể có một Immich hoạt động nhưng timeline trống, trong khi disk vẫn chứa đầy dữ liệu.
Việc tách các phần này rất quan trọng vì Immich lưu state ở 2 nơi không biết gì về nhau. Postgres chứa mọi album, mọi face cluster, mọi shared link, mọi user account và API key, cùng với path đã lưu của từng asset. Filesystem chứa các pixel. Nếu khôi phục file mà không có database, Immich sẽ không hiển thị gì. Nếu khôi phục database mà không có file, mọi asset sẽ mở thành broken image.
Các lệnh trong phần này được viết cho Immich v3.1.0, bản release hiện tại vào đầu tháng 8 năm 2026. Project release rất nhanh và quy trình backup được tài liệu hóa đã thay đổi nhiều lần, vì vậy hãy kiểm tra version bạn đang chạy trước khi sao chép bất kỳ thứ gì. Nếu stack chưa chạy, hãy bắt đầu với hướng dẫn cài đặt Immich rồi quay lại.
Biết đường dẫn của bạn trỏ đến đâu
Hai biến trong .env quyết định mọi thứ trên trang này. UPLOAD_LOCATION là thư mục cha mà Immich ghi toàn bộ media vào. DB_DATA_LOCATION là thư mục dữ liệu Postgres.
example.env mặc định đặt UPLOAD_LOCATION=./library. Đây là giá trị mặc định dễ gây nhầm lẫn, vì sau đó Immich tạo một thư mục tên library bên trong thư mục này. Các file gốc của bạn nằm tại ./library/library. Hãy đặt một đường dẫn tuyệt đối để script backup không bao giờ phụ thuộc vào thư mục mà bạn chạy script.
UPLOAD_LOCATION=/srv/immich/data
DB_DATA_LOCATION=/srv/immich/postgres
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
IMMICH_VERSION=v3.1.0Bên trong UPLOAD_LOCATION, Immich tạo một số thư mục. Ba thư mục trong số đó chứa dữ liệu mà không job nào có thể tạo lại:
library: các file gốc, được sắp xếp theo storage template của bạnupload: các file gốc chưa được chuyển vào bố cục của template, cùng với các file đang được uploadprofile: ảnh profile của người dùng
Nếu mất library thì ảnh đó cũng mất. Immich không lưu bản sao thứ hai của file gốc ở bất kỳ đâu.
Vì sao sao chép thư mục dữ liệu Postgres không phải là backup
DB_DATA_LOCATION trông có vẻ là đích sao chép dễ dàng. Nó là một thư mục, rsync sẽ sao chép thư mục đó, và thao tác sao chép hoàn tất mà không báo lỗi. Tuy nhiên, đây vẫn không phải là backup vì có 2 lý do có thể khiến bạn thấy thao tác này thất bại.
Lý do đầu tiên là dữ liệu bị xé lẻ. Postgres trước tiên ghi mọi thay đổi vào write-ahead log (WAL), rồi mới áp dụng các thay đổi đó vào file bảng tại checkpoint. Vì vậy, tại bất kỳ thời điểm nào, các file trên disk đều có thể đang được cập nhật dở dang. Một thao tác sao chép tuần tự mất 4 phút có thể đọc file đầu tiên lúc 02:00 và file cuối cùng lúc 02:04. 2 file đó không thuộc cùng một transaction. Khi khởi động Postgres với bản sao này, Postgres sẽ từ chối khởi động và báo PANIC: could not locate a valid checkpoint record, hoặc khởi động rồi dừng ngay khi đọc trang dữ liệu bị hỏng đầu tiên với lỗi invalid page in block 1234 of relation base/16384/.... Không thể khôi phục dữ liệu từ bản sao đó trong cả hai trường hợp.
Lý do thứ hai vẫn tồn tại ngay cả khi bạn dừng mọi thứ trước. Thư mục dữ liệu Postgres gắn với chính xác các binary đã ghi dữ liệu vào đó. Immich cố định database image bằng digest, hiện là ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0. Đây là Postgres 14 với 2 extension vector search được biên dịch sẵn. Thư mục dữ liệu được tạo bởi build đó sẽ không mở được bằng Postgres major version khác, và cũng không mở được bằng build có phiên bản extension khác. Host dùng để restore phải tái tạo image chính xác. SQL dump không bị ràng buộc như vậy: nó là văn bản, và bất kỳ server tương thích nào cũng có thể chạy lại nó.
pg_dump loại bỏ hoàn toàn vấn đề dữ liệu bị xé lẻ. Nó đọc toàn bộ database trong một snapshot MVCC (multi-version concurrency control) duy nhất. Vì vậy, nó nhìn thấy database đúng như tại một thời điểm, trong khi các thao tác ghi khác vẫn tiếp tục. Đây là lý do bạn không cần dừng Postgres để tạo dump.
Có thể loại khỏi backup
Các dữ liệu này có thể tạo lại, nên bạn có thể bỏ qua:
thumbs: ảnh preview và thumbnailencoded-video: video đã transcodeDB_DATA_LOCATION: dữ liệu được dựng lại từ dump- volume Docker
model-cache: model machine learning, có thể tải lại khi cần
Bỏ qua các dữ liệu này là một đánh đổi, không phải lợi ích miễn phí. Việc dựng lại thumbnail và transcode cho một thư viện lớn có thể ngốn hàng giờ CPU trên VPS nhỏ, trong thời gian đó timeline sẽ chỉ hiển thị placeholder màu xám. Bạn chạy lại các tác vụ này tại Administration > Jobs, đặt "Generate Thumbnails" và "Transcode Videos" chạy trên các asset còn thiếu. Nếu backup target còn đủ chỗ, hãy đưa chúng vào backup để không phải chờ dựng lại. Nếu sắp chạm giới hạn storage, hãy bỏ chúng và chuẩn bị cho quá trình rebuild. Định cỡ thư viện Immich giải thích các thư mục này thường lớn đến đâu so với file gốc.
Có thêm một thư mục bạn nên biết. UPLOAD_LOCATION/backups chứa các database dump tự động của Immich, được tạo hằng ngày lúc 02:00 và giữ lại 14 bản gần nhất. Bạn có thể cấu hình tại Administration > Settings > Backup. Các dump này không tốn thêm storage đáng kể và thực sự hữu ích. Tuy nhiên, chúng nằm trên cùng disk với library mà chúng bảo vệ, nên chỉ giúp xử lý migration lỗi, không giúp khôi phục khi server hỏng hoàn toàn. Dù vậy, hãy tự tạo dump của riêng bạn, vì dump do bạn chủ động tạo sẽ được ghi cùng thời điểm với file snapshot tương ứng.
Tạo bản dump của database
docker exec -t immich_postgres pg_dump --clean --if-exists \
--dbname=immich --username=postgres \
| gzip > /srv/immich/backup/immich.sql.gzThay immich và postgres bằng DB_DATABASE_NAME và DB_USERNAME của bạn nếu bạn đã thay đổi chúng. --clean --if-exists thêm DROP ... IF EXISTS trước mọi CREATE, nên bản dump được phát lại vào database đã có sẵn các object thay vì dừng ở object đầu tiên.
Bây giờ là chi tiết thường âm thầm làm hỏng các backup script. Lệnh đó là một pipeline, và shell báo cáo exit status của lệnh cuối cùng trong pipeline. Nếu pg_dump fail do sai password hoặc container chưa chạy, gzip sẽ nhận một stream rỗng, ghi ra một file gzip hoàn toàn hợp lệ rồi thoát với mã 0. Script của bạn ghi log thành công, còn bạn chỉ có một bản backup 20 byte. Đặt pipefail ở đầu mọi backup script:
#!/usr/bin/env bash
set -euo pipefailSau đó kiểm tra kết quả thay vì tin vào exit code:
ls -lh /srv/immich/backup/immich.sql.gz
gunzip -c /srv/immich/backup/immich.sql.gz | head -n 3Dòng đầu tiên của một bản dump hợp lệ là -- PostgreSQL database dump. File chỉ vài trăm byte là bản dump bị lỗi, bất kể script báo gì.
Ghi lại build đã tạo file đó ngay cạnh bản dump:
docker inspect --format '{{.Config.Image}}' immich_server > /srv/immich/backup/immich-version.txtĐừng dựa vào .env cho việc này. File mặc định đặt IMMICH_VERSION=v3, đây là một tag thay đổi theo mọi bản phát hành 3.x, nên không cho biết build nào thực sự đã tạo bản dump. Đồng thời ghim tag chính xác trong .env.
Tạm dừng server, sau đó tạo snapshot bằng restic
Các file trong UPLOAD_LOCATION không bất biến khi Immich đang chạy. Server ghi các lượt upload mới, còn job storage template di chuyển file giữa các thư mục. Nếu công cụ backup đọc một file khi file đó đang được ghi dở, nó sẽ lưu các byte đã đọc như thể đó là toàn bộ file, và không thành phần nào báo lỗi. Dừng server container trong suốt thời gian chạy:
docker stop immich_serverĐể immich_postgres tiếp tục chạy vì dump cần đến nó. Web interface và mobile app sẽ offline cho đến khi bạn khởi động lại server. Với một instance dùng trong gia đình, việc này thường không thành vấn đề nếu chạy lúc 03:00.
restic phù hợp ở đây vì nó deduplicate và encrypt dữ liệu trước khi bất kỳ dữ liệu nào rời khỏi máy. Trỏ nó đến một repository không nằm trên server này:
export RESTIC_REPOSITORY=sftp:backup@backup.example.com:/srv/restic/immich
export RESTIC_PASSWORD_FILE=/root/.restic-password
restic initObject storage cũng hoạt động tương tự và là lựa chọn tốt hơn nếu bạn muốn bản sao hoàn toàn nằm ngoài phần cứng của mình:
export RESTIC_REPOSITORY=s3:https://s3.example.com/immich-backup
export AWS_ACCESS_KEY_ID=your-access-key
export AWS_SECRET_ACCESS_KEY=your-secret-key
restic initEndpoint đó có thể là một MinIO bucket do bạn tự chạy trên máy thứ hai hoặc bất kỳ nhà cung cấp nào tương thích với S3. Repository trên cùng disk với thư viện chỉ bảo vệ bạn trước thao tác xóa nhầm, chứ không bảo vệ được trước bất kỳ sự cố nào khác.
Sau đó tạo snapshot, chỉ định chính xác những gì cần backup:
restic backup \
/srv/immich/backup/immich.sql.gz \
/srv/immich/backup/immich-version.txt \
/srv/immich/data/library \
/srv/immich/data/upload \
/srv/immich/data/profile \
/srv/immich/.env \
/srv/immich/docker-compose.yml
docker start immich_serverrestic đọc toàn bộ cây thư mục trong mỗi lần chạy nhưng chỉ upload các block chưa từng xuất hiện trước đó. Vì vậy, snapshot đầu tiên sẽ chuyển toàn bộ thư viện, còn mỗi snapshot sau đó chỉ chuyển các ảnh mới trong ngày.
Retention và các key phải lưu ở nơi khác
restic forget --prune --keep-daily 7 --keep-weekly 5 --keep-monthly 12forget loại snapshot khỏi index. --prune là phần xóa dữ liệu mà các snapshot đó từng là tham chiếu cuối cùng. Chạy forget mà không có --prune thì chi phí lưu trữ sẽ không bao giờ giảm.
Kiểm tra cấu trúc không tốn nhiều tài nguyên, nên hãy chạy mỗi tuần một lần:
restic checkLệnh này xác minh metadata của repository nhất quán. Nó không đọc dữ liệu của bạn. Mỗi tháng một lần, hãy đọc lại một mẫu dữ liệu và đối chiếu với các hash đã ghi nhận:
restic check --read-data-subset=5%Đây là cách kiểm tra duy nhất phát hiện lỗi hỏng dữ liệu âm thầm trên storage backend, vì nó tải các block thực tế xuống và tính lại checksum. Chạy --read-data đầy đủ trên thư viện ảnh nghĩa là tải toàn bộ repository xuống. Với object storage tính phí theo dung lượng truyền, việc này tốn tiền thực tế, nên subset luân phiên mới là cách mọi người thường dùng.
Bây giờ là phần nhiều người bỏ qua. Không thể khôi phục mật khẩu của restic repository. Không có cách reset và cũng không có support ticket. Nếu bản sao duy nhất nằm trong /root/.restic-password trên chính server bạn đang cố restore, backup của bạn chỉ còn là dữ liệu đã mã hóa không thể sử dụng. Điều tương tự cũng áp dụng cho access key của object storage và DB_PASSWORD từ .env. Hãy lưu tất cả những thứ này ở nơi không phụ thuộc vào việc máy này còn hoạt động: in ra giấy và cất trong ngăn kéo, hoặc lưu trong password manager chạy trên phần cứng khác. Nếu password manager đó cũng được self-host, nó cũng cần được xử lý như vậy, và backup Vaultwarden là một công việc riêng.
Khôi phục Immich theo đúng thứ tự
Thứ tự khôi phục quyết định backup tốt có khôi phục được timeline hay không. Hãy thực hiện đúng chuỗi bước này trên host mới.
Khôi phục config trước. Config cho biết cần chạy version nào và các path trỏ đến đâu.
restic restore latest --target /restore \
--include /srv/immich/.env \
--include /srv/immich/docker-compose.yml \
--include /srv/immich/backupPin version trước khi khởi động bất kỳ thứ gì. Đọc immich-version.txt, đặt IMMICH_VERSION trong .env thành đúng tag đó và tạm thời không dùng release mới nhất. Immich không hỗ trợ downgrade, kể cả giữa các patch release. Nếu server mới hơn khởi động với dump cũ và chạy migration, bạn không thể quay lại.
Khôi phục media.
restic restore latest --target /restore --include /srv/immich/dataSau đó di chuyển library, upload và profile để chúng nằm trực tiếp bên trong path mà UPLOAD_LOCATION trỏ đến trên host này. Có thể thay đổi host path, vì compose file bind directory đó vào một path cố định bên trong container. Layout bên trong directory không được thay đổi.
Chỉ khởi động database. Để DB_DATA_LOCATION trống để Postgres khởi tạo cluster mới.
cd /srv/immich
docker compose pull
docker compose create
docker start immich_postgres
docker exec immich_postgres pg_isready --username=postgrespg_isready in accepting connections sau khi hoàn tất thiết lập lần đầu. Quá trình này mất vài giây. docker compose create build tất cả container nhưng không khởi động chúng. Đó là mục đích của bước này: Immich server chưa được chạy. Nếu server khởi động với database trống, nó sẽ chạy migration, tạo schema mới và yêu cầu bạn tạo admin account mới. Khi đó bạn đang restore dump vào bên dưới một application đang chạy.
Restore dump.
gunzip --stdout /restore/srv/immich/backup/immich.sql.gz \
| sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" \
| docker exec -i immich_postgres psql --dbname=immich --username=postgres \
--single-transaction --set ON_ERROR_STOP=onHai thành phần trong lệnh này thực sự cần thiết. sed tồn tại vì pg_dump ghi một search_path trống vào output như một biện pháp an toàn. Nhờ đó, các tên không đủ điều kiện trong dump không thể trỏ nhầm đến một schema khác. Các vector-search type của Immich nằm trong public. Vì search path trống, quá trình restore sẽ gặp column đầu tiên được khai báo bằng vector type và psql dừng với ERROR: type "vector" does not exist. Thêm public vào path sẽ khắc phục lỗi này.
--single-transaction --set ON_ERROR_STOP=on bọc toàn bộ quá trình restore trong một transaction và dừng ngay khi gặp lỗi đầu tiên. Bạn sẽ nhận được database hoàn chỉnh hoặc database chưa bị thay đổi. Nếu không dùng tùy chọn này, lỗi xảy ra giữa chừng sẽ để lại một database vẫn khởi động và chấp nhận đăng nhập nhưng bị thiếu một số lượng album không xác định. Bạn có thể chỉ phát hiện ra việc này vài tuần sau.
Bây giờ khởi động mọi thứ.
docker compose up -d
docker compose ps
docker logs -f immich_serverChờ một startup line như Immich Server is listening on, sau đó mở port 2283 và đăng nhập bằng thông tin xác thực cũ, vì user account đã được khôi phục cùng dump. Nếu trang đăng nhập thay vào đó yêu cầu tạo admin account đầu tiên, database chưa được restore. Hãy dừng lại và đọc lại output của psql.
Lưu ý về hướng dẫn restore chính thức, bắt đầu bằng docker compose down -v. -v xóa named volume. Trong compose file mặc định, UPLOAD_LOCATION và DB_DATA_LOCATION là bind mount nên vẫn còn sau lệnh này. Nếu bạn đã đổi một trong hai thành named volume, lệnh đó sẽ xóa ảnh của bạn. Hãy đọc compose file trước khi chạy lệnh.
Vì sao timeline trống sau khi khôi phục
Timeline được tạo từ các row trong database. Immich không quét upload/ khi khởi động để tìm lại ảnh, vì file không có row sẽ không có owner, ngày tháng hoặc album. Vì vậy, lỗi khôi phục thường gặp nhất là file đã được khôi phục nhưng database bị thiếu. Immich khởi động, tạo schema trống và cung cấp cho bạn một instance hoạt động nhưng không có dữ liệu, trong khi ổ đĩa vẫn chứa đầy ảnh. Không có gì bị mất. Nhưng cũng không có gì hiển thị. Cách khắc phục là replay dump khi server đã dừng, đúng như phần trên.
Trường hợp thứ hai khó nhận biết hơn. Database được khôi phục, timeline hiển thị các entry, nhưng asset nào cũng không mở được. Điều đó có nghĩa là các row trỏ đến những file mà container không nhìn thấy. Nguyên nhân thường là library, upload và profile bị lồng sâu hơn một cấp sau khi có restic restore --target /restore nhưng không ai đưa nó về đúng vị trí. Hãy kiểm tra từ bên trong container thay vì đoán:
docker exec immich_server ls /dataFile compose mặc định mount UPLOAD_LOCATION vào /data, vì vậy kết quả liệt kê phải hiển thị library, upload và profile. Nếu kết quả hiển thị một thư mục trống hoặc một thư mục srv thừa, bind mount của bạn đang trỏ sai cấp thư mục còn các row vẫn đúng.
Khớp phiên bản giữa backup và restore
Immich thường xuyên phát hành phiên bản mới và schema thay đổi theo từng phiên bản, nên dump chứa schema của server đã tạo ra dump đó.
Restore một dump cũ hơn vào server mới hơn thường hoạt động, vì server áp dụng các migration còn thiếu khi khởi động và cập nhật schema theo từng bước. Quy trình này được kiểm thử theo chuỗi phát hành. Vấn đề thường xảy ra khi bỏ qua nhiều phiên bản major trong một lần nâng cấp. Project giữ các thay đổi không tương thích ở các phiên bản major và ghi rõ chúng trong changelog.
Restore một dump mới hơn vào server cũ hơn hoàn toàn không hoạt động. Dump chứa các table và column mà code cũ không biết đến. Immich cũng nêu rõ rằng downgrade không được hỗ trợ, kể cả giữa các patch release. Không có lệnh rollback để sử dụng trong trường hợp này.
Vì vậy, cách restore an toàn thường khá đơn giản. Chạy đúng phiên bản đã tạo dump, restore dump đó, đăng nhập và xác nhận timeline đầy đủ. Chỉ nâng cấp sau khi hoàn tất các bước này. Nâng cấp từng release một, tăng IMMICH_VERSION rồi chạy docker compose pull && docker compose up -d sau mỗi lần tăng phiên bản. Giữ lại dump của một tuần cũng hữu ích: nếu dump mới nhất được tạo trong lúc một lần nâng cấp thất bại, dump của ngày hôm qua vẫn còn trong repository.
Xác minh backup mỗi tháng
Một backup mà bạn chưa từng restore chỉ là phỏng đoán. Mỗi tháng một lần, hãy restore backup vào một instance tạm thời rồi mở một bức ảnh để kiểm tra. Bài kiểm tra này mất khoảng hai mươi phút. Đây là việc duy nhất biến toàn bộ nội dung còn lại của trang này thành một recovery plan.
restic snapshots
restic stats latestsnapshots phải liệt kê lần chạy tối qua. stats latest phải báo kích thước gần với dung lượng thư viện của bạn, không phải chỉ vài megabyte.
Hãy restore vào một thư mục tạm, tốt nhất là trên một host dự phòng:
restic restore latest --target /tmp/immich-drillSao chép docker-compose.yml và .env ra khỏi bộ đã restore, rồi thay đổi ba thứ trong bản sao. Trỏ UPLOAD_LOCATION và DB_DATA_LOCATION đến các thư mục bên dưới /tmp/immich-drill. Publish web port ở một vị trí khác, dùng 12283:2283 thay vì 2283:2283. Xóa các dòng container_name:, vì file compose mặc định hard-code các tên như immich_server. Do đó, stack thứ hai trên cùng host sẽ bị trùng với stack thứ nhất và Docker từ chối tạo stack đó.
Chạy chuỗi restore ở phần trên: chỉ restore database, replay dump, rồi chạy docker compose up -d. Sau đó thực hiện 4 kiểm tra để xác nhận kết quả.
- Đăng nhập bằng password bạn đã dùng trước khi kiểm tra. Tài khoản hoạt động cho biết dump đã được restore.
- Mở timeline và cuộn đến tháng cũ nhất. Asset trải dài toàn bộ khoảng thời gian cho biết tất cả row đã được khôi phục, không chỉ các row gần đây.
- Mở một ảnh ở kích thước đầy đủ và tải original xuống.
- So sánh ảnh đó với cùng file trong thư viện đang chạy bằng
sha256sum. Hash trùng nhau cho biết các byte đã qua được toàn bộ vòng round trip qua restic.
Sau đó dọn bài kiểm tra bằng docker compose down -v trong thư mục kiểm tra và xóa /tmp/immich-drill. Ghi ngày thực hiện ở nơi bạn sẽ nhìn thấy, vì giá trị của việc này hoàn toàn nằm ở việc lặp lại vào tháng sau. Nếu bạn vẫn đang cân nhắc nên chọn photo server nào, phần so sánh PhotoPrism và Immich giải thích hai hệ thống khác nhau như thế nào chính ở khía cạnh này.
FAQ
Tôi có phải dừng Immich để backup không?
Dừng immich_server và để immich_postgres tiếp tục chạy. Database không cần tạm dừng, vì pg_dump đọc trong một MVCC snapshot duy nhất và luôn thấy cùng một thời điểm nhất quán, bất kể các tiến trình khác đang ghi gì. Files mới là lý do phải dừng: server ghi các upload mới, còn storage template job di chuyển files giữa các directory. Vì vậy, công cụ backup có thể đọc một file khi file đang được ghi dở và lưu một bản sao bị cắt ngắn mà không báo lỗi. Chạy docker stop immich_server trước snapshot và docker start immich_server sau snapshot sẽ loại bỏ race này.
Tôi có thể copy thư mục dữ liệu Postgres thay vì chạy pg_dump không?
Không. Copy lần lượt một data directory đang hoạt động sẽ đọc các file ở những thời điểm khác nhau. Kết quả không đại diện cho một trạng thái nhất quán, và Postgres sẽ từ chối khởi động với PANIC: could not locate a valid checkpoint record hoặc chỉ phát hiện lỗi sau đó khi đọc một page bị hỏng. Ngay cả bản copy được tạo khi mọi thứ đã dừng cũng chỉ dùng được với đúng database build đó: Immich cố định image Postgres 14 cùng các phiên bản extension vector-search cụ thể, và directory này sẽ không mở được dưới bất kỳ phiên bản nào khác. SQL dump là plain text và có thể replay vào bất kỳ server tương thích nào.
Vì sao timeline Immich trống sau khi restore?
Vì timeline được tạo từ các row trong database, còn bạn chỉ restore files mà không restore database. Immich không bao giờ quét upload/ để tìm lại photos, nên các files không có row tương ứng sẽ vẫn bị ẩn. Các photos vẫn nguyên vẹn. Dừng server, replay dump vào một Postgres vừa được khởi tạo, rồi start stack. Nếu timeline vẫn đầy nhưng mọi photo đều không mở được, thì vấn đề ngược lại: library, upload và profile không nằm trực tiếp trong directory được bind vào container. Kiểm tra bằng docker exec immich_server ls /data.
Có thể bỏ qua những thư mục Immich nào khi backup?
thumbs và encoded-video có thể được tạo lại từ originals, còn DB_DATA_LOCATION được rebuild từ dump, nên không thư mục nào trong số đó bắt buộc phải có trong backup set. Bỏ qua chúng sẽ chuyển thời gian sang sau khi restore thay vì tốn storage trước đó, vì việc rebuild previews và transcodes cho một library lớn có thể mất hàng giờ CPU, chạy từ Administration > Jobs đối với các assets bị thiếu. Bạn tuyệt đối không được bỏ qua library, upload và profile, vì chúng chứa bản sao duy nhất của mọi original.
Tôi có thể restore dump Immich vào phiên bản mới hơn không?
Thông thường là có, vì server áp dụng các migration đang chờ khi start và nâng schema lên từng bước. Chiều ngược lại sẽ fail: Immich không hỗ trợ downgrade, kể cả giữa các patch release, nên dump từ một release mới hơn không thể được load vào server cũ hơn. Restore với IMMICH_VERSION được pin vào release đã ghi dump, xác nhận timeline đầy đủ, rồi mới upgrade. Ghi lại version bên cạnh từng dump bằng docker inspect --format '{{.Config.Image}}' immich_server, vì IMMICH_VERSION=v3 mặc định là một floating tag và không cho biết thông tin gì.