プログラミング

Google PhotosをImmichで自前に置き換える

自宅のUbuntuサーバーにImmichを立てて、Google Photosの代わりにスマホの写真を自前でバックアップする手順です。本体・AIの頭脳(ML)・DB・Redisの4コンテナ構成、実際に使っているイメージのバージョンとポート2283、写真の保存先、ベクトル検索でAI検索が動く仕組み、Tailscale経由の外部アクセス、Claude Codeへの指示書までまとめました。

目次

はじめに

スマホの写真がどんどん増えて、「Google Photosの容量、そろそろ限界かも」と感じていませんか。

家族や旅行の写真がたまっていくのは幸せなことですが、その分だけクラウドの容量は埋まり、容量を増やすための課金が続きます。
大切な思い出の写真を、ぜんぶよその会社のサーバーに預けっぱなしというのも、少し心もとない気持ちがありました。

結論として、Immich(イミッチ)という無料のソフトで、Google Photosはかなり満足度高く置き換えられました。
スマホの写真が自動で自宅サーバーにバックアップされ、顔や物などで検索もでき、見た目もGoogle Photosそっくりです。
容量は自分のサーバーのディスク次第になります。

この記事では、私が実際に動かしている4つのコンテナのイメージ名・バージョン・ポート・環境変数と、コピーして使える構成ファイルまで具体的に書きます。
後半には、面倒な作業を任せるためのClaude Codeへの指示書も載せておきます。

前提として、Ubuntuを入れてCasaOS(Dockerのアプリを画面から管理できる仕組み)まで用意した自宅サーバーの土台があるものとして進めます。
外からのアクセスにはTailscaleを使うので、そちらも入っている前提です。

Immichとは何か

Immichは、自分のサーバーの上に「自分専用のGoogle Photos」を立てられる、無料のオープンソースソフトです。

特徴は、なんといってもGoogle Photosとの使い心地の近さです。
スマホに専用アプリを入れておくと、撮った写真や動画が自動で自宅サーバーにバックアップされます。
タイムライン表示・アルバム作成・共有といった機能も一通りそろっています。
さらに後で説明しますが、AI(人工知能)による「顔での検索」「写っているもので検索」までできます。

そして大事なのは、写真の実体が自分の家のサーバーのディスクに保存されるという点です。
思い出の写真を、よその会社のサーバーではなく自分の手元に置いておけます。

Google Photosとの違い

ふだん使っているGoogle Photosと、自前のImmichの違いを整理します。

  • 保存場所:Google Photosはよその会社のサーバー、Immichは自分の家のサーバーです。
  • 容量:Google Photosはプランで上限が決まっています。Immichは自分のサーバーのディスクの空きが上限です。写真は意外と容量を食うので、ディスクには余裕を持たせておくのが大事です。私の環境では、写真の実データはすでに200GBを超えています。
  • 料金:Google Photosは容量課金、Immichはソフト自体が無料で、電気代くらいです。
  • AIの賢さ:Google PhotosのAI検索はとても優秀です。Immichも顔や物での検索ができますが、後述のとおり、家庭用サーバーで動かす分には解析に少し時間がかかります。

Immichは4つの部品でできている

同じ自宅サーバーで動かしているSyncthingMinifluxより、Immichはもう一段本格的で、4つの部品(コンテナ)が連携して動きます。
それぞれの正体・実際に使っているイメージ・役割を、私の環境の値で並べると次のとおりです。

Immichを構成する4つのコンテナと、それぞれのイメージ・役割

この4つは、Dockerの中で immich という1つの専用ネットワーク(Dockerが自動で割り当てる内部プライベート範囲)にまとまっていて、本体・ML・DB・Redisがコンテナ名で互いを呼び合って動いています。
だから本体は、DBやMLの場所をサーバーのIPで指定する必要がなく、immich-postgresimmich-redis といった名前でそのまま接続できます。

注目してほしいのは2つです。

ひとつは、データベースがただのPostgreSQLではなく tensorchord/pgvecto-rs、つまり「ベクトル検索」ができる拡張を載せたPostgreSQLだということ。
これがImmichのAI検索の心臓部です(仕組みは後述します)。
ふつうのPostgreSQLでもImmich自体は起動しますが、「海で撮った写真」のような自然文での検索や顔のグループ化が、このベクトル検索拡張に支えられています。

