Deepbeepmynd

ผมทำบล็อกนี้โดยไม่ต้องเช่า VPS Hosting แต่ใช้บริการฟรีของ Cloudflare ได้ยังไง?

Bio

เขียนไปเรื่อย เมื่ออยากเขียน บันทึกไว้เป็นไดอารี่ :P อีเมล : aun@deepbeepmynd.com

13AC49A0-C12F-4CD5-98CB-94A6682DFCD4.png

เดิมทีผมใช้ VPS เป็นทั้งที่รันเว็บไซต์ จัดการระบบหลังบ้าน และเก็บข้อมูลต่าง ๆ ซึ่งหมายความว่าผมต้องจ่ายค่าเช่าเซิร์ฟเวอร์ทุกเดือน(จริงๆใช้กับโปรเจคอื่นด้วย) ไม่ว่าในช่วงเวลานั้นจะมีคนเข้ามาใช้งานเว็บไซต์มากน้อยแค่ไหนก็ตาม เมื่อผมกลับมาทบทวนโครงสร้างของเว็บไซต์ตัวเอง จึงเริ่มตั้งคำถามครับว่า สำหรับบล็อกส่วนตัวที่มีหน้าที่หลักคือเผยแพร่บทความและเขียนไดอารี่ไปเรื่อย ๆ ผมจำเป็นต้องจ่ายเงินเพื่อเปิดเซิร์ฟเวอร์ทิ้งไว้ตลอดเวลาจริงหรือไม่ ในเมื่อสิ่งที่เว็บไซต์นี้ต้องทำส่วนใหญ่คือส่งเนื้อหาให้คนอ่าน และบทความเหล่านั้นก็ไม่ได้เปลี่ยนแปลงอยู่ตลอดเวลาอยู่แล้ว

จริงอยู่ครับ การใช้ Hosting / VPS ช่วยให้การพัฒนาและดูแลเว็บไซต์ง่ายขึ้นในหลายด้าน แต่สิ่งที่ตามมาก็คือค่าใช้จ่ายที่ต้องจ่ายอย่างต่อเนื่อง แม้จะเป็นเงินเพียงไม่กี่บาทต่อเดือน แต่สำหรับผม โจทย์ของเรื่องนี้ชัดเจนมากครับ คือผมต้องการให้เว็บไซต์ส่วนตัวแห่งนี้มีค่าใช้จ่ายเพียงค่าโดเมนเนมเท่านั้น!!! โดยไม่ต้องจ่ายเงินแม้แต่บาทเดียวสำหรับ Hosting หรือ VPS

เมื่อผมมีเป้าหมายแบบนี้ ผมจึงต้องกลับมาคิดใหม่ตั้งแต่ระดับสถาปัตยกรรมของเว็บไซต์ว่า จะออกแบบระบบอย่างไรให้สามารถเขียนบทความ จัดการเนื้อหาผ่านระบบหลังบ้าน และเผยแพร่เว็บไซต์ออกสู่สาธารณะได้ โดยไม่ต้องเช่าเซิร์ฟเวอร์ หรือใช้ ฟรีโฮสติ้งกากๆ สุดท้ายผมจึงให้ AI เข้ามาช่วยคิดและออกแบบสถาปัตยกรรมของบล็อกแห่งนี้ ตั้งแต่การเลือกใช้เทคโนโลยี การแยกหน้าที่ของแต่ละระบบ ไปจนถึงการหาวิธีนำทุกอย่างมาประกอบเข้าด้วยกันภายใต้ข้อจำกัดที่ผมตั้งไว้ครับ (ผมไม่ได้ใช้ claude นะ เพราะมันเก่งเกินไปสำหรับงานนี้!)

