Apache、MariaDB を使った Express.js アプリの設定方法 - AlmaLinux

アプリについて

このページは Apache をリバースプロキシサーバーとして Express.js のアプリをデプロイする方法についての説明です。

サーバーは、VirtualBox に AlmaLinux9 をインストールし開発環境を構築します。SELinux は、「 enforcing 」の状態のまま利用します。

サーバーが再起動しても、Express.js アプリが自動で起動するように、「 PM2 」の自動起動の設定も合わせて説明します。

Apache の設定

まず Apache をインストールします。

sudo dnf -y install httpd

プロキシサーバーとしての設定をします。「/etc/httpd/conf.d/exproxy.conf」というファイルを作成し、設定をします。

sudo vi /etc/httpd/conf.d/exproxy.conf

ファイルを以下のようにします。

/etc/httpd/conf.d/exproxy.conf

<VirtualHost *:80>
    ProxyPass / http://localhost:4000/
    ProxyPassReverse / http://localhost:4000/
</VirtualHost>

Apache の自動起動と起動を行います。

sudo systemctl enable httpd
sudo systemctl start httpd

MariaDB の設定

MariaDB をインストールします。

sudo dnf -y install mariadb mariadb-server

文字コードの設定を行います。設定ファイルを開くには、以下のようにします。

sudo vi /etc/my.cnf 

設定ファイルに以下の内容を追加します。

[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

[client]
default-character-set=utf8mb4

MariaDB の自動起動と起動を行います。

sudo systemctl enable mariadb
sudo systemctl start mariadb

MariaDB の初期設定をするには、以下のコマンドを実行します。

sudo mysql_secure_installation

初期設定のそれぞれの項目は、以下を参考にしてください。

初期設定の完了後、データベースにログインして、新しいユーザーを作成します。

まず、root でログインします。

mariadb -u root -p

初期設定で設定したルートのパスワードを入力しログインします。

CREATE USER 'dbuser'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON * . * TO 'dbuser'@'localhost';
FLUSH PRIVILEGES;

上記の内容については、以下を参照してください。

データベースとテーブルの作成に関しては、Express.js アプリを起動すると自動でデータベースとテーブルが作成されるように「 app.js 」にコードを記述しています。

Express.js アプリ設置

GitHub から Expressアプリのサンプルをユーザーのホームディレクトリにダウンロードします。

git でファイルをクローンします。以下のファイルでは、起動ポートを「 4000 」に変更しています。

git clone https://github.com/beginnerP765/excrud.git

PM2 の自動起動の設定

PM2 の起動のための設定ファイルを作成します。

sudo vi /home/user/excrud/pm2myapp.json

ファイルの内容を以下のようにします。

/home/user/excrud/pm2myapp.json

{
    "name": "myapp",
    "script": "./bin/www",

    "env": {
        "NODE_ENV": "development"
    },

    "env_production": {
        "NODE_ENV": "production"
    }
}

Express アプリのルートディレクトリに移動し、次のコマンドを実行します。

pm2 start pm2myapp.json --env production

Express アプリが起動した状態のまま、次のコマンドを実行します。

pm2 startup

コマンドを実行すると次のような表示がされます。

[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/home/user/.nvm/versions/node/v20.15.0/bin /home/user/.nvm/versions/node/v20.15.0/lib/node_modules/pm2/bin/pm2 startup systemd -u user --hp /home/user

「 sudo env 」から始まる部分をコピーし、そのコマンドを実行します。

上記の場合だと、「 sudo env PATH=$PATH:/home/user/.nvm/versions/node/v20.15.0/bin /home/user/.nvm/versions/node/v20.15.0/lib/node_modules/pm2/bin/pm2 startup systemd -u user --hp /home/user 」の部分をコピーします。

以下のコマンドを実行して、設定を保存します。

pm2 save

SELinux の設定

SELinux を enforcing で利用している為、503 エラーになります。以下のコマンドを実行して設定を変更します。

sudo setsebool -P httpd_can_network_connect on

ここまでの設定で、ブラウザから「 xxx.xxx.xxx.xxx/cms 」に接続しウェブページが表示されれば、設定完了です。「 xxx.xxx.xxx.xxx 」は、サーバーの IPアドレスを指定します。

しかし、SELinux のポリシーを変更をしていないため、サーバーを再起動すると PM2 がエラーになり Express.js アプリは自動起動しません。

エラーを確認してポリシーの設定を変更します。エラーの確認は以下のコマンドを実行し、確認します。

sudo less /var/log/messages

audit2allow によって生成される許可ルールは粗い場合があり、必要以上の許可を与えてしまうこともあるため、利用する際は注意が必要です。

以下は、VirtualBox で環境を構築しているときに audit2allow で作成された許可ルールです。

my-PM2v605God.te

module my-PM2v605God 1.0;

require {
	type init_t;
	type user_home_t;
	class sock_file { create unlink };
	class file { ioctl write };
}

#============= init_t ==============

#!!!! This avc is allowed in the current policy
#!!!! This av rule may have been overridden by an extended permission av rule
allow init_t user_home_t:file ioctl;
allow init_t user_home_t:file write;

#!!!! This avc is allowed in the current policy
allow init_t user_home_t:sock_file unlink;
allow init_t user_home_t:sock_file create;

my-pm2.te

module my-pm2 1.0;

require {
	type init_t;
	type user_home_t;
	class file { execute execute_no_trans open read };
}

#============= init_t ==============

#!!!! This avc is allowed in the current policy
allow init_t user_home_t:file { execute open read };
allow init_t user_home_t:file execute_no_trans;

my-node.te

module my-node 1.0;

require {
	type user_home_t;
	type init_t;
	class file { append create map };
	class sock_file write;
	class process execmem;
}

#============= init_t ==============

#!!!! This avc is allowed in the current policy
allow init_t self:process execmem;

#!!!! This avc is allowed in the current policy
allow init_t user_home_t:file map;
allow init_t user_home_t:file { append create };

#!!!! This avc is allowed in the current policy
allow init_t user_home_t:sock_file write;

my-nodehomeuser.te

module my-nodehomeuser 1.0;

require {
	type mysqld_port_t;
	type init_t;
	class tcp_socket name_connect;
}

#============= init_t ==============
allow init_t mysqld_port_t:tcp_socket name_connect;

audit2allow で作成された許可ルールをコンパイルし反映するには、以下のコマンドを実行します。

# my-PM2v605God.te のコンパイル
# モジュールのコンパイル
checkmodule -M -m -o my-PM2v605God.mod my-PM2v605God.te

# ポリシーパッケージの作成
semodule_package -o my-PM2v605God.pp -m my-PM2v605God.mod

# カーネルへのモジュール読み込み
sudo semodule -i my-PM2v605God.pp

# ------------------------------------------------------------------------
# my-pm2.te のコンパイル
checkmodule -M -m -o my-pm2.mod my-pm2.te
semodule_package -o my-pm2.pp -m my-pm2.mod
sudo semodule -i my-pm2.pp

# ------------------------------------------------------------------------
# my-node.te のコンパイル
checkmodule -M -m -o my-node.mod my-node.te
semodule_package -o my-node.pp -m my-node.mod
sudo semodule -i my-node.pp

# ------------------------------------------------------------------------
# my-nodehomeuser.te のコンパイル
checkmodule -M -m -o my-nodehomeuser.mod my-nodehomeuser.te
semodule_package -o my-nodehomeuser.pp -m my-nodehomeuser.mod
sudo semodule -i my-nodehomeuser.pp