
本篇主題同詩意副標 — 在 Windows 的角落,種了一棵 WordPress。Windows Server 上跑 WordPress 不是主流選擇,網路上中文教程清一色 LAMP / LEMP 棧,Windows 圈在 WordPress 這個議題上算是塊冷門山頭。但我手邊既有的環境就是 Windows Server 2022,自架站時不想為了 WP 重學一套 Linux,所以走上了 IIS + PHP 8 這條相對冷門的路。本片的目的是把這條路的全貌走一遍,給未來的我、給同樣在 Windows 圈想架 WP 的工程師、也給想理解「自架站到底在搞什麼」的客戶。
2025 年底,我決定為自己的 freelance 工作室架一個自有網站。選 WordPress 而不是 Next.js / Astro,是因為 WordPress 對非工程師客戶友善 — 他們之後可以自己改文案、自己上架文章,不用每次找我;社群外掛多,訂閱表單、聯絡表單、SEO 工具一應俱全;12 年累積的內容生態系,不容易被取代。選 self-host 而不是 wp.com 託管,則是因為要客製化 child theme、要綁自己的 SMTP、要自由換 plugin,託管版本綁手綁腳。
至於環境 — 我手邊有一台 Windows Server 2022 的機器,過去三年都在這台機器上做 .NET / SQL Server 的開發,Linux 反而是我陌生的環境。「直接用既有的環境」是合理的決定。雖然網路上 WordPress 教程清一色 Apache + Linux,Windows 圈中文教程稀少,但路是走出來的。
IIS 10:Microsoft 出的 web server,Windows Server 內建。GUI 操作直觀,相比 nginx / Apache 的文字檔配置,IIS 對 Windows 工程師更熟悉。但 PHP 不是它的主場,要自己掛 FastCGI handler。
PHP 8.x:WordPress 6.x 後最低支援版本。在 Windows 上跑 PHP 通常用 php-cgi.exe + FastCGI 模式,不像 Linux 走 php-fpm。
URL Rewrite Module:IIS 預設沒有的擴充,要從 Microsoft 官網下載安裝。WordPress 的 permalink rewrite 完全靠它。
MySQL 8:資料庫。Windows 版安裝很順,沒什麼好說。
WordPress 6.9.4:本片主角,跑得起來就贏一半。
web.config:IIS 的 .htaccess。XML 格式。WordPress 沒附現成的 web.config,要自己寫(或從網路上找模板,但網路上的模板大多 outdated)。
心得我分三條講,因為這 12 個小時裡 8 小時在順流,4 小時在踩坑。
第一條:Handler Mapping 不對,所有 .php 都返 404
第一個坑出現在 WordPress 解壓到 wwwroot 之後。我打開 localhost/wp-admin,期待看到安裝精靈,看到的卻是:
HTTP Error 404.0 - Not Found
The resource you are looking for has been removed,
had its name changed, or is temporarily unavailable.
我以為是檔案路徑錯了,檢查 wwwroot 下確實有 wp-admin/index.php,但任何 .php request 都吃 404。回頭看 IIS Manager,Handler Mappings 列表裡 — 沒有任何 .php 對應。
原來 IIS 預設不認識 PHP,要手動加一條 Handler Mapping:
Request path: *.php
Type: Module Mapping
Module: FastCgiModule
Executable: C:php8php-cgi.exe
加完之後,wp-admin 跳出來,我感動了 30 秒。
第二條:wp-content 上傳失敗 — 權限地獄
第二個坑來自 WordPress 上傳圖片時跳出:
抱歉,目前無法將檔案 logo.png 移動到 wp-content/uploads/
第一反應是磁碟空間問題,檢查發現空間還有 200GB。第二反應是 PHP upload_max_filesize 設太小 — 不是,設的是 32MB。第三反應才想到:Windows 的權限系統。
IIS 預設執行身份是一個叫做 IIS_IUSRS 的 group,任何被 IIS 跑的 PHP 程序都是用這個身份。我去 wp-content/uploads 資料夾右鍵 → 內容 → 安全性,發現 IIS_IUSRS 沒有寫入權限,只有讀取。手動勾上「修改」,問題解決。
Windows 的權限系統
比 Linux 多一層
也多一個地雷區
附帶一提,在 Linux 上同樣的問題會出現在 chmod 755 / 775 / chown www-data 之間的選擇,只是介面從 GUI 變成 terminal,本質都一樣 — 「web server 是用什麼身份跑的,那個身份能不能寫入這個資料夾。」
第三條:web.config 是個無人區
WordPress 官方文件對 web.config 著墨不多,因為他們的主流用戶在 Apache。所以我的 web.config 是參考了 Microsoft 官方 IIS docs + WordPress wiki 的 stub + Stack Overflow 三個來源拼出來的。簡單版只要兩個區塊 — <rewrite> 區塊處理 permalink,<staticContent> 區塊處理 image MIME types(包括 IIS 預設不認識的 .webp,如果你打算用 WebP)。完整 web.config 放在文末彩蛋。
至於 Linux 工程師會問的「中文 URL 怎麼處理?」 — IIS 預設會把中文 URL encode 成 %e6%b8%ac 形式,WordPress 端再 decode 回中文。看似可怕但其實 WordPress 自動處理,我沒有為這件事多寫一行 code。
走了 12 個小時,中文教程網路上找到的不超過 10 篇,但 WordPress 在 IIS 上跑得很穩 — 上線一個多月,沒有因為 IIS 本身的原因掛過。
「在 Windows 的角落,我種了一棵 WordPress」這句副標講的不是炫技,而是 LAMP 浪潮下,Windows 圈還是有一片屬於自己的微冷山頭。如果你也在 Windows Server 環境,或公司既有 IT 是 Windows-based,WordPress 不會是你的阻礙。
如果你公司既有 Windows Server 想架 WP,但不想自己處理 Handler Mapping、權限地獄、web.config — 找我。我能幫你無痛接上。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="WordPress" patternSyntax="Wildcard">
<match url="*"/>
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true"/>
</conditions>
<action type="Rewrite" url="index.php"/>
</rule>
</rules>
</rewrite>
<staticContent>
<mimeMap fileExtension=".webp" mimeType="image/webp" />
</staticContent>
</system.webServer>
</configuration>
直接 copy 進你的 wwwroot 根目錄就能跑。
好了 IIS 沒有那麼難 真的! (ˇωˇ人)