WordPress 檔案權限:外掛安裝與 uploads 目錄要分清甚麼

← 所有文章

Managed-WP.™ PRO 藍色橫幅:WordPress 檔案權限不是單一 755/644 公式;圖中分出 wp-content/plugins、wp-content/uploads 與 wp-config.php 三個範圍,並提醒先核對擁有者、PHP runtime、mount/ACL 與主機規則。
外掛安裝與媒體上傳不是同一條寫入路徑;先分範圍,再談權限數字。

外掛安裝失敗、圖片上傳失敗,或 WordPress 突然要求 FTP/SSH 憑證,畫面上都可能寫着「權限」。但它們不是同一個問題:外掛程式碼寫入 wp-content/plugins,媒體預設寫入 wp-content/uploads,而 wp-config.php 更不應被當成臨時開關。真正要核對的是誰擁有檔案、PHP 用哪個帳戶運行、主機怎樣限制寫入。

先講結論

不要先改權限數字。先記錄錯誤、精確路徑、owner/group、PHP-FPM 或 suexec 的運行帳戶、mount/ACL/provider rules,再對照主機 setup。需要變更時,只在備份、staging 與精確路徑做最小可回復的改動。不要把 755/644 當所有 hosting 的答案,不要使用 777,也不要對未知目錄做整站 chmod -R。

一、先把三個範圍分開

同一個網站,最少有三個不同性質的檔案範圍:

範圍預設位置用途常見寫入者/政策不要混淆
外掛程式碼wp-content/plugins安裝、更新、刪除外掛部署帳戶、CI、SFTP 或主機工具;不一定要由 PHP 執行帳戶長期寫入不要為媒體上傳而放寬整個 plugins 目錄
媒體與附件wp-content/uploads媒體庫、年份/月份子目錄PHP runtime 需要在指定範圍建立及寫入;也可能由物件儲存或 CDN 管理不要為外掛安裝而把 uploads 當成通用寫入區
連線與 secretswp-config.php資料庫連線、salts、常數應嚴格限制讀取,一般不應由 web server 寫入不要把它當成排查外掛/上傳時的臨時權限開關

實際路徑可能被常數、外掛或主機工具改動;例如 uploads 可以自訂位置,也可能由 CDN/物件儲存接管。排查前先確認「這個網站現在實際用哪個路徑」,不要只憑預設值判斷。

權限範圍圖解 · 先看路徑,再看 runtime

01

wp-content/plugins

外掛程式碼

  • 安裝、更新、刪除外掛
  • 可由部署帳戶/CI/SFTP 管理
  • 不要把媒體上傳政策搬過來
02

wp-content/uploads

媒體與附件

  • PHP runtime 的有限寫入範圍
  • 年份/月份子目錄可按設定建立
  • 可寫入不等於可執行 PHP
03

wp-config.php

連線與 secrets

  • 資料庫連線、salts、常數
  • 應嚴格限制讀取
  • 不是臨時權限開關
先記錄:錯誤原文 · 精確路徑 · owner/group · PHP-FPM/suexec runtime · mount/ACL · provider rules

圖解替代文字:左欄 plugins 是程式碼部署;中欄 uploads 是 runtime 媒體寫入;右欄 wp-config.php 是 secrets。三欄下方要求先記錄錯誤、路徑、擁有者、runtime、mount/ACL 與主機規則,再在備份、staging 與精確路徑做最小可回復變更。

權限範圍圖解:plugins、uploads 與 wp-config.php 是三個不同邊界;先核對 owner 與 runtime,不要用同一個數字處理三件事。

二、owner 先於 mode:755 不是一個獨立答案

權限數字只描述 owner、group、others 的讀取、寫入、執行組合。同一個 755,放在不同擁有者、不同 PHP 帳戶、不同 mount 之下,效果可以完全不同。WordPress 官方文件也明言:權限會因主機而異,文件只列一般原則,不能覆蓋所有情況 [1]。

官方文件針對幾種 setup 的描述,可以整理成以下對照;這些是情境示例,不是 universal 公式:

