EST. 2026 — บันทึกงานเซิร์ฟเวอร์จริง SYSADMIN · SECURITY · AI · DIRECTADMIN เล่มที่ 01
THE SYSADMIN ALMANAC
หน้าหลัก / แท็ก / Laravel
Laravel

#Laravel

27 บทความ
Web / CMS
ผ่าน sandbox ไม่ได้แปลว่าใช้ได้จริง — สัญญาณหลอก 7 แบบ
Linux

ผ่าน sandbox ไม่ได้แปลว่าใช้ได้จริง — สัญญาณหลอก 7 แบบ

ระบบสั่งซื้ออัตโนมัติที่ผมเขียนผ่าน sandbox ของผู้ให้บริการครบทุกคำสั่ง แต่เกือบทุกอย่างที่ sandbox บอกเป็นคนละเรื่องกับของจริง ทั้งเวลาตอบกลับ ยอดที่ถูกตัด ชื่อที่ใช้ได้ และรายการที่สร้างสำเร็จแต่ค้นไม่เจอ รวมสัญญาณหลอก 7 แบบพร้อมวิธีเขียนโค้ดให้ไม่หลงเชื่อ

#api#rest-api#testing#debugging
อ่าน 9 นาที·26 ต.ค.
หน้าเว็บว่างเปล่า ไม่มี error สักบรรทัด เพราะตั้งชื่อฟังก์ชันว่า top
Web

หน้าเว็บว่างเปล่า ไม่มี error สักบรรทัด เพราะตั้งชื่อฟังก์ชันว่า top

deploy ขึ้นไปแล้วหน้าว่าง ไม่มี error ในล็อก ไม่มีอะไรผิดใน node --check แต่เบราว์เซอร์ฆ่าทั้งสคริปต์ตั้งแต่บรรทัดแรกเพราะมีฟังก์ชันชื่อ top ไปชนกับ window.top พร้อมรายชื่อที่ต้องเลี่ยง กับดักลำดับการโหลดสคริปต์ และด่านตรวจด้วย Playwright ที่ควรมีทุกโปรเจกต์

#javascript#debugging#troubleshooting#playwright
อ่าน 8 นาที·18 ต.ค.
เขียนค่าลง DirectAdmin ตอนที่ API มีแต่ฝั่งอ่าน ต้องขับฟอร์มของแผงเอง
DirectAdmin

เขียนค่าลง DirectAdmin ตอนที่ API มีแต่ฝั่งอ่าน ต้องขับฟอร์มของแผงเอง

บันทึกการทำให้แอปหลังบ้านสร้างและแก้แพ็กเกจโฮสติ้งบน DirectAdmin ได้ ทั้งที่ CMD_API ตัวทางการมีแต่คำสั่งอ่าน ต้อง POST เข้าฟอร์มของแผงควบคุมเอง พร้อมกฎการยืนยันผลที่ห้ามใช้ regex และสวิตช์ตัดวงจรสองชั้นที่ปิดไว้เป็นค่าตั้งต้น

#directadmin#shared-host#php#laravel
อ่าน 9 นาที·14 ต.ค.
ดูดเมลเข้าระบบโดยไม่ทำลายกล่องจดหมายของคนอื่น
Linux

ดูดเมลเข้าระบบโดยไม่ทำลายกล่องจดหมายของคนอื่น

กล่องเมลที่แอปจะไปดึงของ เป็นกล่องที่คนใช้งานอยู่จริงทุกวัน — ดึงด้วย UNSEEN คือเมลหายเงียบเมื่อเจ้าของเปิดอ่านบนมือถือก่อน cron วิธีที่ถูกคือ UID SEARCH คู่กับ UIDVALIDITY และ BODY.PEEK พร้อมการกันซ้ำที่ต้องทำฝั่งเราเอง

#mail#imap#pop3#dovecot
อ่าน 10 นาที·13 ต.ค.
อ่านจากฐานสำรอง ต้องมีป้ายบอกว่าข้อมูลเก่ากี่นาที
Linux

