chatbot-uiをnginxとpm2で立てる

作成日：2023/05/05

# どういう記事？
chatGPTのUI部分を模倣し、自分でchatGPTみたいなサイトをホストできる[chatbot-ui](https://github.com/mckaywrigley/chatbot-ui)を自宅のproxmoxの中のLXCに建てた時の備忘録。

# なぜchatbot-ui？
- ChatGPT4のAPI申請が通れば、有料プランに入らなくても従量課金でchatGPT4が使える
- APIの方が本家webUIの無料アカウントよりレスが早い気がする(本当かどうかは知らない)
- 入力データが学習に使われないので、さほど神経質にならずに使える

# 建て方
## step1. LXCを用意
#### ・LXCのセットアップ
今回はUbuntu22.04のコンテナで実行しました。
#### ・LXCのアップデート
以下のコマンドを順に実行しました。
```
apt update
apt upgrade -y
apt autoremove
apt clean
```

#### ・ユーザーの追加
次にroot以外のsudoが出来るユーザーを作りました。`<username>`は置き換えてください。
```
adduser <username> 
```
このユーザーをsudoに加えました。
```
usermod -aG sudo <username>
```
#### ・ufwの設定
Ubuntu Fire Wallの設定をしました。このサーバーはhttpで運用する予定なので、80番ポートを開けておきました。
```
ufw allow OpenSSH
ufw enable
ufw allow 80/tcp
```
#### ・gitのインストールと初期設定
まずはインストール
```
sudo apt install git
```
次に初期設定をしました。
```
git config --global init.defaultBranch main
git config --global user.name <username>
git config --global user.email <email>
```

#### ・エディターのインストール
自分はneovimを入れましたが、まぁここはお好みで....
正直な所、ここまでの設定はLXCを作ると大体するので、自分はシェルスクリプトを書いて一括でやっています(本当はcloud-initとか使うべきかもしれないが、わからない...)。

#### ・node.jsのバージョンを上げる
備忘録と言いながら順番が前後するのですが、この記事を読みながらやっている人がもしいればアレなので、先にnode.jsのバージョンを上げます。
自分の時は、nodeのバージョンがそのままだと古くて後々のビルドで失敗したからです。nodeのバージョンマネージャーであるnをインストールして、最新のnode(今回はv18.16.0)にしておきました。
nを用いたnode.jsのバージョン変更の方法は下記の記事を参照してください。
自分が8万回ぐらいお世話になっている記事です。

https://qiita.com/seibe/items/36cef7df85fe2cefa3ea

#### ・nginxのインストール
多分元から入っているけど、一応これをしました。
```
sudo apt install nginx
```

あとはLXCのMACアドレスをルータの固定IPのリストに入れるなどしました。

## step2. chatbot-uiをcloneしbuildする
以下でchatbot-uiをクローンしました。自分は最初に追加したsudoが出来るユーザーのホームディレクトリに入れました(`/home/<username>/`です)。
```
git clone https://github.com/mckaywrigley/chatbot-ui.git
```
ここからは上記githubレポに書いてある手順通りですが、一応書きます。
次にdependanciesをインストール。
```
npm i
```
`.env.local`ファイルを作り、中にOpenAIのAPI Keyを書きました。
```.env.local
OPENAI_API_KEY=YOUR_KEY
```
ビルドします(自分の時はここでエラーが出てnodeのバージョンアップが必要と判明した)。
```
npm run build
```
production modeで動くか見てみます。
```
npm run start
```
問題なさそうだったので、サーバーを止めてstep3へ。

## step3. pm2のインストールと設定
nodeのサーバー単体で使用していると、予期せぬエラーが発生した時、サーバーごと落ちてしまい、再度サーバーを起動する必要があります。それは大変なので、pm2で永続化しました。

以下でインストールしました。`sudo npm`はやらない方が良いらしいですが、プロセスをマネジメントする関係か、sudoを付けてインストールしないと、動きませんでした。
```
sudo npm install -g pm2
```
pm2を使ってnodeサーバーを永続化します。
```
pm2 start "npm run start" --name "chatbot-ui"
```
こんな画面が出れば多分成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327331/50e31fb7-a324-9feb-e8a5-024985811fff.png)

また、サーバが再起動した際に自動で立ち上がるようにしておきます。
```
pm2 startup
```
を実行すると、mp2自体をサーバの再起動時に起動するためのコマンドが表示されるので、それを実行します。

その後、
```
pm2 save
```
で現在起動しているプロセスを保存します。これで再起動後にも勝手に起動します。

## step4. Nginxの設定
#### ・ベーシック認証の設定
今回はページにベーシック認証をかけたいので、ベーシック認証のファイル`.htpasswd`を生成する`apache2-utils`を入れました。
```
sudo apt-get install apache2-utils
```
以下のコマンドで`.htpasswd`を生成しました。
```
sudo htpasswd -c /etc/nginx/.htpasswd <username>
```

#### ・nginxのconfigの作成
`/etc/nginx/sites-available/`に`chatbot-ui`というファイルを作成し、以下の内容を書き込みました。
```chatbot-ui
server {
    listen 80;
    server_name <your sever name>;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;

        auth_basic_user_file /etc/nginx/.htpasswd;
        auth_basic "Restricted Content";        
                }
}
```
書き終えたら、`nginx -t`で問題ないかテストしておきました。問題なかったので、次へ。
`/etc/nginx/sites-enabled`にシンボリックリンクを作成し、外からアクセス出来るようにしました。
```
#/etc/nginxにいるという想定
cd sites-enabled 
sudo ln -s ../sites-available/chatbot-ui .
```
defaultのシンボリックリンクは削除しました。
```
sudo rm default
```
これで、`<LXCのIPアドレス>:80`を叩くと、ベーシック認証の入力画面が表示され、それを抜けるとchatbot-uiにたどり着けるかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327331/005dba40-e77a-05f4-8176-0fadb3515e1b.png)

### この後自分はどうするか
自宅のネットワークは、外部からのリクエストは全て一つのリバースプロキシサーバーがhttpsで受け、SSLを剥がしてから各アプリケーションサーバにリクエストを割り振るようにしています。このchatbot-uiもリバースプロキシサーバーにSSL証明書を置いて、httpsで外からアクセス出来るようにする予定です。(しました)

----------------
時間があまりない中で(初心者が)ざっと書いたので、おかしな所あれば(優しく)教えてください。よろしくお願いいたします。

以上です。

## 参考資料

https://medium.com/bina-nusantara-it-division/how-to-deploy-your-next-js-apps-on-linux-server-using-nginx-and-pm2-65834cfecd37

https://qiita.com/kotarella1110/items/be76b17cdbe61ff7b5ca

https://stackoverflow.com/questions/18089525/nginx-sites-enabled-sites-available-cannot-create-soft-link-between-config-fil