Misskey(v12系)のインストール方法

## はじめに
自分の備忘録的に書いて行くので読みにくいところもありますがご了承ください。
動かなかったらコメント欄で報告をお願いします。
追記: わかりにくいところやバージョン更新で変わったところを修正しました(2022/11/10)

## 環境　
* OS:Ubuntu 22.04
* メモリ:2GB
* ストレージ:40GB
80/443ポートが開けてある前提で書いてます

## インストール
初めに必要なパッケージをインストールしていきます。
```bash
sudo apt update
sudo apt install postgresql redis-server nginx build-essential python3 certbot python3-certbot-nginx
```
### Postgresの設定

次にpostgresを設定して行きます。
```bash
sudo -u postgres psql
```
postgresでユーザーとデーターベースを作成します。
```sql
CREATE ROLE misskey LOGIN CREATEDB PASSWORD '$RANDOMPASSWORD';
CREATE DATABASE misskey OWNER misskey;
\q
```
### ユーザーの作成とnodejsの準備
rootユーザーでMisskeyを実行するのはよくないので、新しくユーザーを作成してログインします。
色々出てきますが、すべてEnterを押して飛ばしてください。
```bash
sudo adduser --disabled-password --disabled-login misskey
sudo -iu misskey
```
ログインしたのでnodenvをインストールしていきます。
```bash
git clone https://github.com/nodenv/nodenv.git ~/.nodenv
cd ~/.nodenv && src/configure && make -C src
```
そしてpathにnodenvを追加します。
```bash
vim ~/.bashrc
```
以下の内容を最終行に追記します。
```vim
export PATH="$HOME/.nodenv/bin:$PATH"
eval "$(nodenv init -)"
export NODE_OPTIONS=--max_old_space_size=4096
```
保存して一度抜けて入りなおします。
```bash
logout
sudo -iu misskey
```
node installができるようにプラグインを追加します。
```bash
mkdir -p "$(nodenv root)"/plugins
git clone https://github.com/nodenv/node-build.git "$(nodenv root)"/plugins/node-build
```
yarnをインストールできるようにするプラグインも追加します。
```bash
git clone https://github.com/pine/nodenv-yarn-install.git "$(nodenv root)/plugins/nodenv-yarn-install"
```
nodenvをupdateするためのプラグインも追加します。
```bash
git clone https://github.com/nodenv/nodenv-update.git "$(nodenv root)"/plugins/nodenv-update
```
### NodejsのインストールとMisskeyのビルド
まず本体をダウンロードします。
```bash
git clone https://github.com/misskey-dev/misskey
```
ダウンロードしたらMisskeyの本体が入ったディレクトリに入って、最新リリースをチェックアウトします。
```bash
cd ~/misskey
git checkout master
```
nodejsの推奨バージョンを確認します。
```bash
cat .node-version
```

自分の環境ではv16.15.0と出た(v12.119.0)ので以下のように入力します。
```
nodenv install 16.15.0
```
yarnで依存関係をインストールします。
アップデートした場合でも必ず実行してください。
```bash
yarn install
```
設定の雛形をコピーして編集します。
```bash
cp .config/example.yml .config/default.yml
vim .config/default.yml
```
変更する部分は主にこの辺りです。
```yaml
url: https://example.tld/
# 運営するときに使用するURLです
# 一度運営すると変更することはできません
db:
  host: localhost
  port: 5432
  db: misskey
  user: misskey
  pass: $RANDOMPASSWORD
  #ここにはpostgresのユーザーを作成したときに入力したパスワードを入力します
```

保存したらMisskeyをビルドしていきます。
* この動作はCPUとメモリを大量に消費するので、スペックが弱いと失敗します。
* 性能にもよりますが、5分以内に終わることが多いです。
* `NODE_ENV=production`は本番環境であることを表していて、開発やテストだけに必要な動作を行わないようになります。
```bash
NODE_ENV=production yarn build
```
ビルドが終わったら、データーベースを初期化します。
これが完了するとMisskeyを実行できます。
* 実行する手順は多いですが一瞬で実行されます。
* Misskeyがアップデートした場合は、yarn migrateでマイグレーションを行います。
マイグレーションは、最新のプログラムで必要な、データベースに対する変更を実行する手順です。
```bash
yarn run init
```
これでMisskeyユーザーでやる作業は終わりです。
```bash
logout
```
ログアウトします。
起動時に実行したいのでサービス化します。
```bash
sudo vim /etc/systemd/system/misskey.service
```
```service
[Unit]
Description=Misskey daemon

[Service]
Type=simple
User=misskey
ExecStart=/home/misskey/.nodenv/shims/yarn start
WorkingDirectory=/home/misskey/misskey
Environment="NODE_ENV=production"
TimeoutSec=60
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=misskey
Restart=always

[Install]
WantedBy=multi-user.target
```
保存したらデーモンを再読み込みして、OSが起動時にMisskeyが起動するようにし、Misskeyを起動します。
```bash
sudo systemctl daemon-reload
sudo systemctl enable misskey
sudo systemctl start misskey
```
停止する場合は`stop`、開始が`start`、再起動が`restart`です。

### nginxの設定
Misskeyは実行できましたがここまだとブラウザから見れない(正確には見れるけど、ポートを指定しないといけない)ので見れるようにしていきます。

まずはufwでhttp/https接続を許可します
```bash
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
```
そしてnginxの設定をしていきます。
```bash
sudo vim /etc/nginx/sites-available/misskey
```
以下の内容を貼り付けます。
`example.tld`はMisskeyの設定ファイルで設定したドメインにしてください。
```nginx
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=cache1:16m max_size=1g inactive=720m use_temp_path=off;

server {
    listen 80;
    listen [::]:80;
    server_name example.tld;

    # For SSL domain validation
    root /var/www/html;
    location /.well-known/acme-challenge/ { allow all; }
    location /.well-known/pki-validation/ { allow all; }
    location / { return 301 https://$server_name$request_uri; }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.tld;
    ssl_session_cache shared:ssl_session_cache:10m;

    # To use Let's Encrypt certificate
    #ssl_certificate     /etc/letsencrypt/live/example.tld/fullchain.pem;
    #ssl_certificate_key /etc/letsencrypt/live/example.tld/privkey.pem;

    # To use Debian/Ubuntu's self-signed certificate (For testing or before issuing a certificate)
    ssl_certificate     /etc/ssl/certs/ssl-cert-snakeoil.pem;
    ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

    # SSL protocol settings
    ssl_protocols TLSv1.2;
    ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:AES128-SHA;
    ssl_prefer_server_ciphers on;

    # Change to your upload limit
    client_max_body_size 80m;

    # Proxy to Node
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_http_version 1.1;
        proxy_redirect off;

        # If it's behind another reverse proxy or CDN, remove the following.
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;

        # For WebSocket
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        # Cache settings
        proxy_cache cache1;
        proxy_cache_lock on;
        proxy_cache_use_stale updating;
        add_header X-Cache $upstream_cache_status;
    }
}
```
設定を有効化します
```bash
cd /etc/nginx/sites-enabled
sudo ln -s ../sites-available/misskey
```
保存して設定が正しいかを検証します
```bash
sudo nginx -t
```
エラーなどが出ていなければnginxを再読み込みします
```bash
sudo nginx -s reload
```
SSL証明書を取得します
```bash
certbot --nginx
```
設定したドメインの番号を入力したら、エンターを押したらあとは自動で完了します。
ブラウザからアクセスしてアクセスできたら成功です。
お疲れ様でした。