もうひとつは、AIの頭脳(ML)を、専用の高性能パーツ(GPU)ではなくふつうのCPUで推論する設定(DEVICE=cpu)にしている点です。
GPUの無い中古機でもAI検索が成立する代わりに、解析に時間がかかる、というトレードオフを承知のうえで選んでいます。
GPUを積んでいないうちの環境ではこれが現実解で、「中古機でもImmichのAI検索はちゃんと動く」という、この記事でいちばん伝えたい実例になっています。

これら4つをまとめて起動する設定は、CasaOSやサーバーに入れたClaude Codeが面倒を見てくれるので、一つずつ手で組み立てる必要はありません。
ただ「4つで1セット」「DBはベクトル検索拡張入り」「MLはCPU」とだけ知っておくと、後の構成ファイルやトラブル対処がぐっと読みやすくなります。

ステップ1:サーバーにImmichを入れる

CasaOSのアプリ管理画面からでも入れられますが、ここでは何を設定しているかが分かる構成ファイル(docker compose)の要点で示します。
中身が分かれば、CasaOSの画面で同じ値を入れるのも、Claude Codeに作ってもらうのも簡単になります。
私が実際に動かしている4コンテナの、効いてくる部分を抜き出すと次の形です。

services:
  immich-server:
    image: altran1502/immich-server:v2.5.3
    ports:
      - "2283:2283"                     # 家の中では http://(サーバーのIP):2283 で開く
    volumes:
      - /DATA/Gallery/immich:/usr/src/app/upload   # 写真の実体はここに貯まる
    environment:
      - DB_HOSTNAME=immich-postgres     # DBはコンテナ名で呼ぶ
      - DB_USERNAME=postgres
      - DB_DATABASE_NAME=immich
      - REDIS_HOSTNAME=immich-redis
    depends_on:
      - immich-postgres
      - immich-redis
    restart: unless-stopped

  immich-machine-learning:
    image: altran1502/immich-machine-learning:v2.5.3
    environment:
      - DEVICE=cpu                      # GPUを使わずCPUで推論する
    restart: unless-stopped

  immich-postgres:
    image: tensorchord/pgvecto-rs:pg14-v0.2.0   # ベクトル検索拡張入りPostgreSQL
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_DB=immich
      - POSTGRES_PASSWORD=your_db_password
    restart: unless-stopped

  immich-redis:
    image: redis:6.2-alpine
    restart: unless-stopped

いちばん大事なのは、写真の実体をサーバーのどこに置くかです。
本体の volumes にある /DATA/Gallery/immich:/usr/src/app/upload がそれで、左側がサーバー上の実フォルダ、右側がコンテナの中でImmichが写真を書き込む場所(/usr/src/app/upload)です。
写真は量が多くなるので、左側は容量に余裕のあるデータ用ディスク、つまり /DATA の下を指定します。
スマホから上がってきた写真は、すべてこの /DATA/Gallery/immich に貯まり、これがバックアップの対象そのものになります。

残りの値も、効いてくる順に説明します。

  • ports: "2283:2283":Immich本体は 2283 番で待っています。家の中からは http://(サーバーのIP):2283 でアクセスします。MinifluxやNextcloudと番号が重ならないよう、ここはImmich標準の 2283 をそのまま使っています。
  • DB_HOSTNAME=immich-postgres / REDIS_HOSTNAME=immich-redis:本体がDBとRedisを探す宛先です。サーバーのIPではなく、同じ immich ネットワークにいる相手のコンテナ名を書くだけでつながります。
  • DB_USERNAME=postgres / DB_DATABASE_NAME=immich:本体が接続するDBのユーザー名とデータベース名で、下のDB側(POSTGRES_USER / POSTGRES_DB)と揃えます。パスワード(POSTGRES_PASSWORD)も本体側の指定と必ず一致させます。
  • DEVICE=cpu:前の見出しで触れた、ML(AIの頭脳)をCPUで動かすための指定です。GPUを積んだ環境なら別の値にできますが、うちは中古機なのでCPUで回しています。
  • イメージのバージョンを固定する:4つとも :v2.5.3 のようにバージョンを明記しています。:latest(最新版を勝手に取る指定)にしておくと、再起動のたびに本体だけ新しくなってDBの想定と食い違う、といった事故が起きやすいので、4つのバージョンを揃えて固定するのがおすすめです。

Immichは4つの部品が連携する分、最初の起動に少し時間がかかります(特にDBが起動しきるまで本体は待ちます)。
起動が終わると、ブラウザでサーバーのアドレスに 2283 番を付けてアクセスすると、Immichの画面が開きます。
私の環境では、この画面も普段は外部に直接公開せず、Tailscaleの専用ネットワーク経由でアクセスしています(外からのアクセス方法は後の見出しでまとめます)。

