Build APM บน Windows: สารบัญ ทำ Apache + PHP 8.4 + MariaDB เอง
XAMPP ในเครื่องผมยังเป็น PHP 8.2.12 จากปี 2023 ขณะที่ PHP เพิ่งออกแพตช์ช่องโหว่ RCE ระดับวิกฤตไปเมื่อวาน ผมเลยทำ stack ของตัวเองขึ้นมาจาก source ชื่อ APM แล้วเขียนทุกขั้นตอนไว้ให้คนที่ไม่เคยคอมไพล์โปรเจกต์ C/C++ ทำตามได้
พอดีเมื่อวาน (21 ตุลาคม 2026) PHP ออกแพตช์ช่องโหว่ RCE ระดับวิกฤตสองตัว คือ CVE-2026-109618 กับ CVE-2026-109619 หรือชื่อเล่นว่า php2shell คะแนน CVSS 9.2 รุ่นที่แก้แล้วคือ 8.4.27, 8.3.36, 8.2.35 และ 8.5.12 รายละเอียดผมเขียนไว้ในบทความ PHP มีช่องโหว่ RCE ระดับวิกฤตสองตัว อัปเดตด่วนวันนี้ ผมเปิดเครื่อง Windows ที่ใช้เขียนโค้ดขึ้นมาดู ก็เจอว่า XAMPP ที่ลงไว้ยังเป็น PHP 8.2.12, Apache 2.4.58 และ MariaDB 10.4 ทั้งหมดเป็นของปี 2023
ปัญหาไม่ได้อยู่ที่ XAMPP ไม่ดี แต่อยู่ที่ว่าชุดสำเร็จรูปแบบนี้ตามหลัง upstream อยู่เสมอ ผมรอ bundle รุ่นใหม่ไม่ได้ เพราะวันที่ช่องโหว่ออก คือวันที่ผมอยากอัปเดตเครื่องของผมเอง ผมเลยทำ web stack ของตัวเองบน Windows จาก source code ต้นทางทั้งหมด ตั้งชื่อว่า APM (Apache, PHP, MariaDB) แล้วออกแบบให้เวลามี security release ผมแก้เลขเวอร์ชันในไฟล์เดียวชื่อ versions.json แล้วสั่ง build ใหม่ได้ในวันเดียวกัน
ซีรีส์นี้เขียนจากการ build จริงเมื่อ 22 ตุลาคม 2026 บน Windows 11 (i5-12500H, RAM 32 GB) ทุกผลลัพธ์ในซีรีส์เป็นของที่วัดจริง ถ้าตรงไหนผมไม่ได้เก็บ output ไว้ ผมจะบอกว่าให้ตรวจอะไรแทนที่จะเดาตัวอักษรให้
APM คืออะไร และสุดท้ายได้อะไร
APM ไม่ใช่โปรแกรมใหม่ มันคือชุดสคริปต์ PowerShell กับไฟล์ตั้งค่า (เรียกรวมว่า build kit) ที่ดาวน์โหลด source ของแต่ละตัว ตรวจ hash แล้วคอมไพล์ด้วย MSVC ผลที่ได้คือโฟลเดอร์ C:\APM หน้าตาเหมือน XAMPP แต่ทุกอย่างเป็นรุ่นล่าสุดที่เลือกเองและตรวจสอบที่มาได้
PHP ที่ build ได้มี 51 module ตรงกับชุดที่ผมใช้บนเครื่อง production ยกเว้น posix, sysvmsg, sysvsem และ sysvshm ซึ่ง Windows ไม่มี รวม PECL อีกสามตัวคือ redis, igbinary และ imagick PHP ทำงานผ่าน mod_fcgid ไม่ใช่ mod_php ส่วน OpenSSL ฝั่ง Apache เลือกสาย 3.5 LTS ซึ่งได้ซัพพอร์ตถึงเมษายน 2030
เส้นทางของ request หนึ่งครั้งเป็นแบบนี้ และโฟลเดอร์ที่ deploy แล้วอยู่ใต้ C:\APM ตามที่เห็นในผัง
พอร์ตเริ่มต้นเลือก 8080, 8443 และ 3307 เพื่อไม่ชนกับ XAMPP ที่ยังรันอยู่บนเครื่องเดียวกัน (XAMPP ใช้ 80, 443 และ 3306) ใครเลิกใช้ XAMPP แล้วเปลี่ยนเป็นพอร์ตมาตรฐานได้ตอน deploy ซึ่งผมจะอธิบายในตอนที่ 7
ใช้เวลาและพื้นที่เท่าไร
ตัวเลขนี้สำคัญกว่าที่คิด เพราะ build ครั้งแรกกินเวลาหลายชั่วโมง ถ้าเครื่องหลับหรือดิสก์เต็มกลางทางจะเสียเวลาเปล่า ตั้ง power plan ให้เครื่องไม่หลับก่อนเริ่ม และเช็กพื้นที่ว่างก่อน
| รายการ | ค่า | หมายเหตุ |
|---|---|---|
| พื้นที่ว่างที่ต้องมี | อย่างน้อย 60 GB | ที่ผมใช้จริงประมาณ 45 GB รวมเครื่องมือ |
| ดาวน์โหลดรวม | ประมาณ 3-4 GB | source, toolchain, ลิบรารีจาก vcpkg |
| เวลา build ครั้งแรก | ประมาณ 2.5 ชั่วโมง | ผลรวมของแต่ละขั้นอยู่ในช่วง 134-156 นาที |
| เวลา build ซ้ำ (cache ยังอยู่) | ประมาณ 10 นาที | วัดจริง fetch 0.0, vcpkg 0.1, apache 1.6, mariadb 0.3, imagemagick 3.3, php 5.0 |
| ขนาดหลัง deploy | ประมาณ 650 MB | apache 20 + php 124 + mariadb 201 + data 302 |
| สิทธิ์ admin | ใช้ตอนติดตั้งเครื่องมือเท่านั้น | ตัว build และ deploy รันเป็น user ปกติ |
ดาวน์โหลดและตรวจ build kit
kit เป็นไฟล์ zip ขนาดราว 47 KB (47 ไฟล์) ที่รวมสคริปต์ทั้งหมด versions.json และไฟล์ตั้งค่า ทำตามนี้ในลำดับเดียว
เปิด pwsh ปกติ (ไม่ต้อง admin) แล้วทำทีละข้อ
- ดาวน์โหลดไฟล์ด้วยคำสั่งในบล็อกถัดไป (หรือเปิด URL ในเบราว์เซอร์แล้วเซฟลงโฟลเดอร์ Downloads ก็ได้)
- เช็กขนาดไฟล์ ต้องได้ 48142 ไบต์
- คำนวณ sha256 แล้วเทียบกับค่าที่ผมประกาศไว้ ต้องเป็น True
- ยังไม่ต้องแตกไฟล์ในตอนนี้ การแตกไฟล์ลง `C:\apm-build` อยู่ในตอนที่ 1 หลังติดตั้งเครื่องมือครบ
curl.exe -L -o "$env:USERPROFILE\Downloads\apm-build-kit.zip" https://linuxthai.org/files/apm-build-kit.zip
(Get-Item "$env:USERPROFILE\Downloads\apm-build-kit.zip").Length
Get-FileHash "$env:USERPROFILE\Downloads\apm-build-kit.zip" -Algorithm SHA256
ผลที่ต้องเห็นคือ ขนาดไฟล์ 48142 และตาราง hash ที่ค่า Hash เป็นตัวพิมพ์ใหญ่ตามนี้
Algorithm Hash Path
--------- ---- ----
SHA256 24BA604D8EE0F355F14C61C948C616FBDB9F97A0A75FC4955BCC64CD939D6206 C:\Users\<you>\Downloads\apm-build-kit.zip
ถ้าไม่อยากเทียบด้วยตา ให้ PowerShell เทียบให้ (การเทียบสตริงใน PowerShell ไม่สนตัวพิมพ์เล็กใหญ่) ต้องได้ True
(Get-FileHash "$env:USERPROFILE\Downloads\apm-build-kit.zip" -Algorithm SHA256).Hash -eq '24BA604D8EE0F355F14C61C948C616FBDB9F97A0A75FC4955BCC64CD939D6206'
hash ที่ประกาศอยู่ในหน้าเดียวกับไฟล์ ช่วยจับไฟล์เสียหรือโหลดไม่ครบได้ แต่ไม่ได้พิสูจน์ว่าเว็บที่แจกไฟล์ไม่ถูกแก้ สิ่งที่คุ้มครองคุณจริงคือการเปิดอ่านสคริปต์ก่อนรัน ทั้งชุดเป็นข้อความธรรมดาไม่กี่ร้อยบรรทัด และซีรีส์นี้พาอ่านทุกไฟล์ที่มีผลต่อระบบ ให้รันเฉพาะสิ่งที่คุณอ่านแล้วเข้าใจ
อัปเดต kit 22 ต.ค. 2026 (บ่าย)
สคริปต์ build ต้นทางถูกแก้ต่อหลังเขียนซีรีส์ ผมเลยสร้าง kit ใหม่จากสคริปต์รุ่นล่าสุด ขนาด 48142 ไบต์ 47 ไฟล์ มีไฟล์ใหม่คือ LICENSE (ติดตั้งเป็น C:\APM\LICENSE.txt), scripts\trust-ca.ps1, scripts\new-cert.ps1, scripts\firewall-lan.ps1 และ scripts\set-path.ps1 ส่วน versions.json มี "apm_version": "1.0.0" เป็นคีย์แรก รวม 14 เรื่องที่แก้ แต่ละเรื่องอยู่ในตอนที่ระบุ
| # | แก้อะไร | อาการเดิม | อยู่ในตอน |
|---|---|---|---|
| 1 | หา Visual Studio 2022 ด้วย vswhere ทุก edition ทุกที่ติดตั้ง | เดิมฝังพาธ Build Tools ไว้ ถ้าลงเป็น Community หรือคนละไดรฟ์ จะขึ้นว่าไม่พบ C++ tools | ตอนที่ 1, ตอนที่ 3, ตอนที่ 4, ตอนที่ 5 |
| 2 | 00-fetch.ps1 -Only php,httpd ใช้ได้กับ pwsh -File แล้ว |
เดิมคอมมาในค่า -Only ถูกตีความผิด ต้องเลี่ยงด้วย -Command |
ตอนที่ 2, ตอนที่ 7 |
| 3 | ซอร์ส PECL ถูกลบแล้วคัดลอกใหม่ลง build\php-pecl\<ext> ทุกรอบ |
เดิมคัดลอกครั้งเดียว แก้เลขเวอร์ชัน PECL แล้ว build ได้ของเก่าเงียบ ๆ | ตอนที่ 6, ตอนที่ 7 |
| 4 | โฟลเดอร์ lib ถูกเก็บไว้ตอน deploy ตัดเฉพาะไฟล์ *.lib |
ปลั๊กอิน MariaDB (ha_archive, auth_ed25519 ฯลฯ) หายหลัง deploy เพราะ /XD lib ตัด mariadb\lib\plugin ทิ้ง |
ตอนที่ 4, ตอนที่ 7 |
| 5 | deploy.cmd -ResetConfig ทับ data\mysql\my.ini ด้วย |
เดิมเปลี่ยนพอร์ตฐานข้อมูลแล้ว -ResetConfig ไม่มีผล เพราะ server อ่านไฟล์ใน data\mysql |
ตอนที่ 4, ตอนที่ 7 |
| 6 | OPcache แยก cache_id ต่อโฟลเดอร์ พร้อม file cache ใน tmp\opcache |
รัน APM สองโฟลเดอร์พร้อมกันแล้วทุกหน้า PHP ขึ้น 500 End of script output before headers (php-cgi -v ขึ้น ASLR) |
ตอนที่ 6, ตอนที่ 7 |
| 7 | FcgidWrapper ใส่เครื่องหมายคำพูดครอบพาธ php-cgi.exe |
ติดตั้งในพาธที่มีช่องว่าง Apache ฟ้อง Wrapper D:/APM cannot be accessed |
ตอนที่ 3, ตอนที่ 7 |
| 8 | mkcert ใส่เครื่องหมายคำพูดให้ extension_dir และเช็กว่า openssl โหลดอยู่ |
พาธมีวงเล็บเช่น (copy) ขึ้น Undefined constant OPENSSL_KEYTYPE_EC |
ตอนที่ 7 |
| 9 | ออก cert เซิร์ฟเวอร์ใหม่ตอน -ResetConfig หรือ -Lan (CA เดิม) |
cert เดิมไม่มีชื่อเครื่องกับ IP ใน LAN เบราว์เซอร์เตือนเมื่อเข้าจากเครื่องอื่น | ตอนที่ 7 |
| 10 | สวิตช์ -Lan ให้ Apache ฟังที่ 0.0.0.0 (MariaDB ยัง 127.0.0.1) ใช้คู่กับ scripts\firewall-lan.ps1 |
เดิมเข้าจากเครื่องอื่นในวงไม่ได้ ต้องแก้ httpd.conf เอง | ตอนที่ 7 |
| 11 | ?info=1 แสดง phpinfo เฉพาะจาก 127.0.0.1 / ::1 |
เครื่องอื่นในวง LAN เห็น phpinfo ได้ถ้าเปิดเซิร์ฟเวอร์ให้เข้าจากภายนอก | ตอนที่ 7 |
| 12 | deploy ไม่ยอมรันถ้าบริการ Windows APM-Apache / APM-MariaDB ยังทำงาน |
บริการที่มาจาก APM Manager ล็อกไฟล์ ทำให้ deploy ทับไฟล์ไม่ครบ | ตอนที่ 7 |
| 13 | deploy คัดลอก templates\ กับ tools\ ลง C:\APM และพิมพ์ httpd.conf Listen: ตอนจบ |
ไม่มีเทมเพลตให้ใช้ซ้ำหลัง deploy และดูไม่ออกว่า Apache ผูกที่ไหน | ตอนที่ 7 |
| 14 | สคริปต์ช่วยใหม่ trust-ca.ps1, new-cert.ps1, set-path.ps1 |
เดิมต้องทำเอง: เชื่อ CA ผ่าน certmgr, ออก cert ให้ vhost, ตั้ง PATH | ตอนที่ 1, ตอนที่ 7 |
ให้โหลดใหม่ แล้วรัน deploy.cmd -ResetConfig ถ้ายังไม่เคยแก้ config เอง ถ้าแก้ไว้แล้ว ให้ก๊อปบรรทัดที่เปลี่ยนไปใส่ด้วยมือ คือ PidFile, FcgidWrapper และค่า opcache รายละเอียดอยู่ในตอนที่ 7
ทางลัดสามคำสั่ง สำหรับคนที่เครื่องมือพร้อมแล้ว
ถ้าติดตั้ง Visual Studio Build Tools, Git, CMake, Ninja และ PowerShell 7 ครบแล้ว (ตอนที่ 1 พาทำ) และแตก kit ไว้ที่ C:\apm-build แล้ว ทั้งระบบเหลือสามคำสั่ง ทุกคำสั่งรันใน pwsh ปกติ ไม่ใช้ admin
- Build ทั้งระบบลงโฟลเดอร์ `stage\` ใช้เวลาประมาณ 2.5 ชั่วโมงในครั้งแรก
- Deploy ลง `C:\APM` สร้าง config, cert และ data directory โดยยังไม่ start อะไร
- Start MariaDB กับ Apache แล้วทดสอบด้วย curl
cd C:\apm-build
.\build.cmd
ระหว่าง build สคริปต์พิมพ์สถานะเป็นช่วง ๆ ในรูปแบบนี้ ถ้าเห็น [ERR] ให้หยุดอ่าน log ในโฟลเดอร์ build\logs\ อย่าเพิ่งรันต่อ
==== fetch ====
...
==== fetch done in 0.0 min ====
==== vcpkg ====
ถ้าอยากหยุดหลังขั้นใดขั้นหนึ่ง ใช้ .\build.cmd -To <ขั้น> ได้ ขั้นที่มีคือ fetch vcpkg apache mariadb imagemagick php (ทำต่อทีหลังด้วย -From)
เมื่อ build จบ ต่อด้วย deploy ผลที่ต้องเห็นบรรทัดสุดท้ายคือ [OK] APM deployed to C:\APM (http :8080, https :8443, db :3307) - not started
.\deploy.cmd
จากนั้น start MariaDB แล้ว Apache ผมวัดผลจริงเมื่อ 22 ตุลาคม 2026 ได้ดังนี้ (ตอนที่ 7 อธิบายทีละบรรทัดและวิธีหยุด)
Start-Process C:\APM\mariadb\bin\mariadbd.exe -ArgumentList '--defaults-file=C:\APM\data\mysql\my.ini'
C:\APM\mariadb\bin\mariadb.exe -uroot --port=3307 --protocol=tcp -e "select version(), @@collation_server, @@have_ssl, @@bind_address"
Start-Process C:\APM\apache\bin\httpd.exe
curl.exe -s -o NUL -w "%{http_code} %{content_type}`n" http://127.0.0.1:8080/
curl.exe -sk -o NUL -w "%{http_code}`n" https://localhost:8443/
version() @@collation_server @@have_ssl @@bind_address
11.8.9-MariaDB-log utf8mb4_unicode_ci YES 127.0.0.1
200 text/html; charset=UTF-8
200
หน้าแรกของเซิร์ฟเวอร์ที่ http://127.0.0.1:8080/ แสดงเวอร์ชัน PHP 8.4.27 พร้อมสถานะ OPcache JIT เวอร์ชัน MariaDB และรายชื่อ extension ที่โหลดอยู่ ใส่ ?info=1 ต่อท้ายเพื่อดู phpinfo()
ทางลัดสามคำสั่งใช้ได้ต่อเมื่อเครื่องมือครบและติดตั้งถูกที่ ถ้า Visual Studio ขาด component ปัญหาจะไปโผล่ที่ขั้น ImageMagick ซึ่งเป็นขั้นที่สี่ของลำดับ build หลังผ่านไปแล้วราว 80 นาที ถ้าไม่เคยคอมไพล์โปรเจกต์ C/C++ บน Windows มาก่อน ให้เริ่มจากตอนที่ 1 แล้วไล่ไปตามลำดับ ซีรีส์นี้ไม่ใช่เอกสาร reference แต่เขียนให้อ่านจากบนลงล่าง
สารบัญทั้งซีรีส์
ทุกตอนมีรูปแบบเดียวกัน คือขั้นตอนมีเลขกำกับ บอกว่ารันใน terminal ไหนและโฟลเดอร์ไหน ผลลัพธ์ที่ต้องเห็น วิธีตรวจว่าสำเร็จ ส่วน "ถ้าพังตรงนี้" และเช็กลิสต์ท้ายตอน
| ตอน | เรื่อง | ลิงก์ |
|---|---|---|
| 1 | เตรียมเครื่องมือ: Visual Studio Build Tools, Git, CMake, Ninja, PowerShell 7, Defender, แตก kit, ทัวร์ versions.json |
apm-build-windows-1-prepare-tools |
| 2 | ดาวน์โหลด source (sha256 กับ trust-on-first-use) และ build ลิบรารีของ Apache ด้วย vcpkg | apm-build-windows-2-fetch-vcpkg |
| 3 | Apache httpd 2.4.69 กับ mod_fcgid: ทุก option ของ CMake และการไล่ DLL | apm-build-windows-3-apache |
| 4 | MariaDB 11.8 LTS: option, ทดสอบที่พอร์ต 3399, การล็อก collation | apm-build-windows-4-mariadb |
| 5 | ImageMagick 7: toolchain ทางการ, patch channel mask 32 bit, ข้อจำกัด HEIC | apm-build-windows-5-imagemagick |
| 6 | PHP 8.4 NTS กับ PECL: configure ทั้งบรรทัดแยกเป็นกลุ่ม, ทดสอบ extension และ JIT | apm-build-windows-6-php |
| 7 | Deploy ลง C:\APM, start ครั้งแรก, ทดสอบ, วิธีลงแพตช์ความปลอดภัยรอบถัดไป, ตารางแก้ปัญหา | apm-build-windows-7-deploy-run-update |
ตอนที่ 7 มีส่วนที่ตอบโจทย์ตั้งต้นของซีรีส์โดยตรง คือ เมื่อ PHP ออกรุ่นใหม่ ต้องทำอะไรบ้าง สั้นที่สุดคือ แก้ version, url และ sha256 ของ PHP ใน versions.json แล้วรัน 00-fetch.ps1 -Only php กับ 30-php.ps1 -Step all แล้ว deploy ใหม่ ไม่ต้อง build Apache หรือ MariaDB ซ้ำ
ใครไม่ควรทำแบบนี้
การ build เอง ได้ความเร็วในการอัปเดตกับการรู้ที่มาของทุกไบนารี แต่ต้องจ่ายด้วยเวลา พื้นที่ และความรับผิดชอบดูแลเอง ผมเขียนเปรียบเทียบให้ตรง ๆ
ต้องการคุมเวอร์ชันเอง
ต้องอัปเดตให้ทันวันที่มี security release ต้องการ extension ชุดเดียวกับเครื่อง production ต้องการรู้ว่า binary มาจาก source ไหน hash อะไร หรือแค่อยากเข้าใจว่า stack ประกอบกันอย่างไร
แค่อยากได้ PHP รุ่นใหม่
ถ้าต้องการเพียง PHP ใหม่ ให้ใช้ไบนารีทางการของ PHP สำหรับ Windows และ MariaDB ที่แจก installer เอง ส่วน Apache httpd โครงการเองแจกเฉพาะ source เลยต้องพึ่งไบนารีจากบุคคลที่สาม ถ้าไม่มีเวลาดูแลสองถึงสามชั่วโมงต่อการ build ใหม่ อย่าเริ่ม ใครอยากได้แค่ไบนารีที่ build เสร็จแล้ว ไปโหลดจาก GitHub Releases ได้เลย ดูกล่อง "ไม่อยาก build เอง" ท้ายหน้านี้
ส่วนตัวผมมองว่า ถ้าเว็บของคุณรันบน Linux เป็นหลัก การมี Windows stack ไว้ทดสอบให้เวอร์ชันตรงกับ production ก็เพียงพอแล้ว ไม่ต้องไล่ทุก patch release ภายในวัน แต่ถ้าเครื่อง Windows เปิดพอร์ตสู่อินเทอร์เน็ต การอัปเดตให้ทันคือเรื่องที่เลื่อนไม่ได้
เรื่องที่ซีรีส์นี้ยังไม่ครอบคลุมคือการติดตั้งเป็น Windows Service และการจัด vhost ผ่านเครื่องมือควบคุมชื่อ apmctl ซึ่งจะแยกเป็นบทความต่างหากภายหลัง ผมไม่ได้ใส่คำสั่งของมันไว้ในที่นี้เพราะยังไม่เสร็จ ตอนนี้ start กับ stop ด้วยมือตามที่เขียนในตอนที่ 7
ใครอยากได้ APM ไปใช้เลยโดยไม่ต้องคอมไพล์ ผมปล่อยตัวที่ build เสร็จแล้วไว้ที่ github.com/ChonLaWan/APM-Server โหลด APM-1.0.0-win64.zip (ราว 140 MB) จากหน้า Releases เทียบ sha256 กับไฟล์ .sha256 ที่แนบไว้ แตกไว้ที่ไหนก็ได้ แล้วเปิด manager\APMManager.exe ตัว Manager จะเลือกพอร์ต เขียน config ออก cert และสร้างฐานข้อมูลให้เอง มีปุ่ม Check for updates ที่โหลดรุ่นใหม่จาก Releases มาตรวจ sha256 แล้วแทน binary ให้ โดยไม่แตะ config ฐานข้อมูล และเว็บของเรา
สารบัญ (หน้านี้) · ตอนถัดไป: ตอนที่ 1 เตรียมเครื่องมือและแตก kit
ถ้าติดขัดตรงไหนของตอนไหน บอกได้เลยว่าเจอ error อะไรและรันคำสั่งอะไรอยู่ เดี๋ยวกลับมาแก้เพิ่มให้ภายหลังครับ
อยากให้เราทำให้ไหม?
ให้เราช่วยติดตั้ง ตั้งค่า ย้ายระบบ หรือแก้ปัญหาเซิร์ฟเวอร์ เพื่อให้คุณมีเวลาไปทำงานที่สำคัญกว่า
เคยเจองานแบบนี้ไหม? ติดตรงไหน?
มาแลกวิธีกันต่อในบอร์ด LinuxThai



ความคิดเห็น 0
ยังไม่มีความคิดเห็น — เป็นคนแรกเลย