Setup官方文件的方向重要 caveat
一般標準 setup檔案通常由你的 FTP/使用者帳戶擁有;目錄 755、檔案 644 可作對照只適用於該 setup;若 PHP 以不同帳戶運行,數字本身不足
同一 group 需要寫入文件舉例可用 775/664只在 group 已知、受信任且確實需要時;不是開啟全站寫入的理由
Shared hosting 用 suexec/PHP 以檔案擁有者身分運行目錄 755 或 750;檔案 644 或 640;wp-config.php 440 或 400;不可 777官方把 suexec 視為 shared hosting 的特定情境,不應把數字套到單站或其他 runtime
PHP-FPM pool/webserver 與部署帳戶分開;容器或受管平台沒有單一數字可由通用文件推導要記錄實際 runtime user、group、ACL、mount、SELinux/provider policy,再決定寫入方式

shared-hosting suexec/owner-runs-PHP

在 suexec 這類 setup,PHP 程序以 PHP 檔案的擁有者身分運行。官方文件的方向是:檔案由實際使用者帳戶擁有,而不是 httpd 程序帳戶;目錄可用 755/750,檔案可用 644/640;wp-config.php 用 440/400;即使是 uploads,也不應給 777。因為 PHP 已是檔案擁有者,它可以按 owner 權限寫入,不需要把目錄開放給所有人 [1]。

這段很重要,但不是叫你把所有主機都當成 suexec。若你的 PHP-FPM pool 使用獨立使用者,或部署人員與 PHP runtime 是兩個帳戶,ownership/group/ACL 的設計就不同;這時直接抄 suexec 的數字,可能仍然不能寫入。

其他 runtime:先問「誰在寫」

以下情況都不應只用一組數字判斷:

  • PHP-FPM pool 以 www-data 或其他服務帳戶運行,但檔案由 SFTP/部署帳戶擁有。
  • 網站跑在容器、唯讀映像、NFS、network mount 或受管平台,檔案系統可能不允許直接寫入。
  • 主機使用 ACL、SELinux、AppArmor 或 provider 自訂的目錄政策。
  • uploads 已交給物件儲存、CDN 或外部媒體服務,本機目錄不再是唯一寫入點。

在這些情況下,先記錄 id、PHP-FPM pool 的 user/group、精確路徑的 ls -ld、mount 與 ACL,再向主機供應商核對預期設定。沒有這些證據,改 755、775 或 777 都只是猜。

三、外掛安裝:寫入 plugins,不是寫入 uploads

WordPress 官方文件列出三種外掛安裝方式:從外掛目錄自動安裝、在管理員上傳 ZIP,以及用 SFTP 手動把解壓後的外掛資料夾放到 wp-content/plugins [4]。按下 Install Now 時,WordPress 會下載、解包及安裝;這個流程需要對 plugins 目錄有適當的建立/寫入權限。

但「需要寫入」不等於「要讓 web server 永久、廣泛地寫入程式碼目錄」。如果外掛是由部署流程管理,較合理的做法是由 CI/SFTP/主機工具以受控帳戶安裝,而不是把 plugins 變成任何人都可寫。相反,若主機的設計就是由 PHP 帳戶管理外掛,則要按該主機的 ownership 模式處理,而不是從 uploads 的權限推論。

外掛安裝失敗也不一定是 mode 問題。ZIP 大小、PHP upload 上限、磁碟配額、外掛目錄是否為唯讀、容器是否禁止寫入、檔案是否已存在,都可能造成失敗。先看實際錯誤與日誌,再決定是否涉及權限。

FTP/SSH 憑證提示代表甚麼?

WordPress 的 Filesystem API 會在偵測到「寫入檔案的擁有者不匹配」時,改用 FTP 或類似方法;在這種情況下,外掛或主題可能需要向使用者要求 FTP 憑證 [2]。你在管理員看到憑證畫面,代表 WordPress 沒有選擇 direct 寫入,不代表你應該立刻把 FS_METHOD 改成 direct。

憑證提示可能符合主機設計,也可能是 ownership 設定不如預期。正確下一步是核對 PHP runtime、plugins 目錄擁有者與主機建議的方法;不是把密碼貼進文章、設定檔、截圖或工單。若憑證曾經外洩,應依主機流程更換,而不是只改一個常數。

四、uploads:runtime 的有限寫入,不是程式碼執行區

WordPress.org 文件指出,wp-content/uploads 是 WordPress 3.5 起的預設 uploads 路徑;若啟用年份/月份分類,WordPress 會在上傳時建立對應子目錄,前提是父層可寫 [5]。這說明媒體上傳需要的是「在指定範圍內建立及寫入」,不是「整個 wp-content 都開放」。