อ่านจากฐานสำรอง ต้องมีป้ายบอกว่าข้อมูลเก่ากี่นาที

replication บอกว่าตามหลัง 0 วินาทีได้ทั้งที่ข้อมูลค้างอยู่เมื่อวาน เพราะสองสัญญาณนี้วัดคนละเรื่องกัน — วิธีตั้งตัวเฝ้าที่เทียบทั้ง Seconds_Behind_Master และความสดของข้อมูลธุรกิจ พร้อมจับคนที่แอบเขียนลง slave และตัวเฝ้าที่เฝ้าตัวเฝ้าอีกชั้น

#mariadb#mysql#monitoring#alerting
อ่าน 9 นาที·12 ต.ค.
ให้ AI อ่านเอกสาร แต่ให้โค้ดเป็นคนคิดเลข
AI

ให้ AI อ่านเอกสาร แต่ให้โค้ดเป็นคนคิดเลข

controller บังคับให้คนกรอกอยู่ในช่วง 0 ถึง 100 แต่เส้นทางที่ AI อ่านค่าจากเอกสารแล้วป้อนเข้ามาตรวจแค่ว่าเป็นตัวเลข ค่าติดลบตัวเดียวดันผลลัพธ์ขึ้นไป 5.25 เท่าโดยไม่มี error — บทเรียนเรื่องการมองเอาต์พุตของ AI เป็น input ที่ไม่น่าเชื่อถือเท่ากับที่คนกรอก

#ai#llm#claude#claude-code
อ่าน 10 นาที·12 ต.ค.
แอปเป็น UTC คนคิดเป็นเวลาไทย — เพี้ยน 7 ชั่วโมงแบบไม่มี error
Linux

แอปเป็น UTC คนคิดเป็นเวลาไทย — เพี้ยน 7 ชั่วโมงแบบไม่มี error

ตั้งเวลาเผยแพร่ไว้บ่ายสาม ของขึ้นจริงสี่ทุ่ม ไม่มี error ไม่มี log อะไรผิด เพราะแอปเก็บเป็น UTC แต่คนกรอกคิดเป็นเวลาไทย บทความนี้ไล่ตั้งแต่ค่าที่ตั้งใน env แล้วไม่มีผล ไปจนถึงบรรทัดเดียวที่เขียนหน้าปัดไทยลงคอลัมน์ที่ทุกคนอ่านเป็น UTC

#laravel#php#mariadb#debugging
อ่าน 9 นาที·11 ต.ค.
ไฟล์ลับคุม 600 ครบ แต่ log 0644 ถูกอัปออกนอกเครื่องทุกคืน
Security

ไฟล์ลับคุม 600 ครบ แต่ log 0644 ถูกอัปออกนอกเครื่องทุกคืน

เข้ารหัส .env เรียบร้อย คุมสิทธิ์ไฟล์ลับครบทุกตัว แต่ข้อมูลลูกค้ายังรั่วออกนอกเครื่องทุกคืนผ่านทางที่ไม่มีใครจัดว่าเป็นความลับ นั่นคือไฟล์ log ที่อ่านได้ทั้งเครื่องและถูกมัดรวมขึ้น object storage พร้อม backup พร้อมวิธีปิดที่ต้นทางด้วยการ log แค่รหัสผลลัพธ์

#security#logging#backup#offsite
อ่าน 10 นาที·10 ต.ค.
เว็บกับคิวคนละผู้ใช้ — mkdir 0700 ฆ่า default ACL ทิ้งทั้งโฟลเดอร์
Linux

เว็บกับคิวคนละผู้ใช้ — mkdir 0700 ฆ่า default ACL ทิ้งทั้งโฟลเดอร์