ひとつ補足です。
DBの中身(写真の情報やAIが出した特徴の数値)は、写真の実体を置く /DATA/Gallery/immich とは別に、Docker側の保存領域に入ります。
「じゃあバックアップから漏れるのでは」と思うかもしれませんが、データベースはファイルを単純コピーすると壊れることがあるため、バックアップの回pg_dumpall 系の専用コマンドで安全に書き出して、/DATA 配下のバックアップに含めます。
写真の実体(/DATA/Gallery/immich)とDBダンプの両方をそろえて初めて、Immichは丸ごと復元できます。

ステップ2:最初のアカウントを作る

Immichの画面を初めて開くと、管理者アカウントを作る案内が出ます。
ここで決めたメールアドレスとパスワードが、自分のImmichの入り口になります。
アカウントを作ると、まだ写真が無い空っぽのタイムラインが表示されます。
次のステップでスマホをつなぐと、ここに写真が流れ込んできます。

ステップ3:スマホから写真を自動バックアップする

スマホにImmichのアプリ(iPhoneでもAndroidでも用意されています)を入れて、自分のサーバーのアドレスと、さきほど作ったアカウントを登録します。
そのうえで「自動バックアップ」をオンにすると、スマホで撮った写真や動画が、自動的に自宅サーバーへアップロードされるようになります。
Google Photosの自動バックアップとまったく同じ感覚です。

最初は今までの写真をすべて送るので時間がかかりますが、一度追いついてしまえば、あとは撮るたびに少しずつアップロードされていきます。
外出先からでも、後述のTailscaleをオンにしておけば安全にバックアップできます。

ステップ4:顔・物体・キーワードで検索する(AI検索の仕組み)

Immichの目玉が、AIによる検索です。
ここは仕組みを知ると面白いので、少し詳しく説明します。

写真がアップロードされると、「AIの頭脳」の部品が、その画像を解析して「特徴」を数百個の数字の並び(ベクトル)に変換します。
たとえば「夕焼けの海辺」の写真も、「犬が芝生で走っている」写真も、それぞれ内容を表す数字の並びに置き換えられ、データベースに保存されます。

検索するときは、この数字の並び同士の「近さ」を比べます。

  • 物・シーンでの検索:「海」と打つと、その言葉も同じように数字の並びに変換され、それに近い特徴を持つ写真が引き出されます。アルバムを手で整理しなくても、「料理」「犬」「雪」といった言葉で目的の写真にたどり着けるのは、この仕組みのおかげです。
  • 顔での検索:写真の中から顔を見つけ、その顔の特徴も数字の並びにします。同じ人物は数字の並びが近くなるので、「この人が写っている写真」をまとめて集められます。

この「数字の並びの近さで似たものを探す」のがベクトル類似検索です。
ふつうのデータベースは「日付がこの範囲」「タイトルにこの語を含む」といった条件で探すのは得意でも、「この数百個の数字の並びに近いものを上から順に」という探し方は不得手です。
そこを担うのが、ステップ1でDBに選んだ tensorchord/pgvecto-rs、つまりベクトル検索の拡張を載せたPostgreSQLです。
Immichが「ふつうのPostgresではなく、わざわざこの拡張入りを指定する」のは、まさにこの近さ検索をDB側で高速に行うためです。

ひとつ正直にお伝えすると、この解析(ベクトル化)はGPUではなく、ステップ1で DEVICE=cpu に設定したとおりCPUで行っています。
そのため、写真を上げてすぐには検索に出てこないことがあります。
サーバーが空いている時間に少しずつ解析を進めるので、しばらく待てばちゃんと検索できるようになります。
枚数が多いほど初回の解析には時間がかかりますが、一度追いついてしまえば、日々の数枚は気になりません。

アップロード後に裏で走る処理は、実はこのベクトル化だけではありません。
一覧表示を速くするためのサムネイル(縮小画像)やプレビューの生成、動画の変換なども順番待ちで処理されます。
これらの「裏の作業」は、設定でどれくらい並行して走らせるか(同時実行数)を調整できます。
中古機では欲張って並行数を上げると逆にもたつくので、私は控えめにして、夜のあいだに少しずつ片付けてもらう形にしています。
最初に大量の写真を入れた直後だけCPUがしばらく忙しくなりますが、追いついてしまえば日々の数枚は気になりません。