排查媒體上傳失敗時,至少分開以下幾層:

  1. 路徑:實際 uploads 路徑是預設值,還是被常數/外掛/主機工具改到別處?
  2. 父層與目錄:父層是否可寫?年份/月份子目錄是否存在?擁有者是否正確?
  3. runtime:PHP 以哪個帳戶運行?它是否 owner、同 group,或取得 ACL 權限?
  4. 資源:磁碟配額、PHP upload 上限、記憶體、圖片處理函式庫是否足夠?
  5. 外部層:是否使用 CDN、物件儲存、媒體卸載外掛或唯讀容器?錯誤可能不是本機 mode。

另外,「可上傳」不等於「可執行 PHP」。uploads 是可寫入的媒體範圍,不應被當成可執行程式碼的地方;實際的 PHP 執行政策要由伺服器、WAF 或主機規則處理,並向 provider 核對。不要用放寬權限來代替上傳驗證或執行政策。

Hardening 文件亦把檔案權限視為其中一層控制,方向是把可寫範圍鎖到最小,而不是把整個內容目錄開放 [6]。

五、Filesystem API 與 FS_METHOD 的邊界

WordPress 的 Filesystem API 把本機讀寫抽象成 WP_Filesystem,支援不同主機連線方式;官方文件說它能在擁有者不匹配時改用 FTP 或類似方法,並可能要求 credentials [2]。函式參考頁列出優先次序:Direct、SSH2、FTP PHP extension、FTP sockets;有效值是 direct、ssh2、ftpext、ftpsockets [3]。

FS_METHOD 可以覆寫自動選擇,但「可以」不等於「應該」。如果 PHP 帳戶在作業系統層根本沒有寫入權限,強制 direct 不會創造權限;如果主機要求 FTP/SSH,強制 direct 只會令錯誤更難解釋。反過來,若你強制 FTP/SSH,但憑證、路徑、port 或防火牆不正確,也一樣會失敗。

因此,本文不建議直接改 FS_METHOD 作第一步。先讓 WordPress 按主機環境自動選擇,並把實際方法、錯誤與主機建議記錄下來;若 provider 有指定方法,按其文件在 staging 驗證,而不是從搜尋結果抄一個常數。

六、排查順序:先留證據,再改一條

1. 記錄症狀,而不是只記「失敗」

記下時間、操作(安裝哪個外掛/上傳哪個檔案)、完整錯誤文字、發生頁面、WordPress 版本、PHP 版本、主機方案與最近改動。若能看到,亦保存 WordPress debug log 與伺服器錯誤日誌;不要把含帳密或內部路徑的完整日誌公開貼出。

2. 記錄精確路徑與 owner/group

以下只讀檢查可在主機 shell 執行;實際 flag 可能因系統而異:

id
namei -l /actual/path/wp-content/plugins
ls -ld /actual/path/wp-content /actual/path/wp-content/plugins /actual/path/wp-content/uploads
findmnt -T /actual/path/wp-content
getfacl -p /actual/path/wp-content/uploads  # 如系統有安裝

這些輸出回答的是:路徑怎樣逐層到達、每一層誰擁有、PHP 以哪個帳戶運行、是否有 mount/ACL 限制。它們不是叫你立即改數字。

3. 對照主機 setup

把以下欄位補齊,再判斷屬哪種情境:

  • 檔案與目錄 owner/group;
  • PHP SAPI(mod_php、PHP-FPM、CGI/suexec)與實際 runtime user;
  • plugins/uploads 是否在不同 mount、不同 ACL 或不同儲存;
  • 是否有 SELinux/AppArmor、唯讀層、物件儲存、CDN 或 provider 自訂政策;
  • 主機對外掛安裝與媒體上傳的官方建議。

若任何一項不明,先問 provider;不要用「整個 wp-content 可寫」來跳過這個步驟。

4. 在 staging 做最小可回復變更

只有在證據指向某個精確路徑、且主機文件支持時,才在 staging 或備份後變更。一次只改一個範圍(例如只處理 uploads 的父層,或只處理 plugins 的部署帳戶),記錄 before/after 的 owner、group、mode、ACL 與實際測試結果。若沒有明確 rollback 方法,就不要在正式站改。

七、快速決策表