deepbeepmynd.com เป็นบล็อกส่วนตัวของผมที่สร้างขึ้นจากแนวคิดนี้ ผมเลือกใช้ Astro 5 ในการสร้างเว็บไซต์ โดยบทความทั้งหมดเขียนด้วย Markdown และเก็บอยู่ใน Git ครับ ส่วนหน้าตาของเว็บไซต์จะถูกสร้างออกมาเป็น HTML ตั้งแต่ขั้นตอน Build แล้วนำไฟล์ที่ได้ไปเผยแพร่ผ่าน Cloudflare ทำให้เว็บไซต์มีหน้าแรก หน้าบทความ หน้าหมวดหมู่ RSS และ sitemap โดยไม่จำเป็นต้องเปิดโปรแกรมประมวลผลเว็บไซต์ค้างไว้บนเซิร์ฟเวอร์เพื่อสร้างหน้าเหล่านี้ทุกครั้งที่มีคนเข้าชม

หากคุณเปิดเว็บไซต์ deepbeepmynd.com แล้วเข้าไปอ่านบทความสักเรื่อง สิ่งที่เกิดขึ้นเบื้องหลังไม่ได้ซับซ้อนอะไรเลย .. เพราะเบราว์เซอร์ของคุณจะได้รับหน้าเว็บที่ถูกสร้างเตรียมไว้ล่วงหน้าแล้ว และมันไม่ใช่การส่งคำขอไปให้ PHP ประมวลผล ไม่ใช่การไปดึงข้อมูลจาก MySQL หรือ PostgreSQL แล้วประกอบหน้าเว็บขึ้นมาใหม่ทุกครั้งที่มีคนเปิดอ่านนะครับ .. เนื้อหาบทความถูกเก็บไว้ในโฟลเดอร์ aaa/bbb/ccc ส่วนข้อมูลที่ใช้กำหนดรายละเอียดของเว็บไซต์ เช่น ชื่อเว็บและการตั้งค่าต่าง ๆ อยู่ใน aaa/bbb/ccc.json และเมื่อระบบสร้างเว็บไซต์เสร็จ.. เจ้า Astro ก็จะนำผลลัพธ์ทั้งหมดไปไว้ในโฟลเดอร์ dist เพื่อเตรียมเผยแพร่ต่อไปครับ

เบื้องหลังการทำงานนี้ ผมใช้ GitHub เป็นที่เก็บต้นฉบับของเว็บไซต์ โดยโปรเจกต์อยู่ใน Repository ชื่อ aunhelloworld/mynameis ของผม และเมื่อผมแก้ไขบทความหรือเปลี่ยนการตั้งค่าผ่านหน้าแอดมินที่ทำไว้ ตัวระบบจะเขียนไฟล์ที่แก้ไขกลับขึ้นไปยัง GitHub และเมื่อมี Commit ใหม่ .. เจ้า Cloudflare จะตรวจพบการเปลี่ยนแปลงและเริ่มกระบวนการ Build กับ Deploy โดยใช้คำสั่ง npm run build ตามด้วย npx wrangler deploy หลังจากนั้นประมาณหนึ่งนาที เนื้อหาเวอร์ชันใหม่ก็จะปรากฏบนหน้าเว็บไซต์นี้ครับ

สิ่งที่ผมชอบในแนวทางนี้คือ บทความไม่ได้ถูกเก็บอยู่ในฐานข้อมูลที่ต้องคอยดูแลแยกต่างหาก แต่เป็นไฟล์ Markdown ที่มีประวัติการเปลี่ยนแปลงอยู่ใน Git โดยตรง หากผมเขียนบทความผิด แก้ไขเนื้อหาบางส่วน หรืออยากย้อนกลับไปดูเวอร์ชันก่อนหน้า ก็สามารถจัดการผ่านประวัติ Commit ได้ ต้นฉบับจึงอยู่ในรูปแบบไฟล์ที่ผมเข้าถึงและนำไปใช้งานต่อได้ โดยไม่ต้องผูกเนื้อหาทั้งหมดไว้กับฐานข้อมูลของระบบใดระบบหนึ่ง

อย่างไรก็ตาม ผมไม่ได้หมายความว่าเว็บไซต์นี้ไม่มี Backend เลย เพราะในความเป็นจริง Backend ยังคงมีอยู่ครับ เพียงแต่ผมแยกหน้าที่ของมันออกจากส่วนที่คนอ่านใช้งานตามปกติ..