แอปตัวเดียวแต่รันด้วยสองผู้ใช้ ฝั่งเว็บเป็น php-fpm ฝั่งคิวเป็นอีกบัญชีหนึ่ง ตั้ง default ACL ไว้ครบแล้วยังเขียนข้ามกันไม่ได้ ต้นเหตุคือ mkdir โหมด 0700 ที่ไปตั้ง mask ทับจนสิทธิ์ ACL หายเกลี้ยง พร้อมกับดักเรื่องลบไฟล์ที่ต้องมีสิทธิ์ที่โฟลเดอร์ ไม่ใช่ที่ไฟล์

#linux#permissions#posix-acl#php-fpm
อ่าน 9 นาที·9 ต.ค.
tinker ส่งเมลผ่าน แต่เว็บส่งไม่ออก — proc_open ที่ปิดอยู่ใน FPM
DirectAdmin

tinker ส่งเมลผ่าน แต่เว็บส่งไม่ออก — proc_open ที่ปิดอยู่ใน FPM

ทดสอบส่งเมลจาก tinker ผ่านฉลุย แต่พอกดจากฟอร์มจริงกลับไม่มีอะไรออกเลย และ mail log ไม่มีสักบรรทัด — เพราะ CLI กับ PHP-FPM ไม่ใช่ PHP ตัวเดียวกัน พร้อมสูตร SMTP AUTH ที่ใช้ได้จริงบนโฮสต์ DirectAdmin และกฎเรื่อง From ที่ห้ามพลาด

#mail#smtp#laravel#php
อ่าน 9 นาที·8 ต.ค.
deploy แล้วเว็บไม่อัปเดต — ไล่แคชห้าชั้นให้จบในครั้งเดียว
DirectAdmin

deploy แล้วเว็บไม่อัปเดต — ไล่แคชห้าชั้นให้จบในครั้งเดียว

อัปไฟล์ขึ้นแล้ว เปิดดูยังเป็นของเก่า กด Ctrl+F5 ก็ยังเก่า — เพราะระหว่างไฟล์บนดิสก์กับสิ่งที่คนเห็นมีแคชคั่นอยู่ห้าชั้น แต่ละชั้นล้างคนละวิธี บทความนี้คือลำดับล้างที่ผมใช้ประจำ พร้อมกับดักที่ทำให้เว็บ 500 ค้างหลังสั่งล้าง view cache

#deployment#laravel#php#php-fpm
อ่าน 10 นาที·8 ต.ค.
route:cache แล้วทุก GET กลายเป็น 405 — กับดักแอปใต้ sub-path
DirectAdmin

route:cache แล้วทุก GET กลายเป็น 405 — กับดักแอปใต้ sub-path

deploy เสร็จ กด optimize ตามคู่มือ แล้วทุกหน้าตอบ 405 Method Not Allowed ทั้งที่ route:list ยืนยันว่า route ถูกต้อง — เรื่องของ route cache ที่พังเฉพาะบางเครื่อง วิธีแยกให้ขาดใน 30 วินาที และของแถมอีกสามอย่างที่เจอพร้อมกันตอนเอาแอปไปวางใต้ sub-path

#laravel#php#deployment#apache
อ่าน 9 นาที·7 ต.ค.
php -l ผ่าน แต่หน้าเว็บ 500 — ประตูตรวจก่อน commit ที่คอมไพล์จริง
Linux

php -l ผ่าน แต่หน้าเว็บ 500 — ประตูตรวจก่อน commit ที่คอมไพล์จริง

เทมเพลตพังสองรอบในเดือนเดียวทั้งที่ php -l ผ่านหมด เพราะ php -l ไม่รู้จักไวยากรณ์ของ Blade บทความนี้คือประตูตรวจ 6 ด่านที่ผมวางไว้ก่อน commit — คอมไพล์ view จริงแล้ว lint ไฟล์ที่คอมไพล์ออกมาซ้ำอีกชั้น พร้อมสคริปต์กวาด GET ทุก route ผ่าน Kernel

