パーミッション


a-blog cms を動かすときのファイル・ディレクトリのパーミッションと所有権(owner / group)をまとめます。インストール時の権限エラー、メディアのアップロード失敗、オンラインアップデートの中断は、たいてい owner かパーミッションが原因で発生します。まずはここを確認してください。

基本は一律でこのパーミッション

ファイル・ディレクトリは、原則として全体を次の値にしておけば問題ありません。インストール・運用・アップデートで必要なパーミッションが変わることはなく、この一律の設定で足ります。

対象

単一ユーザー環境

共有グループ環境

ディレクトリ

755

775

ファイル

644

664

775 / 664 は、FTP ユーザーと PHP 実行ユーザーが別で、同一グループにまとめて運用する環境向けです。mod_php で PHP が www-data などの共通ユーザーで動くケースがこれにあたります。suEXEC や PHP-FPM のユーザー別プールのように、PHP がサイト所有者のアカウントで動くなら 755 / 644 で足ります。

パーミッションの数字よりも、owner と group が揃っているかのほうが効いてきます。owner が揃っていないと、パーミッションが正しくても書き込みや置換に失敗します。

本番で 777 にすると誰でも書き換えられるため、セキュリティ上避けてください。

なお archives/ media/ storage/ cache/ private/ は CMS が書き込みを行うディレクトリです。とはいえパーミッションは上の一律設定のままでよく、owner が PHP 実行ユーザーと合っていることが重要です。

PHP がどの OS ユーザーで動くか

推奨パーミッションが分かれる理由は、SAPI の種類ではなく PHP プロセスの実効 UID にあります。

SAPI / 構成

実行ユーザー

推奨パーミッション

mod_php(Apache DSO)

Web サーバ共通ユーザー(www-data 等)

775 / 664

CGI + suEXEC / suPHP

サイト所有者アカウント

755 / 644

PHP-FPM(ユーザー別プール)

サイト所有者アカウント

755 / 644

PHP-FPM(共通プール)

プールの共通ユーザー

775 / 664

SAPI 名から推測せず、実機で確認したほうが確実です。

<?php
echo posix_getpwuid(posix_geteuid())['name'], PHP_EOL; // 実効ユーザー名
echo php_sapi_name(), PHP_EOL;                          // fpm-fcgi, apache2handler 等
// posix 拡張が無ければ exec('whoami')

CMS が生成するファイルのパーミッション

アップロードやキャッシュ生成では、CMS 自身もファイル・ディレクトリを作成します。そのパーミッションは config.server.php の 定数で決まります。

定数

既定値

用途

CHMOD_DIR

(0775 & ~umask())

CMS が作るディレクトリ

CHMOD_FILE

(0664 & ~umask())

CMS が作るファイル

既定はグループ書き込みあり(775 / 664 相当)が前提なので、上の一律設定と整合します。& ~umask() が掛かるため、実効パーミッションは PHP プロセスの umask 次第になります。意図したパーミッションにならないときは、 umask を確認してください。


所有権が重要

パーミッションよりも owner / group の一致のほうが、重要です。

いちばん堅いのは、CMS ファイル一式の owner を PHP 実行ユーザーに統一する方法です。これなら 755 / 644 で足ります。PHP 実行ユーザーと FTP ユーザーが別であれば、両者を同一グループに入れて group write(775 / 664)を付けてください。

よくある失敗が、FTP で上げたファイル(FTP ユーザー owner)と CMS が作ったファイル(PHP 実行ユーザー owner)が混ざり、ファイルごとに owner がばらばらになった状態です。これだとアップロードやアップデートで書き込みできなくなります。FTPでファイルを差し替えたら、owner とパーミッションを直してから運用・再アップデートしてください。直さずに再実行すると、同じ箇所で止まります。

POSIX 判定の順序に注意

POSIX のアクセス判定は owner → group → other の順で、最初に一致したクラスのビットだけを使います。後ろのクラスがいくら緩くても評価されません。

たとえばパーミッション 604rw- --- r--、group ビットが 0)の場合は、次のようになります。

  • owner なら read / write できます

  • PHP 実行ユーザーが当該ファイルの group に属していると、group ビット --- で確定し、other に read があっても EACCES になります

  • owner でも group でもない(other)なら read だけです

「other に read を付けたから大丈夫」のつもりでも、group が一致すると先に弾かれます。604 のような group ビットだけ 0 のパーミッションは避けてください。


困ったとき

オンラインアップデートで「書き込み権限がありません」と出て進まない。

アップデートはファイルを置換する前に、置換対象(php/ js/ themes/system/ など)とバックアップ先が書き込み可能かを事前チェックします。多くの権限問題はここで止まり、対象パスがメッセージに出ます。出ているパスの owner とパーミッションを直してからアップデートを再実行してください。

オンラインアップデートが途中で止まり、php/themes/system/ が消えた。

置換は旧ファイルを private/backup{YmdHis}/ に退避してから新ファイルを設置します。途中で失敗しても、通常は退避物から自動でロールバックされるため、消えたままにはなりません。問題になるのはロールバックできなかったときで、タイムアウトやメモリ不足でプロセスごと落ちると例外を捕捉できずロールバックが走りません(ロールバック自身も書き込めなければ途中で止まります)。その結果、退避物が private/backup{YmdHis}/ に残ったまま元の場所が空に見えます。退避物を確認し、owner とパーミッションを直してから戻してください。

メディアのアップロードや生成で 書き込みエラー。

archives/ media/ storage/ cache/ のどれかに、PHP 実行ユーザーから書き込みできていません。owner とパーミッションを確認してください。ディレクトリは実行権限も必要です。中のファイルへ辿るのに必要で、欠けていると読み取り・書き込み以前にアクセスできません。

パーミッションは正しいのに動かない。

表示上のパーミッションが合っていても、次の理由で 書き込みできないことがあります。

  • umask — CMS が新規生成するファイル/ディレクトリの権限は (0775 & ~umask()) のように umask がデフォルトで適用されます。手で設定した値が正しくても、CMS が作るファイルだけ 書き込みできないなど、実効値が意図とずれることがあります。

  • owner の不一致 — group / other に 書き込み権限を振っていない構成では、書けるのは owner だけです。親ディレクトリやファイルが別ユーザー所有だと、PHP 実行ユーザーが 書き込みできず rename や上書きに失敗します。chmod もファイル所有者しかできません。パーミッションの数字には owner が現れないので見落としがちです。

  • open_basedir — PHP がアクセスできるパスを制限する設定です。OS のパーミッションが正しくても、範囲外のパスは PHP から触れません。

  • SELinux / AppArmor — OS の通常パーミッションとは別の強制アクセス制御(MAC)レイヤーです。chmod / chown が正しくても、ポリシー側で拒否されることがあります。


コマンド例

実行前にバックアップを取り、<user> <group> は実環境の PHP 実行ユーザー/グループに置き換えてください。owner 変更には root 権限が必要で、共有ホスティングではホスティング側の対応が要る場合があります。

# owner を PHP 実行ユーザーに統一
chown -R <user>:<group> .

# 単一ユーザー環境: ディレクトリ 755 / ファイル 644
find . -type d -exec chmod 755 {} \;
find . -type f -exec chmod 644 {} \;

# 共有グループ環境: ディレクトリ 775 / ファイル 664
find . -type d -exec chmod 775 {} \;
find . -type f -exec chmod 664 {} \;