ตัวเว็บไซต์ที่คนทั่วไปเข้าถึงจะเน้นการส่งไฟล์ HTML ที่สร้างเสร็จแล้วผ่าน Cloudflare ส่วนที่ต้องมีตรรกะในการทำงานจริง ๆ จะอยู่ใน Cloudflare Worker ซึ่งเป็นโปรแกรมที่ทำงานเมื่อมีคำขอที่จำเป็นต้องทำงานผ่านมันครับ.. โดยผมกำหนดให้เส้นทาง หน้าระบบจัดการแอดมิน ต้องเข้ามาทำงานผ่าน Worker ก่อน ในขณะที่หน้าแรกและหน้าบทความทั่วไปสามารถส่งไฟล์สำเร็จรูปให้ผู้เข้าชมได้โดยตรงครับ

หน้าแอดมินจึงไม่ได้เป็นเว็บไซต์ PHP อีกชุดหนึ่งเหมือนระบบที่ผมเคยใช้ก่อนหน้านี้ และไม่ได้เป็นส่วนหนึ่งของหน้า Astro ที่ส่งให้คนอ่าน แต่เป็นโปรแกรมสำหรับจัดการเว็บไซต์ที่ทำงานอยู่บน Worker โดยเฉพาะ และที่เจ๋งคือ ผมยังสามารถเข้าสู่ระบบ เขียนบทความ แก้ไขข้อมูลเว็บไซต์ จัดการหมวดหมู่ และอัปโหลดไฟล์ผ่านหน้าแอดมินได้ตามปกติ เพียงแต่เบื้องหลังการทำงานเปลี่ยนไปจากเดิม (เปลี่ยนมากกกก แต่เอไอมันช่วย เลยง่ายขึ้น)

ในส่วนของการรักษาความปลอดภัย ผมกำหนดให้ระบบแอดมินมีบัญชีผู้ใช้เพียงบัญชีเดียว รหัสผ่านไม่ได้ถูกเก็บไว้เป็นข้อความธรรมดา แต่จัดเก็บในรูปแบบแฮชด้วย PBKDF2 และกำหนดให้ต้องยืนยันรหัสจาก Google Authenticator ทุกครั้งที่เข้าสู่ระบบ ส่วนเซสชันใช้คุกกี้ที่มีลายเซ็นเพื่อป้องกันการแก้ไขข้อมูลโดยไม่ได้รับอนุญาต และมีอายุ xxx ชั่วโมง นอกจากนี้ หากมีการลองเข้าสู่ระบบผิดหลายครั้ง ระบบจะล็อกการลองเข้าสู่ระบบในเบราว์เซอร์นั้นไว้ชั่วระยะเวลาหนึ่งด้วยครับ

ข้อมูลสำคัญอย่างรหัสผ่าน รหัสสำหรับยืนยันตัวตน และโทเค็นที่ใช้เชื่อมต่อกับ GitHub จะไม่ถูกเก็บไว้ใน Git แต่ตั้งค่าเป็น Secret ของ Cloudflare Worker ผ่านคำสั่ง npx wrangler secret put ซึ่งเป็นวิธีแยกข้อมูลลับออกจากซอร์สโค้ดและไฟล์ที่ใช้สร้างเว็บไซต์ หน้าแอดมินเองก็ไม่ได้เปิดให้เปลี่ยนค่าเหล่านี้ได้ตามใจชอบ ดังนั้น การแก้ไขบทความตามปกติจึงไม่เท่ากับการมีสิทธิ์เปลี่ยนข้อมูลลับที่ใช้จัดการหรือควบคุมระบบหลังบ้านครับ

เมื่อผมกดบันทึกบทความ ตัว Worker จะไม่ได้เขียนข้อมูลลงในดิสก์ของเซิร์ฟเวอร์ แต่จะเรียก GitHub API เพื่อสร้างหรือแก้ไขไฟล์ Markdown ใน Repository จากนั้นจึงปล่อยให้กระบวนการ Build และ Deploy ของ Cloudflare ทำงานต่อไป ส่วนการแก้ไขชื่อเว็บไซต์ เมนู ลิงก์ และการจัดหมวดหมู่ จะอาศัยการแก้ไขข้อมูลในไฟล์ xxxx.json เช่นเดียวกัน หากผมเปลี่ยน Slug ของหมวดหมู่ ระบบจะปรับบทความที่เกี่ยวข้องให้สอดคล้องกันภายใน Commit เดียวกันด้วยครับ

