GCPでMisskey鯖構築ガイド

## 概要
Misskeyが話題なので、せっかくだから自分でも鯖を建ててみよう！
ついでに最近ハマってるラブライブの話題を語れる場にしようと思います。

## 前提
- Misskeyは執筆時点での最新版 v13.10.2 (2023/03/23)
    - 構築方法は、一番簡単そうな Docker Composeを利用する方法で。
- サーバー環境はGCP上に構築する
    - 無料枠があるので、AWSではなくGCPを選択(結局無料枠使わなかったけど)
    - VM: e2-small (後述しますが、e2-microだと動きが遅いので)
    - OS: Debian系ならOK ( Debian 11 )
- CDNは外部サービス(Cloudflareなど)を利用する予定
- 独自ドメインは事前に用意しておく(Google Domainsを利用した)
    - ちなみに建てた鯖は https://misskey.lovelive.net/ です。
- とにかく動くようにするのが大事。細かいことは後からでもなんとかなる

## 前準備
1. 独自ドメインの取得([Google Domains](https://domains.google.com/))
    - 公式サイトから「新しいドメインを探す」の手順通りに進めればOK
    - Googleアカウント持ってるなら、紐付いてる支払い方法で決済出来ます
1. SSH公開鍵の生成
    `$ ssh-keygen -t rsa -b 4096 -C <UserName>`
    // 3回Enter押して生成(デフォルト)
    // 鍵のファイル名を変更したい場合は、1回目のEnter押す前にフルパスでファイル名を入力
    ```
    $ ssh-keygen -t rsa -b 4096 -C <UserName>`
    Enter file in which to save the key (/Users/ユーザー名/.ssh/id_rsa): <--鍵の保存先 
    Enter passphrase (empty for no passphrase):  <-- パスフレーズを入力（任意）
    Enter same passphrase again:  <-- もう一度、パスフレーズを入力（任意）
    ```
    デフォルトだと、`.ssh/id_rsa`と`.ssh/id_rsa.pub`の2ファイルが作られます。

## 手順
[無料枠](https://cloud.google.com/free/docs/free-cloud-features?hl=ja)でも作れるけど動作が不安定なので、複数人利用前提ならsmall以上が良い
1. GCPにVMインスタンス生成
    1. どうせ有料枠で作るならということで、東京リージョンを選択
        ![スクリーンショット 2023-03-23 13.29.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186422/0f24cfd2-bed1-1be2-e951-2940db1b3caa.png)

    1. マシン構成は `e2-small`を選択
        ![スクリーンショット 2023-03-23 13.30.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186422/d591833f-4a41-4d1a-b86c-57c933af5bf5.png)
    1. ブートディスクはサイズを10 → 30 に変更(標準永続ディスクなら、30GBまでは無料枠)
        ![スクリーンショット 2023-03-23 13.31.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186422/8ce17c3b-9a5a-0bfb-2a59-a5fdb2cd4070.png)
    1. HTTP、HTTPSは有効に
        ![スクリーンショット 2023-03-23 13.31.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186422/203fc0e0-3d4a-a6c1-cb39-92a2e8cd7c46.png)
    1. 保存
    ※余談ですが、上記構成だと月間利用料予測はこんな感じ・・・
        ![スクリーンショット 2023-03-23 13.32.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186422/bf59c761-2b24-ed12-16af-efb892084a61.png)

1. SSH接続
    1. 作成しておいた公開鍵をGCEに登録
        `$ cat ~/.ssh/id_rsa.pub` で表示された内容をまるっとコピー
        インスタンスの詳細画面->「編集」->「SSH認証鍵」に追加する
        「項目を追加」を押して、SSH認証鍵3に追加した
        ![スクリーンショット 2023-03-25 13.17.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186422/e0a018b0-439b-e2c6-a494-4367be03ff1c.png)

    1. terminalでVMに接続
        `$ ssh <UserName>@<GCE_IPAddress> -i ~/.ssh/id_rsa`
1. [swap領域作成](https://qiita.com/wqwq/items/38f5dfd84e7bc4f1631e)
    1. swap領域を生成(サイズは用途に合わせて変更)
        `$ sudo dd if=/dev/zero of=/swapfile bs=1M count=2048`
        `$ sudo chmod 600 /swapfile`
        `$ sudo mkswap /swapfile`
        `$ sudo swapon /swapfile`

    1. 起動時に有効になるように以下の内容を追記して保存
        `$ sudo vi /etc/fstab`
        `/swapfile swap swap defaults 0 0`
1. [dockerインストール](https://docs.docker.com/engine/install/debian/)
    公式手順`Install using the repository`通りに
1. nginxの準備
    Misskeyはリバースプロキシで接続する仕組みのため、先にnginxを用意しておく
    1. nginx用のフォルダを作成(以降、作業フォルダとする)
        `$ mkdir nginx`
        `$ cd nginx`
    1. docker-compose.ymlを作成し、以下の通り編集する
        `vi docker-compose.yml`
        ```docker-compose.yml
        version: "3"
        services:
          nginx-proxy:
            image: jwilder/nginx-proxy
            container_name: nginx-proxy
            ports:
              - "80:80"
              - "443:443"
            volumes:
              - /var/run/docker.sock:/tmp/docker.sock:ro
              - ./certs:/etc/nginx/certs:ro
              - /etc/nginx/vhost.d
              - /usr/share/nginx/html
            restart: always
            networks:
              - external_network

          letsencrypt:
            image: jrcs/letsencrypt-nginx-proxy-companion
            container_name: letsencrypt
            volumes:
              - /var/run/docker.sock:/var/run/docker.sock:ro
              - ./certs:/etc/nginx/certs:rw
            volumes_from:
              - nginx-proxy
            restart: always
            networks:
              - external_network

        networks:
          external_network:
            external: true
        ```
    一旦ここまで準備したら、一度ホームに戻る
    `$ cd ~/`
1. Misskeyの準備
    - [公式手順(Docker Composeを使ったMisskey構築)](https://misskey-hub.net/docs/install/docker.html)の通りにコマンド流す
        - envファイル編集はviコマンドで
            `vi .config/default.yml`
        - 使うviコマンド
            - i ・・・ 挿入(編集)モード
            - ESCキー ・・・ 編集モードを抜ける
            - :wq ・・・ 編集内容を保存してvi終了

    1. リポジトリの取得
        `$ git clone -b master https://github.com/misskey-dev/misskey.git`
        `$ cd misskey`
        `$ git checkout master`
    1. 設定
        1. 設定ファルの作成
            `$ cp .config/docker_example.yml .config/default.yml`
            `$ cp .config/docker_example.env .config/docker.env`
            `$ cp ./docker-compose.yml.example ./docker-compose.yml`
        1. default.ymlの編集
            `$ vi .config/default.yml`
            長いので、変更点のみ抜粋
                - HostURLの変更
                - db(PostgreSQL)のid/pw
            ```default.yml
              # Final accessible URL seen by a user.
              url: https://example.tld/  //取得した独自ドメインに変更

                〜中略〜

              # The port that your Misskey server should listen on.
              port: 3000　　//特に問題なければ変更なし

              #   ┌──────────────────────────┐
              #───┘ PostgreSQL configuration └────────────────────────────────

              db:
                host: localhost
                port: 5432

                # Database name
                db: misskey　　//好きな名前に

                # Auth
                user: example-misskey-user　　//ご自由に
                pass: example-misskey-pass　　//ご自由に
            ```
        1. docker.envの編集
            先程の`default.yml`で設定したdb内容を反映する
            `$ vi .config/docker.env`
            ```docker.env
            # db settings
            POSTGRES_PASSWORD=example-misskey-pass
            POSTGRES_USER=example-misskey-user
            POSTGRES_DB=misskey
            ```
        1. docker-compose.ymlの編集
            - 公式ではbuildになってるが、image利用に変更している
            - LetsEncryptの設定を追加
                - `example.tld`は自身の独自ドメインに変更する
                - `example@example.com`も自分のメールアドレスに(外部に公開されません)

            `$ vi docker-compose.yml`
            ```docker-compose.yml
            version: "3"

            services:
              web:
                image: misskey/misskey:latest
                restart: always
                links:
                  - db
                  - redis
            #      - es
                depends_on:
                  db:
                    condition: service_healthy
                  redis:
                    condition: service_healthy
                ports:
                  - "3000:3000"
                networks:
                  - internal_network
                  - external_network
                volumes:
                  - ./files:/misskey/files
                  - ./.config:/misskey/.config:ro
                environment:
                  VIRTUAL_HOST: example.tld
                  VIRTUAL_POST: 3000
                  LETSENCRYPT_HOST: example.tld
                  LETSENCRYPT_EMAIL: example@example.com

              redis:
                restart: always
                image: redis:7-alpine
                networks:
                  - internal_network
                volumes:
                  - ./redis:/data
                healthcheck:
                  test: "redis-cli ping"
                  interval: 5s
                  retries: 20

              db:
                restart: always
                image: postgres:15-alpine
                networks:
                  - internal_network
                env_file:
                  - .config/docker.env
                volumes:
                  - ./db:/var/lib/postgresql/data
                healthcheck:
                  test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
                  interval: 5s
                  retries: 20

            #  es:
            #    restart: always
            #    image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.4.2
            #    environment:
            #      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
            #      - "TAKE_FILE_OWNERSHIP=111"
            #    networks:
            #      - internal_network
            #    volumes:
            #      - ./elasticsearch:/usr/share/elasticsearch/data

            networks:
              internal_network:
                internal: true
              external_network:
                external: true
            ```
        一旦ここまで
1. docker network の作成
    nginxとmisskeyのexternal_networkをつなぐ
    `$ cd ~/`
    `$ sudo docker network create --driver bridge external_network`
    これで、Webからのアクセスをnginxがリバースプロキシとして働いてMisskeyに接続できるようになる

1. nginxの起動
    `$ cd ~/nginx`
    `$ sudo docker compose up -d`

1. misskeyの起動
    `$ cd ~/misskey`
    `$ sudo docker compose up -d`
    filesの権限を変更する(ファイルアップロードエラーの回避)
    `$ sudo chmod 777 files`
1. Misskeyサーバにアクセス( https://example.tld )
    もしエラー(502など)が出る場合は、一度nginxを再起動するとうまくいくかも

## 積み残し(後日書きます)
1. CDN(Cloudflare)の設定
    Misskeyをキャッシュする
1. Mailを使えるようにする
    [MailGun](https://qiita.com/u1-liquid/items/9aadd3a057c5629fa79f)
1. オブジェクトストレージの設定
    [Cloudflare r2を使う](https://qiita.com/hihumikan/items/1f692f3bd5516820e0ec)


## まとめ(感想)
- 最初はdocker buildでやろうとしたら、マシンパワーが足りずにひたすらハマりました
- 公式サイトの手順だけだと全部を説明してるわけではないので、色々試行錯誤したのは(今となっては)楽しかったです
- Misskey構築はある程度分かってないと難しいと言われますが、本当にそうだったｗ
- 色々気になるところはあるけど、これから鯖運営頑張ってみたいと思います

というわけで、興味を持たれた方はぜひ覗いてみてください