#laravel#php#blade#testing
อ่าน 9 นาที·7 ต.ค.
งานที่ยิงออกนอกระบบ ต้องจองสถานะก่อนยิงเสมอ
Linux

งานที่ยิงออกนอกระบบ ต้องจองสถานะก่อนยิงเสมอ

guard แบบ "อ่านสถานะแล้วค่อยยิง" ดูปลอดภัยจนถึงวันที่ worker โดนฆ่าหลังยิงแต่ก่อนเขียนฐานข้อมูล แล้ว retry ก็ยิงซ้ำให้ลูกค้าเห็นของสองรอบ บทความนี้คือชุดกันซ้ำทั้งชุดที่ผมใช้ ตั้งแต่การจองแบบ atomic ไปจนถึง retry_after กับ failed() ที่ห้ามทับสถานะที่สำเร็จแล้ว

#laravel#php#queue#worker
อ่าน 11 นาที·6 ต.ค.
โค้ดชุดเดียวสองบทบาท เว็บอยู่โฮสต์ worker อยู่เครื่องที่บ้าน
Linux

โค้ดชุดเดียวสองบทบาท เว็บอยู่โฮสต์ worker อยู่เครื่องที่บ้าน

ระบบทั้งตัวเคยวิ่งอยู่บนเครื่องเดียวหลังเน็ตบ้าน เครื่องดับทีเดียวทีมใช้อะไรไม่ได้เลย ผมเลยแยกเป็นสองบทบาทด้วยโค้ดชุดเดิม — เว็บอยู่โฮสต์ที่เปิดตลอด งานหนักอยู่เครื่องที่บ้านแล้ววิ่งมาดึงงานเอง พร้อมตาราง claim แบบ atomic และแผนสลับ 18 ขั้นที่มีทางถอย

#laravel#php#queue#worker
อ่าน 12 นาที·6 ต.ค.
โฮสต์ static บน DirectAdmin แล้ว GET ได้ 404 แต่ HEAD ได้ 200
DirectAdmin

โฮสต์ static บน DirectAdmin แล้ว GET ได้ 404 แต่ HEAD ได้ 200

อัปเว็บ static ขึ้น public_html แล้วเปิดไม่ได้ ไฟล์เล็กออกปกติ ไฟล์ใหญ่ 404 แต่ยิง HEAD กลับได้ 200 ทุกไฟล์ ต้นเหตุคือ .htaccess ของ Laravel ที่นั่งอยู่ที่ docroot ดูดทุกอย่างเข้า front controller บทความนี้เล่าทั้งการวินิจฉัยและทางออกสามทาง

#directadmin#cloudflare#apache#htaccess
อ่าน 9 นาที·14 ก.ย.
audit ระบบ prod ที่มีข้อมูลลูกค้าจริง โดยไม่ทิ้งขยะสักแถว
Linux

audit ระบบ prod ที่มีข้อมูลลูกค้าจริง โดยไม่ทิ้งขยะสักแถว

เจ้าของระบบสั่งให้ทดสอบทั้งระบบบนเครื่องจริงที่มีข้อมูลลูกค้าอยู่ แล้วห้ามเหลือแถวขยะไว้แม้แถวเดียว วิธีที่ผมใช้คือ bootstrap Laravel เองแล้วเรียก controller ตรง ๆ ใน transaction ที่ rollback ทิ้ง พร้อมนับ COUNT ทุกตารางก่อนและหลังเป็นหลักฐาน

#laravel#php#mysql#mariadb
อ่าน 11 นาที·13 ก.ย.
มี backup ครบทุกไฟล์ แต่สร้างเครื่องใหม่ไม่ได้
Backup

มี backup ครบทุกไฟล์ แต่สร้างเครื่องใหม่ไม่ได้

dump ฐานข้อมูลครบ tar โค้ดครบ ไฟล์ความลับครบ แต่พอเอาไปวางบนเครื่องเปล่าแล้วเว็บไม่ขึ้น เพราะของที่ทำให้เครื่องทำงานได้จริงไม่เคยอยู่ในไฟล์ backup เลย บทความนี้คือรายการของที่หายไปกับเครื่อง และลำดับกู้ที่ผมเขียนไว้ให้ตัวเองในอนาคต

