Immichの外部ライブラリで既存の写真フォルダを再アップロードせずに取り込む
PCからrsyncした写真やNASの共有フォルダを、Immichに再アップロードせず外部ライブラリとして読み取り専用で登録する手順。compose編集、除外パターン、スキャン予定、家族でのフォルダ分け、ディスクから消えた時の挙動まで。
先に結論: 写真は動かさず、Immich に読ませる
Immich の外部ライブラリを使えば、PC から rsync で上げた写真ツリーや NAS の共有フォルダを、アプリで再アップロードせずにそのままの場所で取り込めます。フォルダを読み取り専用で immich-server コンテナに見せ、管理画面でライブラリを作ってスキャンするだけです。ファイルは元の場所に残り、Immich はそれを読むだけです。
手順は 4 つです。docker-compose.yml でフォルダを :ro 付きでバインドマウントする。管理画面で外部ライブラリを作り、インポートパスと除外パターンを登録する。スキャンを走らせる。定期スキャンの予定を決める。以下は 2026 年 9 月時点の最新タグ v3.2.2 の Docker Compose と公式ドキュメントに合わせています。外部ライブラリの削除まわりと監視機能はバージョンごとに挙動が変わってきたので、別のタグを使うならその版のドキュメントを読み直してください。
Immich 本体がまだ動いていないなら、先に Immich を VPS にセルフホストする手順 で Docker Compose の構成を立ち上げてから戻ってきてください。以下は docker-compose.yml と .env が /srv/immich にある前提で書きます。
アップロードと外部ライブラリ、2 つの所有モデル
Immich には写真の持ち方が 2 つあります。
アプリや Web からアップロードした写真は UPLOAD_LOCATION の配下(コンテナ内では /data)にコピーされ、Immich が所有します。Immich で削除すればファイルも消えます。
外部ライブラリの写真は元のフォルダに置いたままで、Immich は読むだけです。コンテナに :ro で見せておけば、Immich 側からファイルを消したり書き換えたりすることはできません。原本を守る側に倒した設計です。
ただし「読むだけ」でも Immich 自身のディスクは消費します。サムネイルとプレビューは UPLOAD_LOCATION/thumbs に、ブラウザで再生できない形式の動画は変換版が UPLOAD_LOCATION/encoded-video に生成され、顔認識と検索用のベクトルは PostgreSQL に入ります。原本が 200 GB あるからといって Immich 側に 200 GB は要りませんが、ゼロでもありません。サムネイルと DB の目安は Immich の RAM とストレージ要件 にまとめてあるので、ボリュームを切る前に見ておいてください。
もう一つ大きな違いがあります。重複チェックはアップロードにしか働かず、しかもライブラリ単位です。すでにアプリで一部の写真をアップロード済みなら、同じ写真が外部ライブラリからも入って二重に見えます。先に外部ライブラリを登録し、アプリのバックアップ対象はこれから撮る写真だけにするのが、後始末の少ない順番です。
写真ツリーを VPS に置く 3 つの方法
外部ライブラリの前提は、immich-server が動くホストから写真が普通のディレクトリとして見えることです。置き方は 3 通りあります。どれを選んでも、ユーザーごとにフォルダを分けておきます。理由は後半で説明します。
rsync で PC から上げる。 VPS のローカルディスクに置くので、いちばん速く、いちばん壊れにくい形です。まず VPS 側で受け皿を作ります。
sudo mkdir -p /srv/photos/alice /srv/photos/bob
sudo chown -R "$USER":"$USER" /srv/photos転送は PC 側から実行します。転送元の末尾のスラッシュを忘れると Pictures というフォルダが一段余計に掘られます。
rsync -avh --partial --progress ~/Pictures/ ubuntu@203.0.113.10:/srv/photos/alice/--partial があると、回線が切れても転送済みの部分を捨てません。同じコマンドを再実行すれば続きから転送されます。終わったら VPS 側で件数を数えておくと、後でスキャン結果と突き合わせられます。
find /srv/photos/alice -type f | wc -l追加のストレージボリュームに置く。 VPS にブロックストレージを足して /srv/photos にマウントする形です。Immich から見ればローカルディスクと同じです。/etc/fstab に nofail を付けておけば、ボリュームが外れた状態で再起動しても OS は起動します。
NAS の共有を NFS か SMB でマウントする。 自宅の NAS を VPN 越しに VPS から読む構成です。読み取り専用でマウントします。
sudo apt update && sudo apt install -y nfs-common
sudo mkdir -p /srv/photos/alice/etc/fstab に 1 行足します。nas.example.com は VPN 越しに届く NAS のアドレスに読み替えてください。
nas.example.com:/volume1/photo/alice /srv/photos/alice nfs ro,_netdev,nofail 0 0sudo systemctl daemon-reload
sudo mount /srv/photos/alice
ls /srv/photos/alice | headSMB なら cifs-utils を入れて、//nas.example.com/photo/alice /srv/photos/alice cifs ro,_netdev,nofail,credentials=/root/.smbcred 0 0 の形になります。どちらの場合も _netdev は「ネットワークが上がってからマウントする」、nofail は「マウントに失敗しても起動を止めない」という意味です。
docker-compose.yml に読み取り専用でバインドマウントする
Immich の Compose ファイルは名前付きボリュームを使わず、.env の UPLOAD_LOCATION をバインドマウントで /data に当てています。外部ライブラリも同じ流儀で、ホストのフォルダを immich-server にバインドマウントします。名前付きボリュームとの使い分けは Docker Compose のバインドマウントと名前付きボリュームの違い で整理していますが、外部ライブラリに限れば答えは一つです。Immich の外にある既存のディレクトリを見せる手段はバインドマウントしかありません。
まず .env でバージョンを固定します。v3.2.2 に同梱の example.env は IMMICH_VERSION=v3 となっていて、メジャーバージョン内の最新を追いかける設定です。手順どおりに動くことを確かめたいなら、タグまで書きます。
IMMICH_VERSION=v3.2.2
UPLOAD_LOCATION=/srv/immich/library
DB_DATA_LOCATION=/srv/immich/postgres
TZ=Asia/Tokyo次に docker-compose.yml の immich-server の volumes に、写真フォルダを :ro 付きで追加します。immich-machine-learning には追加しません。公式の例でもマウント先は immich-server だけです。
services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
volumes:
- ${UPLOAD_LOCATION}:/data
- /etc/localtime:/etc/localtime:ro
- /srv/photos/alice:/mnt/media/alice:ro
- /srv/photos/bob:/mnt/media/bob:roコロンの左がホスト側、右がコンテナ内のパスです。あとで管理画面に入力するのは右側の /mnt/media/alice であって、ホスト側の /srv/photos/alice ではありません。公式ドキュメントも「パスはすべてコンテナから見えるものでなければならない」と念を押しています。
:ro は外すこともできます。外すと Immich 内でファイルを削除したときに原本も削除され、メタデータの編集が .xmp サイドカーとして原本の隣に書き込まれます。原本をアプリの操作ミスから守りたいなら :ro のままにしてください。
書き換えたら、定義が変わったサービスだけを作り直します。
cd /srv/immich
docker compose pull
docker compose up -d
docker compose exec immich-server ls /mnt/media/alice | headdocker compose up -d は定義が変わった immich-server だけを再作成するので、データベースは止まりません。最後の ls でファイル名が並べば、コンテナから写真が見えています。
ls: cannot open directory '/mnt/media/alice': Permission denied が出るのは、NFS マウントでよくある結果です。NFS サーバー側の root_squash により、コンテナ内の root は NAS 側では nobody に落とされるので、所有者しか読めない権限のディレクトリは読めません。NAS 側で写真ツリーに全員の読み取り権限を付ける(chmod -R o+rX)か、エクスポート設定で root のマッピングを止めれば通ります。
管理画面で外部ライブラリを作る
右上のアバターから「管理」→「外部ライブラリ」を開き、「ライブラリを作成」を押します。最初にライブラリの所有者となるユーザーを選びます。これは後から変更できません。家族全員分のフォルダを一つのライブラリに入れると、全員の写真が一人の所有物になります。ここで人ごとに分けてください。
作ったライブラリの「インポートパス」に /mnt/media/alice を追加します。パスが読めないと画面に警告が出ます。警告が出たら前節の docker compose exec の ls に戻ってください。原因はマウントか権限のどちらかで、Immich の設定ではありません。
続けて除外パターンを登録し(次節)、それから「スキャン」を押します。順番が大事です。除外パターンを後から足しても、すでに取り込まれた NAS のサムネイル画像が消えるのは次のスキャンのときなので、それまでタイムラインに小さな複製が混ざります。
写真の枚数が多いと、ライブラリのスキャン自体は数分で終わっても、サムネイル生成と顔認識のジョブは何時間も残ります。ジョブの進み具合は管理画面のジョブ一覧で見えます。VPS の CPU が細いなら、初回は夜に流して放置するのが現実的です。
除外パターン: @eaDir と #recycle を最初に書く
除外パターンは glob 形式です。Synology の NAS は写真フォルダの中に @eaDir というサムネイル用の隠しフォルダを作り、#recycle にゴミ箱を持ちます。QNAP は .@__thumb です。これらを除外しないと、NAS が作った縮小画像が本物の写真と並んで取り込まれます。
**/\@eaDir/**
**/#recycle/**
**/.\@__thumb/**
**/Raw/**@ は glob の特殊文字なので、公式ドキュメントの例に合わせてバックスラッシュで逃がしています。**/Raw/** は RAW と JPEG を両方保存している人向けで、RAW 側のフォルダを外せば同じ一枚が二重に見えるのを防げます。拡張子で弾くなら **/*.{tif,psd} のように書きます。
スキャンの予定を決める。「監視」は NFS と SMB で効かない
外部ライブラリは自動では更新されません。ディスク上の変化を Immich に反映するには再スキャンが要る、というのがドキュメントの原則で、それを自動化する手段が 2 つあります。
定期スキャン。 「管理」→「設定」→「外部ライブラリ」に「ライブラリ定期スキャンの有効化」があり、既定でオンです。間隔は cron 式で、既定値は 0 0 * * *、つまり毎日 0 時です。時刻はコンテナのタイムゾーンで解釈されるので、.env の TZ=Asia/Tokyo を有効にしておけば日本時間の 0 時になります。確認は docker compose exec immich-server date です。旅行から帰って rsync した日にすぐ見たいなら、ライブラリの画面で「スキャン」を手で押します。
ライブラリ監視(実験的機能)。 同じ設定画面にある「外部ライブラリのファイル変更を監視」です。有効にすると、OS がファイルの変化を通知した時点で Immich がその 1 枚を取り込みます。仕組みは Linux の inotify で、これは自分のカーネルを通ったファイル操作についてだけ発火します。NFS や SMB のマウントでは、写真を書き込むのは NAS 本体か、NAS に向けて書いている自宅の PC です。その書き込みは VPS のカーネルを一度も通らないので、VPS 側の inotify には何も届かず、監視は発火しません。ドキュメントも「ネットワークドライブ上の写真では自動監視はまず動かない」と書いています。
つまり、NAS をマウントした外部ライブラリでは定期スキャンが唯一の確実な経路です。rsync で VPS のローカルディスクに置いた写真なら監視は原理的に動きますが、実験的機能と明記されているので、定期スキャンを主にして監視はおまけと考えるのが無難です。
家族で使う: ユーザーごとにフォルダを分けてパートナー共有で見せる
家族の写真を一つのフォルダに入れて全員で見る、という形は外部ライブラリではできません。ライブラリは作成時に選んだ一人のユーザーに属し、そのユーザーのタイムラインにしか出ないからです。
正解は人ごとにフォルダとライブラリを分けることです。/srv/photos/alice は alice の外部ライブラリ、/srv/photos/bob は bob の外部ライブラリ。Compose のマウントを二行に分けたのはこのためです。管理者が bob の分のライブラリを作るときも、所有者には bob を選びます。
お互いの写真を見せ合うにはパートナー共有を使います。alice でログインし、アカウント設定の「パートナーの共有」から「パートナーを追加」で bob を選びます。これで bob のタイムラインに alice の写真が、外部ライブラリの分も含めて出ます。逆向きも同じ操作です。相手の写真を自分のタイムラインに混ぜて表示するかどうかも、同じ画面で切り替えられます。
家族共通のフォルダ(例: /srv/photos/family)がどうしても欲しいなら、それも誰か一人のライブラリにして、パートナー共有で全員に見せます。所有者を後から変えられない以上、共通用のユーザーを一人作って共通フォルダはそこに持たせるのが、後で困らない置き方です。
ディスクから消えたときと、Immich で削除したときの違い
外部ライブラリでいちばん質問が多いのがここで、しかもバージョンで挙動が変わってきた部分です。v3.2.2 の公式ドキュメントと FAQ に書かれている挙動は次のとおりです。
ディスクからファイルが消えた。 次のスキャンで、その写真は Immich のゴミ箱に移ります。タイムラインからは消えますが、DB にはまだ残っています。元のファイルをディスクに戻して再スキャンすれば復活します。ゴミ箱の保持期間は既定で 30 日(「管理」→「設定」→「ゴミ箱」で変更可)で、それを過ぎると Immich から完全に消え、Immich 内で付けたお気に入りやアルバム、編集した日時などのメタデータも失われます。
Immich にとって「パスごと読めない」と「ファイルが消えた」は別の状態で、インポートパスが読めないときはライブラリの画面に警告が出ます。NAS マウントの構成では、マウントが外れたまま夜の定期スキャンが走る状況を作らないことが第一です。nofail に頼りきらず、mountpoint -q /srv/photos/alice || echo unmounted のような確認を監視に入れておいてください。
Immich の中で削除した。 :ro でマウントしている場合、ゴミ箱に入れることはできますが、ゴミ箱を空にするときに Immich は原本を消せません。FAQ に書かれているとおり、その写真はタイムラインに戻ってきます。原本を消したいならディスク側で消してください。:ro を外して書き込み可にしている場合は、ゴミ箱を空にした時点で原本のファイルがディスクから削除されます。取り消せないので、家族が使うサーバーでは :ro を推奨します。
フォルダ内で移動・リネームした。 Immich は移動を追跡しません。ドキュメントには「ライブラリ内で別の場所に移すと、再スキャンでそのメタデータはすべて失われる」と明記されています。フォルダ構成は Immich に登録する前に固めておき、以降は動かさない運用にします。
メタデータはどこに残るか、バックアップの分担
:ro の外部ライブラリでは、Immich が原本の隣に .xmp サイドカーを書けません。つまり Immich で直した撮影日時や場所、お気に入り、アルバム、顔に付けた名前は PostgreSQL にしかありません。原本のフォルダをバックアップしても、それらは含まれないということです。
だから外部ライブラリ構成でも Immich 側のバックアップは省けません。DB ダンプと UPLOAD_LOCATION を守る手順は Immich のバックアップと復元 にあります。原本はもともと別の場所にあるので、そちらは NAS のスナップショットや rsync 元の PC に任せ、Immich 側は DB と thumbs を守る、という分担になります。
FAQ
外部ライブラリの写真は Immich のディスクを使わないのですか?
原本はコピーされませんが、サムネイルとプレビューは UPLOAD_LOCATION/thumbs に、ブラウザで再生できない形式の動画は変換版が UPLOAD_LOCATION/encoded-video に生成されます。顔認識と検索用のベクトルは PostgreSQL に入ります。原本よりはずっと小さいものの、動画が多いと変換版で膨らむので、Immich 側のボリュームにも余裕を持たせてください。
スキャンしても写真が出てきません。何を確認すればいいですか?
確認は 4 点です。docker compose exec immich-server ls /mnt/media/alice でコンテナから見えているか。ライブラリのインポートパスがホスト側の /srv/photos/alice ではなくコンテナ側の /mnt/media/alice になっているか。ライブラリの所有者でログインしているか(管理者でも他人のライブラリはタイムラインに出ません)。除外パターンが広すぎないか。Permission denied が出るなら NFS の root_squash で、コンテナ内の root が NAS 側では nobody になっていて読めない状態です。
NAS に写真を追加しても Immich に反映されません。監視をオンにしたのに、なぜですか?
ライブラリ監視は Linux の inotify に頼っていて、inotify はそのマシンのカーネルを通ったファイル操作しか通知しません。NFS や SMB でマウントした NAS への書き込みは NAS 側で起きるので、VPS のカーネルには何も届かず、監視は発火しません。ネットワークドライブでは定期スキャン(既定で毎日 0 時)に任せ、急ぐときはライブラリの画面で手動スキャンしてください。
家族全員の写真を一つのフォルダに入れて共有できますか?
外部ライブラリは作成時に選んだ一人のユーザーに属し、あとから所有者を変えられません。人ごとに /srv/photos/alice、/srv/photos/bob のようにフォルダとライブラリを分け、アカウント設定の「パートナーの共有」でお互いを追加すると、相手の写真が自分のタイムラインに出ます。共通フォルダが欲しい場合は、共通用のユーザーを一人作ってそのライブラリにし、全員のパートナーにします。
Immich で削除した写真は NAS からも消えますか?
:ro でマウントしていれば消えません。ゴミ箱には入りますが、ゴミ箱を空にする段階で Immich は原本を削除できず、写真はタイムラインに戻ります。:ro なしで書き込み可にしている場合は、ゴミ箱を空にした時点で原本がディスクから削除され、取り消せません。逆にディスク側でファイルを消した場合は、次のスキャンで Immich のゴミ箱に移り、既定では 30 日後に完全に消えます。