外からアクセスするには(Tailscale経由)

Immichは、家の中だけでなく外出先でも使えてこそ本領を発揮します。
私の設定では、Immichの画面(2283 番)をインターネットに直接公開せず、Tailscaleの回で決めたUFW(ファイアウォール)の方針どおり、2283 番の入り口は自宅LANと自分のTailscale端末からだけ許可しています。
具体的には、こんな2行を入れているイメージです。

sudo ufw allow from <自宅LANの範囲> to any port 2283 proto tcp     # 自宅LANから
sudo ufw allow from <Tailscaleの範囲> to any port 2283 proto tcp  # Tailscaleの端末から

<自宅LANの範囲> には自宅ネットワークの範囲(ご家庭により異なります。土台を作る回で調べた値)を、<Tailscaleの範囲> にはTailscaleが各端末に割り当てる専用アドレスの範囲を入れます。
こうしておくと、次のように使い分けられます。

  • 家の中から:http://(サーバーのIP):2283 でアクセスします。
  • 外出先から:スマホやパソコンでTailscaleをオンにしたうえで、「サーバー名+2283」(たとえば myserver:2283 の形)でアクセスします。

スマホのImmichアプリの接続先も、同じくTailscaleで付けたサーバー名と 2283 番を登録しておきます。
こうしておくと、家でも外でも設定を変えずに同じまま使えて、外出先で撮った写真も、Tailscaleがオンになっていれば自動でバックアップされていきます。
写真という、とりわけ人に見られたくないデータだからこそ、「インターネットに入り口を開けず、自分の端末からだけ届く」というTailscaleの仕組みは安心感が大きいです。

Claude Codeへの指示書

ここまでの構築を実際にやってもらうための、Claude Codeへの指示書です。
サーバーに入れたClaude Codeにこれを渡せば、サーバー側の準備を進めてくれます。
本文で出した値(4コンテナのイメージ・ポート 2283DEVICE=cpupgvecto-rs・保存先)を、そのまま方針として渡しています。
スマホアプリの導入と自動バックアップの設定は、最後に自分で行います。

あなたはこのUbuntuサーバーの構築を手伝うエンジニアです。
私は非エンジニアなので、専門用語は噛み砕いて、操作の前には何をするか一言説明してください。

目的:Google Photosの代わりに、Immichで写真を自宅サーバーに自動バックアップし、
顔や物で検索できるようにしたい。

次の手順で進めてください。
1. docker compose で、Immichの4つのコンテナを組にして起動する。
   - immich-server(altran1502/immich-server:v2.5.3)を 2283:2283 で公開。
   - immich-machine-learning(altran1502/immich-machine-learning:v2.5.3)は
     GPUが無いので DEVICE=cpu で動かす。
   - DBは tensorchord/pgvecto-rs:pg14-v0.2.0(ベクトル検索拡張入り)を使い、
     DB_USERNAME=postgres / DB_DATABASE_NAME=immich に揃える。
   - Redisは redis:6.2-alpine。4つは同じネットワークでコンテナ名で接続する。
   - イメージのバージョンは latest にせず、上の v2.5.3 等で固定する。
2. 写真の実体の保存先は、容量に余裕のある /DATA/Gallery/immich にして、
   本体の /usr/src/app/upload にマウントすること。
3. ブラウザでImmichの初期設定画面を開く方法(アドレスと2283番)を教えてほしい。
4. UFWで、2283番を自宅LANとTailscaleの範囲からだけ許可する。
   インターネットには直接公開しない。
5. うまく起動しないときは、どのコンテナで止まっているかログを見て調べて直してほしい
   (特にDBの起動待ち)。
各ステップで、何をしたか・次に私が手元の端末で何をすればいいかを説明してください。

「4コンテナを同じネットワークで」「MLは DEVICE=cpu」「DBは pgvecto-rs」「写真の実体は /DATA/Gallery/immich」「バージョン固定」という方針を伝えておくのがコツです。

動作の重さと容量について