#backup#disaster-recovery#systemd#debian
อ่าน 11 นาที·12 ก.ย.
ออกใบเสนอราคา PDF ภาษาไทยจาก HTML ด้วย Chromium และกับดักที่เจอ
Linux

ออกใบเสนอราคา PDF ภาษาไทยจาก HTML ด้วย Chromium และกับดักที่เจอ

ทำระบบออกใบเสนอราคาเป็น PDF จาก HTML ด้วย Chromium ให้รองรับหลายบริษัทในเครือและหลายเทมเพลต ตั้งแต่ error Executable doesn't exist ที่ไปหยิบ headless shell ผิดตัว การจัด A4 กับแบ่งหน้า การ sanitize ชื่อไฟล์ภาษาไทย จนถึงระบบเลขเอกสารแบบ token ที่เผลอใส่ slash แล้ว path พัง

#pdf#chromium#playwright#python
อ่าน 9 นาที·31 ส.ค.
ย้ายการคำนวณจาก PHP ไปทำในเบราว์เซอร์: 12 วินาที เหลือ 12 มิลลิวินาที
Linux

ย้ายการคำนวณจาก PHP ไปทำในเบราว์เซอร์: 12 วินาที เหลือ 12 มิลลิวินาที

หน้าเดียวยิง subquery หลักหมื่นครั้งจนโหลดนาน 12 วินาที ผมแก้ด้วยการทำตารางสรุปไว้ล่วงหน้า ส่ง dataset ก้อนเดียว 107 KB แล้วย้ายสูตรไปคำนวณในเบราว์เซอร์ เหลือ 12 มิลลิวินาที พร้อม parity test ที่บังคับให้ผลฝั่ง JS ตรงกับ PHP ทุกแถว

#performance#php#javascript#laravel
อ่าน 9 นาที·29 ส.ค.
เก็บ secret ใน .env แบบเข้ารหัส แล้วถอดอัตโนมัติตอน config โหลด
Security

เก็บ secret ใน .env แบบเข้ารหัส แล้วถอดอัตโนมัติตอน config โหลด

วิธีเก็บรหัสผ่านและ API key ใน .env ของ Laravel เป็น ciphertext แล้วให้ config ถอดกลับเองตอนโหลด ด้วย helper ตัวเดียวที่ตรวจเองว่าค่าไหนเข้ารหัสไว้ พร้อมกับดัก APP_KEY ต่าง environment ที่ทำให้ระบบล่มทั้งชุดถ้าพลาด

#laravel#php#security#encryption
อ่าน 9 นาที·18 ส.ค.
คิวงาน Laravel บน shared host — อย่าเอาคิวไว้ Redis ตัวเดียวกับ cache
Linux

คิวงาน Laravel บน shared host — อย่าเอาคิวไว้ Redis ตัวเดียวกับ cache

จะเปิด queue ให้ Laravel บน shared host แล้วคิดจะแยก REDIS_DB ให้คิวอยู่คนละเบอร์กับ cache — ไม่ช่วยครับ เพราะ maxmemory กับ eviction เป็นของทั้ง instance ไม่ใช่ของราย DB บทความนี้เล่าเหตุผลที่ผมเลือก database driver แทน พร้อม systemd unit เต็ม ๆ ที่ใช้แทน Supervisor

#laravel#redis#queue#systemd
อ่าน 10 นาที·17 ส.ค.
Laravel หลัง proxy เห็น IP เป็น 127.0.0.1 — ฟอร์มเงียบ ไม่มี error
DirectAdmin

Laravel หลัง proxy เห็น IP เป็น 127.0.0.1 — ฟอร์มเงียบ ไม่มี error

