LoginSignup
2
3

More than 5 years have passed since last update.

VPS はシェアしよう!効率のいい Linux ユーザー権限管理法。(LNMP)

Last updated at Posted at 2019-01-09

前言

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\$ {
    try_files \$uri =404;
    fastcgi_split_path_info ^(.+.php)(/.+)\$;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
    fastcgi_param PHP_ADMIN_VALUE open_basedir=\$document_root:/tmp;
    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 にも、全く工夫せずに、ユーザーの権限分離が実現した。

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

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3