แต่ไม่ใช่ทุกอย่างที่จะต้องผ่าน GitHub เพราะรูปภาพและไฟล์ประกอบบทความมีลักษณะการใช้งานต่างออกไป ผมจึงแยกพื้นที่เก็บไฟล์ออกมาใช้ Cloudflare R2 (ฟรีด้วยนะจ้ะ ถ้าไม่เกิน10gb) โดยมี Bucket ชื่อ deepbeepmynd และเปิดให้เข้าถึงไฟล์ผ่านโดเมน files.deepbeepmynd.com รูปภาพจะถูกเก็บไว้ในโฟลเดอร์ images ส่วนไฟล์ประเภทอื่นจะอยู่ในโฟลเดอร์ files โดยกำหนดขนาดไฟล์ที่อัปโหลดได้ไม่เกิน 20 MB ต่อไฟล์

เมื่ออัปโหลดไฟล์ผ่านหน้าแอดมิน ไฟล์จะถูกส่งไปยัง R2 โดยตรงเลยครับ ลิงก์ของไฟล์ที่อัปโหลดสามารถนำไปใช้ในบทความได้ทันที เพราะโดเมนที่ใช้ให้บริการไฟล์ถูกตั้งค่าให้เข้าถึงได้จากสาธารณะครับ*(มันเป็นระบบของ Cloudflare R2 ที่เราสามารถเซ็ทโดเมนเนมได้ ยิ่งถ้าจดโดเมนกับ Cloudflare จะยิ่งง่าย)* โดยภายในหน้าเขียนบทความของผม ยังมีเครื่องมือช่วยเขียน Markdown และสามารถลากไฟล์ที่มีอยู่หรืออัปโหลดไว้แล้ว มาวางในช่องเขียนได้เลย แบบ Google Blogspot อ่ะ มันจึงทำให้การจัดการเนื้อหายังคงสะดวกครับ

หากอธิบายให้เข้าใจง่ายที่สุด .. ตัว GitHub ทำหน้าที่เก็บต้นฉบับของบทความและข้อมูลเว็บไซต์ ส่วน Cloudflare R2 ทำหน้าที่เก็บรูปภาพและไฟล์ และไอเจ้า Cloudflare Worker ก็ทำหน้าที่เป็นส่วนประมวลผลของระบบแอดมิน

ขณะที่หน้าเว็บไซต์ซึ่งคนทั่วไปเข้ามาอ่านคือผลลัพธ์ที่สร้างเสร็จแล้วจากกระบวนการ Build ครับ ซึ่งทั้งหมดนี้ทำให้ผมสามารถแยกหน้าที่ของแต่ละส่วนออกจากกันได้อย่างชัดเจน โดยไม่ต้องใช้ VPS เครื่องเดียวแบกรับทั้งเว็บไซต์ ระบบแอดมิน ฐานข้อมูล และพื้นที่เก็บไฟล์เหมือนที่ผ่านมา (แต่เรื่องเยอะมากกก)

อีกเรื่องหนึ่งที่ผมให้ความสำคัญคือค่าใช้จ่าย เพราะการเช่า VPS หมายถึงการจ่ายเงินเพื่อให้มีเครื่องหนึ่งพร้อมทำงานตลอดเวลา ไม่ว่าจะมีคนเข้าเว็บไซต์มากหรือน้อยเพียงใดก็ตาม สำหรับบล็อกส่วนตัวที่มีหน้าที่หลักคือเผยแพร่บทความ ผมมองว่าการจ่ายค่าเครื่องทั้งเดือนอาจไม่ใช่ทางเลือกที่จำเป็นเสมอไป โดยเฉพาะเมื่อเนื้อหาส่วนใหญ่สามารถสร้างเป็นไฟล์ HTML แล้วแจกซ้ำให้ผู้เข้าชมจำนวนมากได้ โดยไม่ต้องคำนวณใหม่ทุกครั้งที่มีคนเปิดหน้าเว็บ ซึ่งใครทำเว็บลักษณะนี้ ไม่ต้องไปเช่าให้เปลืองเงินครับ ยิ่งสาย Landing Page เนี่ย จะไปเช่าโฮสติ้งทำไม ทำแบบผมนี่แหละ สบายกระเป๋า แต่ แต่ แต่ ถ้าจะทำระบบหลังบ้านแบบผม แล้วจะไม่ใช้ VPS Hosting มันอาจจะซับซ้อนหน่อยนะครับ เพราะเราต้องมาเล่นแร่ แปรธาตุ อยู่พอสมควร

