VPS はシェアしよう！効率のいい Linux ユーザー権限管理法。（LNMP）

## 前言

VPS を買った後に、リソースの利用率が少なく、友達とシェアしたくないですか？

だが、権限の設定はしっかりしていないと、友達はみんな Linux の専門家ではないので、何かやっちまったら困ります。

ここで、独断でいいと思った「バーチャルホスト」の作り方をシェアします。

本文は CentOS 7 + Nginx + PHP-FPM + MySQL をベースに語るものです。

## 無難なやり方

一番安全なやり方というと、もちろんユーザーごとにユーザーを作ることです。
`useradd` して、ユーザーのホームフォルダの下にウェブサイトのフォルダを作るか、それとも、Nginx にアクセス権限のある `/var/www/html` などの場所に集約して、`setfacl` でユーザーごとにフォルダーの権限を付けます。もちろん、PHP-FPM もユーザーごとに、Socket ファイルを作ります。完璧ですね。

だが面倒くさい。デメリットもいっぱいあります。

- PHP はユーザーごとに独立なプールがあって、コンピュータリソースが無駄に使われる。
- ユーザーのホームフォルダの下にウェブサイトのフォルダを作ると、Nginx に権限渡すのが面倒くさい。（新しく作成されたファイルは ACL 権限継承されていない可能性ある）

## ここで 2019 に考えた案を紹介

簡単に言えば、面倒なことを出来るだけ避けたいです。

Nginx と PHP は全員のウェブサイトフォルダーにアクセス権を与える。**だが、一つのウェブサイトの PHP プロセスは別のウェブサイトフォルダーに書き込んではいけない。**

Nginx と PHP は全員のウェブサイトフォルダーにアクセス権を与えるので、面倒な設定を避けるため、**統一 Nginx のユーザーで動かせる。**

こうやると、PHP が新しく書き込んだファイルは `nginx:nginx` になり、他のユーザーが読み取れないので、**そこで、他のユーザー（友達）を全部 Group:nginx に入れる。**

でもでも、**全員 Group:nginx になったら、他のユーザーフォルダーにもアクセス可能になる！**これも勿論解決しなければ。

これらを踏まえて、以下の案が生まれました。

- Nginx と PHP は `User:nginx Group:nginx` で動く。
- 友達に全員独立ユーザーを発行する、ウェブサイトフォルダーはホームフォルダの下に作って、ウェブサイトフォルダーのグループ権限は nginx に変更する。
- PHP はウェブサイトごとに制限しなければならないので、そこは、`fastcgi_param PHP_ADMIN_VALUE open_basedir`（PHP の中で実行フォルダーを制限するパラメタ）を使って、Nginx から制限かける。
- ユーザーは他人のホームフォルダーをアクセスしてはいけない、でもユーザー全員 Group:nginx にいるので、ここに、ユーザーのホームフォルダ閲覧権限だけは `setfacl` を使い、User:nginx （ **Group:nginx ではない** ）が閲覧権限持つように設定する。

## つまり

友人Aのウェブサイトは `/home/A/www` にあって、友人Bのウェブサイトは `/home/B/www` にする。
これらのフォルダーは Group:nginx がアクセスすることが可能です、つまり、Nginx と PHP が自由に使えます。
でも、友人Aのウェブサイトをアクセスしているのに、何かの脆弱性で友人Bのウェブサイトに PHP が実行されたらやばいことになる。ここで、`fastcgi_param PHP_ADMIN_VALUE open_basedir=/home/A/www` とかで制限かける。
また、友人Aと友人Bのアカウントは、PHP が新しく作ったファイルにも編集できるようにするため、`Group:nginx` のユーザーになってる。でもこれじゃ、友人Bは同時に友人Aのフォルダーにも編集権限はある。
そこで、`/home/A` のアクセスに `User:nginx` だけ追加することで解決する。（ これで、友人Bは友人Aのウェブサイトフォルダーに権限ありますが、でも `/home/A/www` に入るため、まず `/home/A` に入らなきゃならない、それができなくなったので、自然にその中にある www フォルダーに進まない ）

## つまり！（コード実現）

username=hoge `ユーザー名を変数に定義する`

useradd $username `新しいユーザーを作成`
usermod -a -G nginx $username　`このユーザーを Group:nginx に追加する`
su -c "mkdir /home/\$username/www" $username `このユーザーのウェブサイトフォルダーを作る`
chgrp nginx /home/$username/www `ウェブサイトフォルダーのグループ所有者を nginx にする`
chmod g+rwxs /home/$username/www `グループ所有者 nginx の権限を設定する`

su -c 'cat /dev/zero | ssh-keygen -t ed25519 -q -N ""' \$username
su -c "cp /home/\$username/.ssh/id_ed25519.pub /home/\$username/.ssh/authorized_keys" \$username
chmod 600 /home/$username/.ssh/authorized_keys
`2019 にまだパスワードログインするとかはしていないですよね？ SSH　Keyでログインさせよう。`

setfacl -m u:nginx:rx /home/$username `ホームフォルダの閲覧権限は User:nginx だけに追加する`

location ~ \\.php\$ {
&nbsp;&nbsp;&nbsp;&nbsp;try_files      \$uri =404;
&nbsp;&nbsp;&nbsp;&nbsp;fastcgi_split_path_info ^(.+\.php)(/.+)\$;
&nbsp;&nbsp;&nbsp;&nbsp;fastcgi_pass   127.0.0.1:9000;
&nbsp;&nbsp;&nbsp;&nbsp;fastcgi_index  index.php;
&nbsp;&nbsp;&nbsp;&nbsp;fastcgi_param  SCRIPT_FILENAME  \$document_root\$fastcgi_script_name;
&nbsp;&nbsp;&nbsp;&nbsp;**fastcgi_param  PHP_ADMIN_VALUE  open_basedir=\$document_root:/tmp;**
&nbsp;&nbsp;&nbsp;&nbsp;include        fastcgi_params;
} `Nginx の PHP 処理する部分に fastcgi_param PHP_ADMIN_VALUE を追加する`

; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
; RPM: apache Choosed to be able to access some dir as httpd
user = **nginx**
; RPM: Keep a group allowed to write in log dir.
group = **nginx**
`もちろん、PHP-FPM のユーザー設定を忘れずに（ 通常は /etc/php-fpm.d/www.conf にいます ）`

dbpass=\`pwgen -s 24 1`
echo "ランダム作成したデータベースパスワードは: \$dbpass"

mysql -u root -p <<MYSQL_SCRIPT
CREATE DATABASE \$username;
CREATE USER '\$username'@'localhost' IDENTIFIED BY '\$dbpass';
GRANT ALL PRIVILEGES ON \$username.* TO '\$username'@'localhost';
FLUSH PRIVILEGES;
MYSQL_SCRIPT
`最後はいつも通りにユーザーごとにデータベースを作成すればいい`

## ドン勝！

これで、Nginx にも、PHP にも、全く工夫せずに、ユーザーの権限分離が実現した。

唐突に終わったのですが、本文に何か間違ったものがあれば、コメントで頂ければと思います。