2026年5月17日
2026年5月17日
WordPressのアップロードディレクトリのパーミッションエラーを解決する方法
はじめに
WordPressでメディアをアップロードしようとした際に「Unable to create directory wp-content/uploads/2026/05. Is its parent directory writable by the server?」というエラーが表示されることがあります。これはWebサーバーのプロセスがアップロードディレクトリへの書き込み権限を持っていないことが原因です。本記事ではパーミッション・所有者の修正から、カスタムディレクトリの設定・セキュアな管理方法まで解説します。
症状・原因
- 画像や動画のアップロード時に「Unable to create directory」エラーが出る
wp-content/uploadsディレクトリの所有者が Web サーバーのユーザー(www-data など)ではない- ディレクトリのパーミッションが
700など、サーバープロセスからアクセスできない設定になっている - FTP でファイルを転送したため所有者が FTP ユーザーになっている
- SELinux や AppArmor がファイルへのアクセスをブロックしている
解決手順
ステップ1:現在の所有者とパーミッションを確認する
# wp-content/uploads の所有者とパーミッションを確認する
ls -la /var/www/html/wp-content/
# 出力例:
# drwxr-xr-x 2 ftpuser ftpuser 4096 May 16 10:00 uploads
# ↑ 所有者が ftpuser になっていて、www-data が書き込めない
# Webサーバーが動いているユーザーを確認する
# Apache の場合
ps aux | grep apache | head -1
# Nginx + PHP-FPM の場合
ps aux | grep php-fpm | head -1
# 一般的な値:www-data(Ubuntu/Debian)、nginx(CentOS)、apache(RHEL)
# WordPress が期待するアップロードパスを確認する
wp eval 'print_r( wp_upload_dir() );'
# basedir と baseurl が正しいか確認する
# SELinux の確認(CentOS/RHEL の場合)
getenforce
ls -Z /var/www/html/wp-content/uploads/
ステップ2:ディレクトリとファイルのパーミッションを正しく設定する
# ディレクトリに 755、ファイルに 644 を設定する(推奨構成)
# uploads ディレクトリ以下の全ディレクトリを 755 に設定
find /var/www/html/wp-content/uploads -type d \
-exec chmod 755 {} \;
# uploads ディレクトリ以下の全ファイルを 644 に設定
find /var/www/html/wp-content/uploads -type f \
-exec chmod 644 {} \;
# uploads ディレクトリ自体のパーミッションも確認
chmod 755 /var/www/html/wp-content/uploads
# WordPress コアファイルの推奨パーミッション
# ディレクトリ:755
# ファイル:644
# wp-config.php:600(最小権限)
chmod 600 /var/www/html/wp-config.php
# パーミッション設定後に確認する
ls -la /var/www/html/wp-content/uploads/
ステップ3:所有者を Web サーバーのユーザーに変更する
# Ubuntu/Debian(Apache または Nginx + PHP-FPM)の場合
sudo chown -R www-data:www-data /var/www/html/wp-content/uploads
# CentOS/RHEL(Apache)の場合
sudo chown -R apache:apache /var/www/html/wp-content/uploads
# CentOS/RHEL(Nginx + PHP-FPM)の場合
sudo chown -R nginx:nginx /var/www/html/wp-content/uploads
# 所有者変更後に確認する
ls -la /var/www/html/wp-content/
# WordPress ルート全体の所有者を修正する場合(注意して実行)
# FTP ユーザーも書き込める構成にする場合(グループを活用)
sudo usermod -aG www-data ftpuser
sudo chown -R ftpuser:www-data /var/www/html/wp-content/uploads
find /var/www/html/wp-content/uploads -type d -exec chmod 775 {} \;
find /var/www/html/wp-content/uploads -type f -exec chmod 664 {} \;
# SELinux の場合:コンテキストを修正する
sudo semanage fcontext -a -t httpd_sys_rw_content_t \
'/var/www/html/wp-content/uploads(/.*)?'
sudo restorecon -Rv /var/www/html/wp-content/uploads
ステップ4:UPLOADS 定数と upload_dir フィルターでカスタムディレクトリを設定する
<?php
// wp-config.php でアップロード先ディレクトリを変更する
// UPLOADS は wp-config.php で設定する(wp-content/uploads がデフォルト)
// パスは WordPress のインストールディレクトリからの相対パス
define( 'UPLOADS', 'wp-content/media' ); // カスタムパスに変更
// より柔軟な設定は upload_dir フィルターを使用する(functions.php)
add_filter( 'upload_dir', 'custom_upload_directory' );
function custom_upload_directory( $dirs ) {
// 年月サブディレクトリを使わずにフラットな構造にする
$custom_dir = '/uploads-flat';
$dirs['subdir'] = $custom_dir;
$dirs['path'] = $dirs['basedir'] . $custom_dir;
$dirs['url'] = $dirs['baseurl'] . $custom_dir;
return $dirs;
}
// ユーザーごとに分けたアップロードディレクトリ
add_filter( 'upload_dir', 'user_specific_upload_directory' );
function user_specific_upload_directory( $dirs ) {
$user_id = get_current_user_id();
if ( $user_id ) {
$subdir = '/users/' . $user_id;
$dirs['subdir'] = $subdir;
$dirs['path'] = $dirs['basedir'] . $subdir;
$dirs['url'] = $dirs['baseurl'] . $subdir;
// ディレクトリが存在しない場合は作成する
if ( ! file_exists( $dirs['path'] ) ) {
wp_mkdir_p( $dirs['path'] );
}
}
return $dirs;
}
ステップ5:アップロードディレクトリをウェブルート外に移動してセキュリティを強化する
<?php
// wp-config.php でアップロード先をウェブルート外に設定する
// (セキュリティ上、実行可能ファイルをウェブから直接アクセスさせない)
// ウェブルート外のパス(例:/var/uploads)
define( 'UPLOADS', '../uploads' ); // ウェブルートの1つ上
// または upload_dir フィルターで絶対パスを指定する
add_filter( 'upload_dir', 'secure_upload_directory' );
function secure_upload_directory( $dirs ) {
// ウェブルート外のディレクトリ
$secure_dir = '/var/wordpress-uploads';
$secure_url = 'https://example.com/uploads-proxy'; // プロキシ経由で配信
$dirs['basedir'] = $secure_dir;
$dirs['baseurl'] = $secure_url;
$dirs['path'] = $secure_dir . $dirs['subdir'];
$dirs['url'] = $secure_url . $dirs['subdir'];
return $dirs;
}
# Nginx でウェブルート外のアップロードを配信するプロキシ設定
server {
# アップロードファイルをウェブルート外から配信する
location /uploads-proxy/ {
alias /var/wordpress-uploads/;
# PHP ファイルの実行を禁止(セキュリティ)
location ~* \.php$ {
deny all;
}
# SVG・HTML ファイルも制限する
location ~* \.(html|htm|svg)$ {
add_header Content-Type text/plain;
}
}
}
注意事項
- 実行可能ファイルのアップロード: .php ファイルがアップロードされ実行されるとサーバーが乗っ取られます。アップロードディレクトリで PHP の実行を Nginx/Apache で禁止してください。
- 777 パーミッションは使用しない:
chmod 777はすべてのユーザーに書き込み権限を与えるため非常に危険です。問題が解決しても 755/644 に戻してください。 - バックアップ: 所有者変更の前に、現在の設定をメモまたはスクリプトで記録しておきましょう。
まとめ
アップロードパーミッションエラーは「所有者の確認→chmod/chown で修正→カスタムディレクトリの設定→セキュリティ強化」の手順で根本的に解決できます。ウェブルート外へのアップロード配置まで実施すれば、マルウェアのアップロード・実行リスクを大幅に低減できます。関連記事:WordPressのXMLRPC脆弱性を無効化してセキュリティを強化する方法