(ก็ใช้เอไอสิ ง่ายมาก)

สิ่งที่ยังต้องจ่ายคือค่าโดเมนและค่าใช้บริการที่เกี่ยวข้องกับ Cloudflare อย่างไรก็ตาม สำหรับเว็บไซต์เล็กๆ แบบนี้.. การใช้งานสามารถอยู่ในขอบเขตของโควต้าฟรีของ Cloudflare Workers และ R2 ได้ โดยขึ้นอยู่กับปริมาณการใช้งานจริงและเงื่อนไขของบริการ ซึ่งหน้าเว็บไซต์ที่สร้างเสร็จแล้วสามารถถูกส่งให้ผู้เข้าชมได้ซ้ำ ๆ โดยไม่ต้องเรียกใช้กระบวนการสร้างบทความใหม่ทุกครั้ง ขณะที่ค่าใช้จ่ายในการจัดเก็บและอ่านไฟล์บน R2 ก็สัมพันธ์กับการใช้งานและเงื่อนไขการคิดค่าบริการของแพลตฟอร์ม แทนที่จะเป็นการจ่ายค่าเช่าเครื่องเซิร์ฟเวอร์ทั้งเครื่องเป็นประจำ

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

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

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

ท้ายที่สุด สิ่งที่ผมทำกับ deepbeepmynd.com ไม่ใช่การพยายามทำให้เว็บไซต์ไม่มี Backend แต่เป็นการเลือกให้แต่ละส่วนทำงานเท่าที่จำเป็น ..ผมยังมี Backend สำหรับจัดการบทความและดูแลระบบ ผมยังมีพื้นที่เก็บไฟล์ และยังมีกระบวนการ Build ที่ต้องทำงานเมื่อมีการเปลี่ยนแปลง เพียงแต่ผมไม่จำเป็นต้องเปิดเซิร์ฟเวอร์แบบเดิมรอรับทุกคำขอจากผู้เข้าชมอีกต่อไปครับ

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

จากตัวอย่างเว็บไซต์ผม จะเห็นได้ว่า เว็บไซต์หนึ่งๆ นั้น ไม่จำเป็นต้องประกอบด้วยเซิร์ฟเวอร์ ฐานข้อมูล และโปรแกรมที่ทำงานค้างอยู่ตลอดเวลาเสมอไปครับ เราสามารถเลือกใช้บริการที่เหมาะสมกับหน้าที่ของแต่ละส่วน แล้วประกอบเข้าด้วยกันให้เป็นระบบเดียวได้ โดยไม่จำเป็นต้องทำทุกอย่างด้วยตัวเองบนเครื่องเซิร์ฟเวอร์เพียงเครื่องเดียว (แม้ว่าจะเช่า โฮสติ้งหรือ VPS จะง่ายกว่าก็เถอะ)

deepbeepmynd.com จึงเป็นตัวอย่างของวิธีคิดที่ผมเลือกใช้กับบล็อกส่วนตัวของตัวเอง เพราะมันสอดคล้องกับสิ่งที่ผมต้องการทำจริง ๆ นั่นคือการเขียนบทความ จัดการเนื้อหา เก็บต้นฉบับอย่างเป็นระบบ และเผยแพร่เว็บไซต์โดยมีภาระในการดูแลโครงสร้างพื้นฐานให้น้อยที่สุดเท่าที่จะทำได้ครับ!!!