症狀先查不要先做
安裝外掛時要求 FTP/SSHPHP runtime、plugins owner/group、主機建議的 Filesystem 方法直接把 FS_METHOD 改成 direct;把密碼貼進設定或工單
上傳 ZIP 外掛失敗ZIP 大小、PHP upload 上限、磁碟配額、plugins 是否可寫/唯讀把 uploads 或整個 wp-content 改成 777
媒體上傳失敗實際 uploads 路徑、父層寫入、runtime user、配額、卸載/CDN對未知目錄做整站 chmod -R
圖片上傳成功但前台 404檔案是否真的存在、URL/路徑、rewrite、CDN/物件儲存先改權限,未檢查實際檔案與 URL
搬家後出現 0000 或不能寫新主機 owner/group、mount、ACL、provider 政策把舊主機的數字原封不動複製到新主機

八、交接時要留下甚麼

把權限問題當成一次可重現的維運事件,而不是一次性的「調好了」。交接紀錄至少包括:實際路徑、owner/group、mode、PHP runtime、Filesystem 方法、錯誤原文、測試動作、before/after、改動人、時間、備份位置、rollback 方法與 provider 工單編號。若涉及 staging,可配合上線前 staging 檢查;若近期做過更新,先看更新後安全訊號,不要把更新、權限與快取混成一個問題。需要演練回復時,另看備份還原演練。

要整理外掛安裝與 uploads 的權限邊界?

若你需要按實際主機 runtime、owner/group、mount/ACL 與 provider 規則整理排查紀錄,可聯絡 Managed-WP.™ PRO(WordPress 專業代管服務)。

聯絡 Managed-WP.™ PRO

常見問題

755/644 是否適用於所有 WordPress 主機?

不是。官方文件明言權限因主機而異,755/644 只是一般標準 setup 的對照;suexec、PHP-FPM 獨立帳戶、容器、ACL、NFS 或受管平台都可能不同。先確認 owner 與 runtime,再談數字。

外掛安裝要求 FTP/SSH,是否應把 FS_METHOD 改成 direct?

不建議把改常數當第一步。憑證提示代表 WordPress 沒有選擇 direct 寫入,原因可能是 ownership、runtime 或主機設計;先查實際帳戶與 provider 建議。強制 direct 不會創造作業系統權限。

uploads 目錄可以設 777 嗎?

不建議。777 會把寫入/執行權限開放給過多對象;官方 suexec 段落亦明確說 uploads 不應給 777。應按 runtime user、owner/group、ACL 與 provider 規則,給予指定範圍所需的最小寫入。

外掛安裝與媒體上傳可以用同一套權限嗎?

不應假設可以。plugins 是程式碼安裝路徑,uploads 是 runtime 媒體寫入路徑;兩者可能有不同擁有者、不同部署流程與不同主機政策。分開記錄,才不會為了其中一個而放寬另一個。

可以用 chmod -R 一次改好整個 wp-content 嗎?

不建議。遞迴改動會影響主題、外掛、快取、上傳與其他未知檔案,亦難以確認哪個改動真正有效或如何 rollback。應在備份與 staging 下,只針對已確認的精確路徑作最小變更。

FTP/SSH 密碼可以寫在 wp-config.php 或文章嗎?

不應把密碼寫入文章、截圖、工單或可提交的設定片段。使用主機提供的安全憑證流程或 secret 管理方式;若曾外洩,依 provider 流程更換。排查時只需記錄使用了哪種方法,不需要把憑證內容複製到交付物。

資料來源

  1. Changing File Permissions · WordPress Developer Resources;頁面標示發布 2023-03-28、更新 2026-10-14。
  2. Filesystem · WordPress Developer Resources;頁面未列明日期。
  3. get_filesystem_method() · WordPress Developer Resources;頁面未列明日期。
  4. Manage Plugins · WordPress.org Documentation;頁面標示發布 2018-10-24、更新 2026-01-10。
  5. Settings Media screen · WordPress.org Documentation;頁面標示發布 2018-11-06、更新 2024-06-08。
  6. Hardening WordPress · WordPress Developer Resources;頁面標示發布 2023-03-28、更新 2026-10-14。

編輯說明:本文由 Managed-WP.™ PRO 編輯團隊整理官方文件。權限數字與 setup 例子只作對照,不是所有主機的通用建議;本文不指示使用 777、整站遞迴改權限或直接改 FS_METHOD,也不承諾任何主機、外掛、CDN、SLA 或效能結果。實際 owner、runtime、mount、ACL 與 provider policy 應以你的主機環境為準。