Amazon Linux 2023でHTTPS対応のNode-RED環境を構築する（nginxリバースプロキシ使用）

# 背景
諸事情によりインターネット環境にNode-REDの実行環境が必要となり、EC2にサーバー構築しました。
いつものAmazon Linux 2で構築しようと思ったのですが、以下サイトに「**WARNING: BUILD SYSTEM CURRENTLY BROKEN FOR NODEJS 18+**」とあったので、Amazon Linux 2023で構築しました。

https://rpm.nodesource.com/

# 手順
## EC2インスタンスの起動と初期設定
詳細については割愛し、注意点のみ記載します。
### インスタンス起動時の注意点
- インターネット環境で使用するため、「パブリックIPの自動割り当て」を「有効化」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/0651b06d-be57-3118-c4b2-c6cdbc8487ed.png)
- セキュリティグループで以下のルールを追加
  - SSH（デフォルトで入っている・ソースタイプを「自分のIP」にすること推奨）
  - HTTP
  - HTTPS
  - TCP1880（動作確認用・ソースタイプを「自分のIP」にすること推奨）

### インスタンス起動後の作業
- Elastic IPの割り当て
- DNS登録：ホスト名でグローバルIPが変換できるようにする（当方はRoute53でAレコード追加）

### SSH接続
これまで使ってきたTeraTermが使えないらしいので、コマンドプロンプトから接続します。
```
> cd (キーペアのpemファイルのダウンロードフォルダ)
> ssh -i "(キーペア名).pem" ec2-user@(ホスト名)
```


### OSインストール後の共通作業
EC2のAmazon Linux起動後の共通作業（日本語化対応）を実施します。
```
$ sudo -s
# vi /etc/hostname
(ホスト名を書き換えて保存)
# rm -f /etc/localtime; ln -sf /usr/share/zoneinfo/Japan /etc/localtime
# vi /etc/sysconfig/clock
(ZONEを「UTC」から「Asia/Tokyo」に書き換えて保存)
# vi /etc/sysconfig/i18n
(「en_US」を「ja_JP」に書き換えて保存)
# source /etc/sysconfig/i18n
# reboot
```

## Node-REDインストールと初期設定
### Node-REDインストール
再起動完了後、SSHで再接続してNode-REDのインストールを行います。
```
$ sudo -s
# curl -fsSL https://rpm.nodesource.com/setup_20.x | bash -
# dnf install -y nodejs
# npm install -g --unsafe-perm node-red
```
### パスワード保護
そのままだとセキュリティ的に問題があるので、パスワードでログインするようにします。
```
# node-red admin hash-pw
Password:(パスワード入力しEnter)
$2XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX(この値をコピーしておく)
# vi /usr/lib/node_modules/node-red/settings.js
…
(以下のコメント解除)
    adminAuth: {
        type: "credentials",
        users: [{
            username: "admin",
            password: "$2a$08$zZWtXTja0fB1pzD4sHCMyOCMYz2Z6dNbM6tl8sJogENOMcxWV9DN.",
                             ↓ 初期値は「password」なので、上でコピーしたハッシュ値に変更
            password: "$2XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
            permissions: "*"
        }]
    },
…
```
### 自動起動設定
OS起動時にNode-REDが自動で起動するように、PM2をインストール、設定します。
```
# npm install -g pm2
…
# exit

※注意：以下はec2-userで実行する
$ pm2 start /usr/bin/node-red
…
$ pm2 startup
[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u ec2-user --hp /home/ec2-user
…
$ pm2 save
…
```

https://(グローバルIP):1880/でアクセスし、adminでログインできることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/4092b588-119f-49ad-5bb5-6babf2961172.png)

## リバースプロキシ導入とHTTPS対応
### nginxインストール
nginxをインストールし、サービスの起動、自動起動設定します。
```
$ sudo -s
# dnf install -y nginx
# systemctl start nginx
# systemctl enable nginx
```
http://(ホスト名)でアクセスし、Welcome画面が表示されることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/3891373c-4f3e-9034-b3ec-928cd200e9d1.png)

### Let's Encryptインストール
certbotのインストールと、証明書取得、nginxの設定を行います。
```
# dnf install -y python3 augeas-libs pip
# python3 -m venv /opt/certbot/
# /opt/certbot/bin/pip install --upgrade pip
# /opt/certbot/bin/pip install certbot
# ln -s /opt/certbot/bin/certbot /usr/bin/certbot
# systemctl stop nginx
# certbot certonly --standalone
…
(メールアドレスを記入)
…
(ライセンス規程に同意)
…
(メール配信希望に回答)
…
(ホスト名を入力)
…
# vi /etc/nginx/nginx.conf
…
(コメントを外し、ssl_certificateとssl_certificate_keyを編集)
    server {
        listen       443 ssl http2;
        listen       [::]:443 ssl http2;
        server_name  _;
        root         /usr/share/nginx/html;

        ssl_certificate "/etc/letsencrypt/live/(ホスト名)/fullchain.pem";
        ssl_certificate_key "/etc/letsencrypt/live/(ホスト名)/privkey.pem";
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers PROFILE=SYSTEM;
        ssl_prefer_server_ciphers on;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }
…
# systemctl start nginx
```
http<font color='red'>s</font>://(ホスト名)でアクセスし、Welcome画面が表示されることを確認します。


### リバースプロキシ設定
nginxの設定ファイルにリバースプロキシ設定を追記し、サービスを再起動します。
```
# vi /etc/nginx/nginx.conf
…
    server {
        listen       443 ssl http2;
        listen       [::]:443 ssl http2;
        server_name  _;
        root         /usr/share/nginx/html;
        # ここから追記
        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_pass http://127.0.0.1:1880/;
        }
        # ここまで追記

        ssl_certificate "/etc/letsencrypt/live/(ホスト名)/fullchain.pem";
        ssl_certificate_key "/etc/letsencrypt/live/(ホスト名)/privkey.pem";
…

# systemctl restart nginx
```

https://(ホスト名)でアクセスし、Node-REDの画面が表示されることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916611/1394bfb4-104c-acb5-2c64-f608d885bb82.png)

以上で構築完了となります。
インターネット公開しているため、セキュリティグループのTCP 1880のルールを削除しておくことをおすすめします。

# 証明書更新（2023/8/3追記）
Let's Encryptで取得した証明書は3か月で有効期限が切れるため、有効期限の1か月程度前に更新が必要となります。
更新の方法は[こちら](https://codenote.net/ssl/3920.html)を参考に実行しましたが、「Failed to renew certificate ceemskj.chugai-tec.com with error: The requested nginx plugin does not appear to be installed」となったため、以下のコマンドでプラグインを追加しました。
```
# /opt/certbot/bin/pip install certbot-nginx
```
プラグインインストール後、以下のコマンドで無事更新ができました。
```
# certbot renew --nginx --renew-hook "/bin/systemctl reload nginx"
```

# 参考URL
今回も先人の方々の情報により短時間で実現できました。
以下の著者の皆様、誠にありがとうございます。

https://qiita.com/kolinz/items/94869a3ca8529b14f458

https://blog.interstellar.co.jp/2023/05/11/amazon-linux-2023-nginx-install/

https://softwarenote.info/p3954/

https://blog.goo.ne.jp/lm324/e/13b0da9ae03cde5324582cf8024cdc92

https://codenote.net/ssl/3920.html