実際に使う前に知っておくとよい点です。

  • 写真は容量を食う:写真や動画は書類よりずっと容量を使います。実体は /DATA/Gallery/immich に貯まり続けるので、このフォルダがあるディスクの空きには余裕を持たせ、ときどき確認しておきましょう。
  • AI解析はのんびり進む:DEVICE=cpu でMLを回しているぶん、上で説明したベクトル化の解析には時間がかかります。急がず、サーバーに任せておけば大丈夫です。最初に大量の写真をまとめて入れた直後は、全部の解析が終わるまでしばらくかかる(枚数とサーバーの性能しだい)と見ておくと気が楽です。
  • バックアップは必須:大切な思い出を自分のサーバーに置くなら、別のディスクへのバックアップが欠かせません。Immichは写真の実体(/DATA/Gallery/immich)だけでなくデータベースも一緒に守る必要があり、しかもDBはファイル直コピーではなく専用ダンプで書き出す必要があるので、外付けHDDへ自動バックアップする仕組みのほうでまとめて扱っています。

よくあるトラブルと対処

つまずきやすい点をQ&Aでまとめておきます。

Q. なかなか起動しない、画面が開かない
Immichは4コンテナある分、最初の起動に時間がかかります。
本体(immich-server)は、DB(immich-postgres)が起動しきる前に立ち上がると接続に失敗するので、少し待ってから本体を再起動すると直ることが多いです。
それでも開かないときは「Immichのどのコンテナで止まっているかログを見て」とClaude Codeに頼むと、docker ps でどのコンテナが落ちているか、docker logs immich-server でどのエラーかを調べてくれます。
DB_USERNAME / DB_DATABASE_NAME がDB側の POSTGRES_USER / POSTGRES_DB と食い違っていると必ず失敗するので、まずここを合わせます。

Q. 画面は開くのに、AI検索(顔・物・キーワード)だけ効かない
このときは、DBがベクトル検索拡張入りの tensorchord/pgvecto-rs になっているか、MLコンテナ(immich-machine-learning)がちゃんと動いているかを疑います。
DBをうっかりふつうの postgres イメージにしているとベクトル検索が成立しません。
MLが落ちていれば写真の特徴が作られないので、いつまでも検索に出てきません。
docker ps で両方が動いているかを見るのが先決です。

Q. スマホから自動バックアップされない
アプリの「自動バックアップ」がオンか、スマホのバッテリー最適化でアプリが眠らされていないかを確認しましょう。
写真をたくさん送る初回は、Wi-Fiにつないでしばらく放置しておくのがおすすめです。
送った写真は、サーバー側の /DATA/Gallery/immich に貯まっていくので、ここのフォルダにファイルが増えていれば取り込みは効いています。

Q. 検索しても写真が出てこない
アップロード直後は、まだAIの解析(ベクトル化)が終わっていないことが多いです。
前述のとおりMLを DEVICE=cpu で回しているので、枚数が多いと初回はサーバーが空いている時間に少しずつ進みます。
一日ほど待ってからもう一度試してみてください。

Q. 外出先からアプリでつながらない
まず、スマホのTailscaleがオンかを確認してください。
次に、アプリに登録したサーバーの場所が、Tailscaleで付けたサーバー名と 2283になっているかを見直します。
家の中では使えるのに外だけつながらない場合は、ほぼTailscaleのオン・オフか、UFWで 2283 番をTailscaleの範囲から許可し忘れているかのどちらかです。

まとめ

いかがでしたか。
今回は、Google Photosを自前のImmichで置き換える方法を紹介しました。

振り返ると、

  1. Immichは「自分専用のGoogle Photos」を立てられる無料ソフト
  2. 本体(immich-server)・AIの頭脳(immich-machine-learning)・DB(pgvecto-rs)・Redisの4コンテナを、同じネットワークでコンテナ名で連携させて動かす
  3. 写真の実体は /DATA/Gallery/immich、本体のポートは 2283、MLは DEVICE=cpu、と構成ファイルの値で動きを決める
  4. AIは画像を数字の並び(ベクトル)に変換し、その近さで顔・物・キーワード検索を実現する。これをベクトル検索拡張入りのDB(pgvecto-rs)が支える(CPU推論なので少しのんびり)
  5. スマホアプリの自動バックアップをオンにすればGoogle Photosと同じ感覚で使え、外からはTailscale経由(2283 番を自宅LANとTailscaleだけ許可)でアクセスする

という内容でした。

思い出の写真を自分の手元に置けて、容量を気にしなくてよくなったのは、かなり大きな満足感がありました。
古い中古機でもここまで動くので、写真の保存場所に悩んでいる方は、ぜひ一度検討してみてください。

なお、書類やファイルのほうをGoogle Driveから移したい場合は、同じサーバーの上でNextcloudを動かす方法を別の記事にまとめています。

この記事が誰かの役に立てばうれしいです。