ไฟล์ .htaccess (Hypertext Access) คือไฟล์ configuration ขนาดเล็กที่ Apache Web Server อ่านแบบ per-directory — ทุกครั้งที่มี HTTP request เข้ามา Apache จะตรวจสอบ .htaccess ใน directory นั้นพร้อมกับทุก parent directory ตลอดเส้นทาง ทำให้เจ้าของเว็บไซต์สามารถปรับแต่งพฤติกรรม server ได้โดยไม่ต้องมีสิทธิ์แก้ httpd.conf หลัก
ใน Shared Hosting และ DirectAdmin Hosting .htaccess จึงเป็นเครื่องมือหลักที่นักพัฒนาเว็บและผู้ดูแลระบบใช้ทำ URL Redirect, บังคับ HTTPS, ตั้ง Browser Cache, เปิด GZIP Compression, เพิ่ม Security Headers และแก้ปัญหาด้านประสิทธิภาพต่างๆ บทความนี้รวม .htaccess Commands ที่ใช้บ่อยที่สุดในโลกจริงสำหรับ WordPress และ PHP Web Application พร้อมคำอธิบายและตัวอย่างที่ทดสอบแล้วบน Apache 2.4
พื้นฐาน .htaccess ก่อนเริ่มใช้งาน
ก่อนเพิ่ม directive ใดๆ ลงใน .htaccess ควรทำความเข้าใจหลักการทำงานพื้นฐาน 3 ข้อ:
- Apache อ่าน .htaccess ทุก request — ต่างจาก httpd.conf ที่โหลดครั้งเดียวตอน start server .htaccess ถูก parse ใหม่ทุก request จึงแก้แล้วเห็นผลทันทีโดยไม่ต้อง restart server แต่ก็มีผลต่อ performance เล็กน้อยถ้ามี rule มากเกินไป
- Scope ของ .htaccess ครอบคลุม subdirectory — ไฟล์ .htaccess ใน
/public_html/มีผลกับทุก URL บนเว็บ แต่ถ้าสร้าง .htaccess ใน/public_html/blog/จะ override เฉพาะ URL ที่อยู่ใต้ /blog/ เท่านั้น - AllowOverride ต้องเปิด — หาก server config ตั้ง
AllowOverride NoneApache จะไม่อ่าน .htaccess เลย บน Shared Hosting ส่วนใหญ่รวมถึง DirectAdmin Hosting จะเปิด AllowOverride ไว้แล้ว ถ้าใส่ directive แล้วไม่ทำงาน ให้ตรวจจุดนี้ก่อน
บรรทัดที่ขึ้นต้นด้วย # คือ comment ไม่มีผลต่อการทำงาน ควรใส่ comment ไว้เสมอเพื่อให้ทราบว่า block นั้นทำอะไร โดยเฉพาะเมื่อมีหลาย rule รวมกัน
WordPress Permalink — .htaccess มาตรฐาน
WordPress ใช้ mod_rewrite เพื่อ route ทุก request ที่ไม่ตรงกับไฟล์หรือ directory จริงไปยัง index.php ซึ่งเป็นกลไกหลักของ WordPress Routing System block นี้ WordPress Dashboard จะเขียนให้อัตโนมัติเมื่อตั้งค่า Permalinks แต่ควรรู้ว่าแต่ละบรรทัดทำอะไร:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
คำอธิบายแต่ละบรรทัด: RewriteBase / กำหนด base path สำหรับ relative rule — ถ้า WordPress อยู่ใน subdirectory เช่น /blog/ ต้องเปลี่ยนเป็น RewriteBase /blog/ และแก้ RewriteRule . /blog/index.php [L] ด้วย RewriteCond %{REQUEST_FILENAME} !-f และ !-d หมายถึง "ถ้าไม่ใช่ไฟล์จริงและไม่ใช่ directory จริง ค่อย route ไป index.php" ทำให้ไฟล์ static เช่น .jpg, .css, .js ยังเสิร์ฟได้ปกติ
ถ้า WordPress อยู่ใน subdirectory เช่น https://example.com/wp/ ต้องเปลี่ยน block ให้ตรงกับ path จริง:
# BEGIN WordPress (installed in /wp/)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /wp/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /wp/index.php [L]
</IfModule>
# END WordPress
GZIP Compression — ลดขนาดไฟล์ถ่ายโอน
GZIP Compression ช่วยลดขนาดไฟล์ HTML, CSS, JavaScript และ XML ก่อนส่งจาก server ไปยัง browser ได้ถึง 60-80% ทำให้หน้าโหลดเร็วขึ้นมากโดยเฉพาะบนการเชื่อมต่อที่ช้า บน Apache ใช้ mod_deflate:
<IfModule mod_deflate.c> # บีบอัด text-based content AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/xml AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE application/xml AddOutputFilterByType DEFLATE application/xhtml+xml AddOutputFilterByType DEFLATE application/rss+xml AddOutputFilterByType DEFLATE application/javascript AddOutputFilterByType DEFLATE application/x-javascript AddOutputFilterByType DEFLATE application/json # ไม่บีบอัดไฟล์ที่บีบแล้ว SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|svg|ico|zip|gz|bz2|mp4|mp3)$ no-gzip dont-vary </IfModule>
ตรวจสอบว่า GZIP ทำงานหรือยังด้วยคำสั่ง: curl -H "Accept-Encoding: gzip" -I https://example.com/ ถ้า response header มี Content-Encoding: gzip แสดงว่าเปิดใช้งานแล้ว
Browser Caching — ลด Request ซ้ำ
Browser Caching กำหนดให้ browser เก็บ static files เช่น รูปภาพ CSS JS ไว้ใน cache เพื่อไม่ต้อง download ซ้ำในการเยี่ยมชมครั้งถัดไป ช่วยลด bandwidth และเพิ่มความเร็วโหลดหน้าอย่างมีนัยสำคัญ ใช้ mod_expires:
<IfModule mod_expires.c> ExpiresActive On ExpiresDefault "access plus 1 month" # รูปภาพ — cache 1 ปี ExpiresByType image/jpeg "access plus 1 year" ExpiresByType image/png "access plus 1 year" ExpiresByType image/gif "access plus 1 year" ExpiresByType image/webp "access plus 1 year" ExpiresByType image/svg+xml "access plus 1 year" ExpiresByType image/x-icon "access plus 1 year" # CSS และ JavaScript — cache 1 เดือน ExpiresByType text/css "access plus 1 month" ExpiresByType application/javascript "access plus 1 month" ExpiresByType application/x-javascript "access plus 1 month" # Font files — cache 1 ปี ExpiresByType font/woff2 "access plus 1 year" ExpiresByType font/woff "access plus 1 year" ExpiresByType application/font-woff2 "access plus 1 year" # HTML และ XML — cache สั้น ExpiresByType text/html "access plus 1 hour" ExpiresByType application/xml "access plus 0 seconds" ExpiresByType application/rss+xml "access plus 1 hour" </IfModule> <IfModule mod_headers.c> Header append Cache-Control "public" </IfModule>
Tip สำคัญ: ถ้าอัพเดต CSS หรือ JS แล้วผู้ใช้ยังเห็นเวอร์ชันเก่าเนื่องจาก cache ให้ใช้ Cache Busting — เพิ่ม query string ต่อท้าย URL เช่น style.css?v=20260609 browser จะมองว่าเป็นไฟล์ใหม่และ download ใหม่โดยไม่ต้องรอ cache หมดอายุ
Security Headers และการป้องกัน WordPress
Security Headers ช่วยป้องกันช่องโหว่ด้านความปลอดภัยหลายประเภทโดยไม่ต้องแก้ code ใน application เลย เหมาะมากสำหรับ WordPress ที่มักตกเป็นเป้าหมายของการโจมตี:
<IfModule mod_headers.c> # ป้องกัน Clickjacking Header always set X-Frame-Options "SAMEORIGIN" # ป้องกัน MIME Type Sniffing Header always set X-Content-Type-Options "nosniff" # XSS Protection (legacy browsers) Header always set X-XSS-Protection "1; mode=block" # Referrer Policy Header always set Referrer-Policy "strict-origin-when-cross-origin" # บังคับ HTTPS (HSTS) — ตั้งค่าหลังมั่นใจว่า HTTPS ทำงานปกติ Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" </IfModule>
บล็อก xmlrpc.php (WordPress)
xmlrpc.php เป็นไฟล์ที่ WordPress ใช้สำหรับ remote publishing และ Jetpack แต่มักถูกใช้เป็นช่องโจมตีแบบ Brute Force และ DDoS ถ้าไม่ได้ใช้ควรบล็อกทิ้ง:
# บล็อก xmlrpc.php <Files xmlrpc.php> Order Deny,Allow Deny from all </Files>
บล็อก PHP ใน /uploads/ (WordPress)
ไดเรกทอรี uploads/ ไม่ควรสามารถ execute PHP file ได้ เพราะถ้า attacker อัพโหลด PHP ไฟล์ปลอมปน image ได้จะสามารถรันคำสั่งบน server ได้ ให้สร้าง .htaccess แยกใน wp-content/uploads/.htaccess:
# ป้องกัน PHP execution ใน uploads/ <FilesMatch "\.php$"> Order Allow,Deny Deny from all </FilesMatch>
การตั้งค่า PHP ผ่าน .htaccess
บน Shared Hosting ที่ไม่มีสิทธิ์แก้ php.ini โดยตรง สามารถ override ค่า PHP บางตัวผ่าน .htaccess ได้ ขึ้นอยู่กับว่า Hosting อนุญาตหรือไม่ (DirectAdmin Hosting ของ AsiaGB รองรับ):
# เพิ่ม PHP memory limit php_value memory_limit 256M # เพิ่ม max upload file size php_value upload_max_filesize 64M php_value post_max_size 64M # เพิ่ม max execution time (วินาที) php_value max_execution_time 300 # ซ่อน PHP error ในหน้าเว็บ (production) php_flag display_errors Off # เปิด error logging (log ไปยัง error_log แทน) php_flag log_errors On # ตั้ง timezone php_value date.timezone "Asia/Bangkok" # ป้องกัน session hijacking php_value session.cookie_httponly 1 php_value session.cookie_secure 1
ถ้าใส่ php_value แล้วเกิด 500 Error แสดงว่า Hosting นั้นไม่อนุญาต PHP override ผ่าน .htaccess ให้ลองใช้ไฟล์ php.ini หรือ user.ini ใน root directory แทน
Custom Error Pages
การตั้ง Custom Error Pages ทำให้ผู้ใช้เห็นหน้า error ที่สวยงามและมี navigation กลับสู่เว็บแทนหน้า error มาตรฐานของ server ซึ่งดูไม่เป็นมิตรและอาจเปิดเผยข้อมูล server:
# Custom Error Pages ErrorDocument 400 /error/400.html ErrorDocument 401 /error/401.html ErrorDocument 403 /error/403.html ErrorDocument 404 /error/404.html ErrorDocument 500 /error/500.html
สำหรับ WordPress ให้ใช้หน้า 404 ของ WordPress แทน เพราะ WordPress มีระบบ routing ของตัวเอง การ override ErrorDocument 404 นอก WordPress block อาจทำให้ WordPress 404 handler ไม่ทำงาน
ป้องกัน Hotlinking และจำกัดการเข้าถึง
Hotlinking คือการที่เว็บอื่นโหลดรูปภาพจากเซิร์ฟเวอร์ของคุณโดยตรง ทำให้ bandwidth หมดโดยไม่ได้ประโยชน์ ป้องกันได้ด้วย mod_rewrite:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?yourdomain\.com [NC]
RewriteRule \.(jpg|jpeg|png|gif|webp|svg)$ - [F,NC]
</IfModule>
บรรทัดที่ 2 อนุญาตให้เข้าถึงได้ถ้า Referer ว่างเปล่า (เช่น พิมพ์ URL โดยตรงหรือ curl) บรรทัดที่ 3 อนุญาตเฉพาะ request จากโดเมนของคุณเอง flag [F] ส่ง 403 Forbidden แทนที่จะ serve ไฟล์
บล็อก User-Agent ที่ไม่พึงประสงค์
<IfModule mod_rewrite.c>
RewriteEngine On
# บล็อก bot/scanner ที่รู้จัก
RewriteCond %{HTTP_USER_AGENT} (nikto|sqlmap|netsparker|acunetix|dirbuster) [NC]
RewriteRule .* - [F,L]
</IfModule>
ตารางสรุป .htaccess Commands ที่ใช้บ่อยที่สุด
ตารางนี้รวมคำสั่งสำคัญพร้อมวัตถุประสงค์และ module ที่ต้องการ ใช้เป็น quick reference เมื่อต้องการค้นหาคำสั่งที่ใช่:
| Category | คำสั่ง / Directive | Module | วัตถุประสงค์ |
|---|---|---|---|
| Redirect | Redirect 301 |
mod_alias | ย้าย URL ถาวร รักษา SEO |
| Rewrite | RewriteRule / RewriteCond |
mod_rewrite | เปลี่ยน URL pattern, WordPress routing |
| GZIP | AddOutputFilterByType DEFLATE |
mod_deflate | บีบอัดไฟล์ก่อนส่ง ลด bandwidth |
| Cache | ExpiresByType |
mod_expires | กำหนดอายุ browser cache |
| Headers | Header always set |
mod_headers | Security headers, CORS, HSTS |
| PHP | php_value / php_flag |
mod_php | Override php.ini สำหรับ directory นั้น |
| Access | Order Deny,Allow / <Files> |
mod_access | จำกัดการเข้าถึงไฟล์หรือ IP |
| Error | ErrorDocument |
core | กำหนดหน้า error ที่กำหนดเอง |
Best Practices และข้อควรระวัง
การใช้ .htaccess อย่างถูกต้องจะช่วยให้เว็บทำงานได้ดีขึ้น แต่ถ้าตั้งค่าผิดอาจทำให้เว็บล่มได้ทันที ควรปฏิบัติตามแนวทางต่อไปนี้เสมอ:
- Backup ก่อนแก้เสมอ — ดาวน์โหลดไฟล์ .htaccess ปัจจุบันไว้ก่อนทุกครั้ง ถ้าแก้แล้วพังสามารถ upload คืนได้ทันที
- ทดสอบบน staging ก่อน — สำหรับเว็บที่ traffic สูง ควรทดสอบ .htaccess บน dev environment ก่อน deploy ขึ้น production
- ใช้ IfModule เสมอ — ครอบทุก block ด้วย
<IfModule mod_xxx.c>เพื่อป้องกัน 500 Error เมื่อ module นั้นไม่ได้ติดตั้ง - ตรวจ Error Log หลังแก้ — ถ้าเกิด error ใดๆ Apache จะบันทึกใน error_log ซึ่งดูได้จาก DirectAdmin → Logs → Error Log
- ลำดับ rule สำคัญ — Apache ประมวลผลจากบนลงล่าง rule ที่กว้างกว่าควรอยู่บน rule เฉพาะเจาะจงควรอยู่ล่างและใช้ flag
[L]เพื่อหยุดการประมวลผลหลัง match - ระวัง Redirect Loop — ตรวจสอบ rule ทุกตัวว่าไม่มีการ loop ก่อน deploy โดยเฉพาะ rule ที่ redirect จาก HTTP ไป HTTPS และจาก www ไป non-www พร้อมกัน
- ล้าง Browser Cache หลังแก้ — 301 Redirect ถูก cache ใน browser ทดสอบในโหมด Incognito เสมอเพื่อผลที่ถูกต้อง
- จำกัด PHP override — ใช้ php_value เฉพาะค่าที่จำเป็น เช่น memory_limit หรือ upload_max_filesize ค่าที่เกี่ยวกับ security ควรตั้งผ่าน php.ini ของ server แทน
คำถามที่พบบ่อย (FAQ)
.htaccess ใช้กับ Hosting ทุกประเภทได้ไหม
.htaccess ใช้ได้เฉพาะ Hosting ที่ใช้ Apache Web Server เท่านั้น ซึ่งครอบคลุม Shared Hosting และ VPS ส่วนใหญ่รวมถึง DirectAdmin Hosting ของ AsiaGB หาก Hosting ใช้ Nginx จะต้องใส่ directive ใน nginx.conf แทน และถ้าใช้ LiteSpeed Server จะรองรับ .htaccess เหมือน Apache เกือบทั้งหมด
แก้ .htaccess แล้วเว็บขึ้น 500 Internal Server Error ต้องทำอย่างไร
500 Error จาก .htaccess มักเกิดจาก syntax ผิด เช่น directive สะกดผิด, flag ขาดวงเล็บ [L] หรือ mod_rewrite ยังไม่ได้เปิด ให้ตรวจ Error Log ใน DirectAdmin (Logs > Error Log) เพื่อดู error message จริง หรือใช้คำสั่ง curl -I เพื่อดู HTTP status และ header response ก่อนแก้ไข และควร Backup .htaccess เดิมไว้ก่อนทุกครั้ง
WordPress ต้องการ .htaccess แบบพิเศษอะไรบ้าง
WordPress ต้องการ RewriteRule สำหรับ Permalink ซึ่ง WordPress Dashboard (Settings > Permalinks) จะสร้าง .htaccess block ให้อัตโนมัติ นอกจากนี้ยังนิยมเพิ่ม GZIP Compression เพื่อลดขนาดไฟล์, Browser Caching เพื่อเพิ่มความเร็ว, บล็อก xmlrpc.php เพื่อป้องกัน brute force และบล็อก .php execution ใน /uploads/ เพื่อป้องกัน malware upload
ไฟล์ .htaccess หลายไฟล์ใน subdirectory ต่างกันอย่างไรจาก root
Apache ประมวลผล .htaccess ตั้งแต่ root ลงมาถึง directory ของ request นั้น ทุก .htaccess ในเส้นทางจะถูกรวมกัน โดยไฟล์ที่อยู่ลึกกว่าจะ override ไฟล์บน สำหรับ WordPress ควรให้ root .htaccess จัดการ RewriteRule ส่วน subdirectory เช่น /uploads/ มี .htaccess แยกเพื่อบล็อก PHP execution เท่านั้น การแยกไฟล์แบบนี้ช่วยให้ดูแลรักษาง่ายกว่าใส่ทุกอย่างในที่เดียว
Hosting DirectAdmin ครบชุดของ AsiaGB
AsiaGB Hosting รองรับ DirectAdmin เต็มรูปแบบ PHP 8.3 MySQL เริ่มต้น 500 บาท/ปี
ดูแพ็กเกจ Hosting