【immich】Google Photoを卒業した話

SCSK永見です。

Google Photo、便利ですよね。Androidユーザとして長年重宝してきました。

しかし、重宝しすぎてストレージが足りなくなりました。ひとつ上のプランにするのもなぁ、、と調べているうちに、Google Photo ライクなメディア管理OSS、Immichを見つけました。

半年ほど利用し、大変重宝しているので、皆様に構築手順とともにご紹介します。

※本記事では、Immichソフトウェアを紹介・説明する目的のためにのみロゴを使用しています。

そもそもImmichとは

Immichとは、セルフホスト型のメディア管理ソフトウェアです。

Immich
Self-hosted photo and video management solution. Easily back up, organize, and manage your photos on your own server. Im...

見た目も使い勝手もGoogle Photoそっくりで、接続できれば使い方は説明も不要なくらいです。

興味があればデモサイトをぜひご覧ください。

https://demo.immich.app/

何が嬉しいの?

メリットとしては、データのガバナンスやプライバシーをコントロールできることです。

SaaSサービスは便利ですが、突然「サービス終了するのでデータを全削除します」なんてこともあり得るわけです。これは極端な例にしても「規約違反により利用が制限されました」などは起こりうる範疇と思います。

また、軽く流し読みした利用規約に「AIの学習に使います」なんてことが書いてあったら、知らず知らずのうちにプライベートな情報が学習されているかもしれません。そういった事態を避けることができます。

また、後述しますが自宅サーバ上に構築すれば、コストをより抑えることもできます。

前提

今回はEC2Instance、Ubuntu24.04を使います。Dockerを使って構築します。

おそらくこの記事を参照している人は自宅サーバ上に構築する方が多いと思います。理想はデータ用のボリュームを1つ追加することですが、今回はボリューム1つで構築します。

事前準備

本筋ではないのでCfnテンプレートを掲載するのみとします。EC2を1台作成するだけのシンプルなCfnテンプレートです。

AWSTemplateFormatVersion: "2010-09-09"

Parameters:
  ResourcePrefix:
    Type: String

  AllowedHttpCidr:
    Type: String
    Default: 0.0.0.0/0

  CostTag:
    Type: String

  LatestUbuntuAmi:
    Type: AWS::SSM::Parameter::Value
    Default: /aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id

Resources:

  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub "${ResourcePrefix}-vpc"
        - Key: Cost
          Value: !Ref CostTag

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${ResourcePrefix}-igw"
        - Key: Cost
          Value: !Ref CostTag

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      MapPublicIpOnLaunch: true
      AvailabilityZone: !Select [ 0, !GetAZs "" ]
      Tags:
        - Key: Name
          Value: !Sub "${ResourcePrefix}-public-subnet"
        - Key: Cost
          Value: !Ref CostTag

  RouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${ResourcePrefix}-rt"
        - Key: Cost
          Value: !Ref CostTag

  DefaultRoute:
    Type: AWS::EC2::Route
    DependsOn: AttachGateway
    Properties:
      RouteTableId: !Ref RouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  SubnetRouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnet
      RouteTableId: !Ref RouteTable

  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTP
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 2283
          ToPort: 2283
          CidrIp: !Ref AllowedHttpCidr
      SecurityGroupEgress:
        - IpProtocol: -1
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub "${ResourcePrefix}-sg"
        - Key: Cost
          Value: !Ref CostTag

  EC2Role:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      Tags:
        - Key: Cost
          Value: !Ref CostTag

  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles:
        - !Ref EC2Role

  EC2Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t3.large
      ImageId: !Ref LatestUbuntuAmi
      SubnetId: !Ref PublicSubnet
      SecurityGroupIds:
        - !Ref SecurityGroup
      IamInstanceProfile: !Ref InstanceProfile
      BlockDeviceMappings:
        - DeviceName: /dev/sda1
          Ebs:
            VolumeSize: 100
            VolumeType: gp3
      PropagateTagsToVolumeOnCreation: true
      Tags:
        - Key: Cost
          Value: !Ref CostTag
        - Key: Name
          Value: !Sub "${ResourcePrefix}-ec2"

Outputs:
  InstanceId:
    Value: !Ref EC2Instance

  PublicIP:
    Value: !GetAtt EC2Instance.PublicIp

作成後はSSMセッションマネージャー等でSSH接続します。(再)接続後はsudo su ubuntuなどでユーザ切り替えるとよいでしょう。

構築手順

さて本題です。

EC2にSSHしたらまずはサーバ上の環境を整えます。パッケージの更新とタイムゾーンの更新をします。

sudo apt update
sudo apt upgrade -y