ฟอร์มติดต่อบน DirectAdmin กดส่งแล้วขึ้นว่าไม่ใช่คน เมลไม่ออก แต่ log ทุกชั้นเงียบสนิท — ต้นเหตุคือ Laravel หลัง nginx-to-apache เห็น $request->ip() เป็น 127.0.0.1 ทำให้ด่านตรวจบอทไม่ผ่านแล้ว return ก่อนถึงบรรทัดส่งเมล พร้อมเหตุผลว่าทำไม TrustProxies ห้ามใส่ '*'

#laravel#php#nginx#php-fpm
อ่าน 9 นาที·16 ส.ค.
WAF ตอบ 406 เพราะข้อความไทยใน POST — แก้ยังไงเมื่อไม่ใช่ root
Security

WAF ตอบ 406 เพราะข้อความไทยใน POST — แก้ยังไงเมื่อไม่ใช่ root

ModSecurity บนโฮสต์ตอบ 406 ใส่ข้อความไทยบางประโยคใน POST body ทำให้ฟอร์มบันทึกไม่ได้ — แต่เราเป็นแค่ผู้เช่า แก้ rule เองไม่ได้ บทความนี้คือวิธี isolate หาท่อนที่โดนแบบ black-box แล้วอ้อมด้วย JS encode ตอน submit + middleware decode กลับฝั่ง Laravel

#modsecurity#waf#laravel#php
อ่าน 9 นาที·15 ส.ค.
นำเข้าไฟล์ .xls จากระบบเก่าหลายร้อยไฟล์ลง Laravel ด้วย PhpSpreadsheet
Linux

นำเข้าไฟล์ .xls จากระบบเก่าหลายร้อยไฟล์ลง Laravel ด้วย PhpSpreadsheet

ไฟล์ .xls จากระบบเก่าที่หัวตารางภาษาไทยเป็น tis-620 อ่านชื่อคอลัมน์ไม่ได้ ไฟล์ใหญ่ทำ PhpSpreadsheet กิน memory จนล้ม และไฟล์ที่ผู้ใช้รวมเองก็มีแถวซ้ำในตัวเอง — เลิกอ่านชื่อคอลัมน์แล้วนับตำแหน่งแทน ใส่ read filter และกันซ้ำด้วย natural key

#php#laravel#excel#phpspreadsheet
อ่าน 9 นาที·10 ส.ค.
เครื่องในโรงงานหลัง NAT ขึ้นคลาวด์ ด้วย push snapshot + คิวคำสั่ง
Network

เครื่องในโรงงานหลัง NAT ขึ้นคลาวด์ ด้วย push snapshot + คิวคำสั่ง

เครื่องงานจริงอยู่ใน LAN หลัง NAT ไม่มี public IP แต่เจ้าของอยากดูข้อมูลบนเว็บคลาวด์และแก้ข้อมูลจากมือถือให้ลงไปถึงเครื่องใน — ทำได้โดยไม่เปิดพอร์ตไม่ตั้ง VPN ด้วย push snapshot + คิวคำสั่งแก้ + ack แบบ idempotent

#automation#networking#nat#api
อ่าน 10 นาที·9 ส.ค.
ตรวจ security เว็บ Laravel ที่ deploy แล้ว — ไล่ 3 ชั้นตามลำดับที่ควรแก้
Security

ตรวจ security เว็บ Laravel ที่ deploy แล้ว — ไล่ 3 ชั้นตามลำดับที่ควรแก้

หลัง deploy Laravel ขึ้น production ควรไล่ตรวจความปลอดภัย 3 ชั้น — external probe หา endpoint ที่รั่ว, ตรวจไฟล์/สิทธิ์บนเซิร์ฟเวอร์, แล้ว grep หาช่องในโค้ด บทความนี้ให้ชุดคำสั่งพร้อมลำดับความสำคัญ P0-P2 ที่ควรแก้ก่อนหลัง

#security#hardening#php-fpm#cloudflare
อ่าน 8 นาที·17 ก.ค.