sudo timedatectl set-timezone Asia/Tokyo
sudo reboot

dockerのインストール

再度SSHし、dockerをインストールします。

参考:https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository

sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

sudo apt update

sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
docker --version
# Docker version 29.4.1, build 055a478 などと出力されればOK

現在使っているユーザをdockerグループに追加します。この作業は飛ばしても大丈夫ですが、その場合はdockerコマンドを実行する際にsudoしてください。

sudo gpasswd -a $USER docker
# Adding user ubuntu to group docker などと出力されればOK。ubuntuはSSHしているユーザ名。
sudo reboot

これでdockerを利用する準備ができました。

immichのインストール

まずはディレクトリを作ります。

APP_DIR=/opt/immich
sudo install -d -m 0755 -o ${USER} -g ${USER} ${APP_DIR}
ls -la ${APP_DIR}/..
# immich のディレクトリが作成されていればOK

設定ファイルなどを作成したディレクトリへ保存します。

cd ${APP_DIR} && wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
cd ${APP_DIR} && wget -O .env https://github.com/immich-app/immich/releases/latest/download/example.env
ls -a ${APP_DIR}
# .env docker-compose.yml の2ファイルが出力されればOK

.envファイルを更新します。

IMMICH_VERSIONは https://github.com/immich-app/immich のタグを確認し、任意の(こだわりがなければ最新の)バージョンを指定しましょう。執筆時点ではv2.7.5が最新だったので、これを使います。

vi ${APP_DIR}/.env
# Etc/UTC を Asia/Tokyo に書き換えて、# を削除する
# IMMICH_VERSION を v2.7.5に書き換える
# DB_PASSWORD を 任意のパスワードに書き換える

diff -u <(wget -qO- https://github.com/immich-app/immich/releases/latest/download/example.env) ${APP_DIR}/.env
# 以下のような差分があればOK
# -# TZ=Etc/UTC
# +TZ=Asia/Tokyo

# -IMMICH_VERSION=v2
# +IMMICH_VERSION=v2.7.5

# -DB_PASSWORD=postgres
# +DB_PASSWORD=指定したパスワード

それでは起動します。

cd ${APP_DIR} && docker compose up -d
# 4つのコンテナが立ち上がります。初回は少し時間がかかります。
docker ps -a
# 4つのコンテナすべてのSTATUSが (healthy) になっていればOK

アプリの初期設定

http://{IPアドレス}:2283 にブラウザからアクセスします。

管理者登録をします。

ログイン画面に遷移します。

ガイドに沿って初期設定を進めます。

ストレージテンプレートとは、ファイルシステム構成の設定だと理解してください。

「プリセット」プルダウンであらかじめ用意されたテンプレートを設定することもできますし、「テンプレート」テキストボックスで任意のテンプレートを設定することもできます。私はプリセットは使わず、以下のような設定をしています。

{{y}}/{{MM}}/{{y}}{{MM}}{{dd}}_{{filename}}

バックアップはとっておいた方がいいですよ のガイド画面です。ここで具体的な設定ができるわけではありません。
私は月一でS3 Glacierにミラーリングするスクリプトでバックアップを取っています。

モバイルアプリもインストールしておくとよいでしょう。Apple StoreやGoogle Play StoreでImmichと検索をかければすぐに出てきます。

設定ができました!もう後は直感的に理解できると思います。

料金

構築は簡単にできました。参考までランニングコストも計算してみましょう。

執筆時点ではGoogle Oneは100GBで290円、2TBで1450円、5TBで2900円とのことでした。

自宅サーバであれば電気代のみですが、もしEC2を利用したらどうでしょう。
必要スペックは6GB of RAM and 2 CPU cores、EC2のt3.largeであれば事足りそうです。

Quick start | Immich
Here is a quick, no-choices path to install Immich and take it for a test drive.

t3.largeの時間単価はUSD 0.1088、30日稼働すると$0.1088×24h×30日=$78.336、1ドル150円換算だと11,750円…。さらにこれにEBSやECSの料金が追加されます。AWSを利用するのはコストメリットはなさそうですね。

自宅サーバの場合は余っているミニPCなどを流用するのがおすすめです。仮に平均25Wの消費電力、1kWhあたり30円の電気代とした場合、540円(=0.025kW×30円/kWh×24h×30日)程度で運用できます。

まとめ

セルフホストできるメディア管理ソフトウェア、immichを紹介しました。

コストメリットも然り、データの統制にも気を使いたいですね。

この記事がみなさまの助けになれば幸いです。

参考ドキュメント

公式サイト https://immich.app/

github https://github.com/immich-app/immich

公式ドキュメント https://docs.immich.app/

×
タイトルとURLをコピーしました