เปรียบเทียบซอฟต์แวร์ออกใบแจ้งหนี้ Self-hosted ตัวไหนดี
เปรียบเทียบ 5 ซอฟต์แวร์ออกใบแจ้งหนี้ Invoice Ninja, InvoiceShelf, InvoicePlane, Kimai และ ERPNext บน VPS วิเคราะห์ฟีเจอร์การเรียกเก็บเงิน ภาษี และเงื่อนไขลิขสิทธิ์
คุณควรเลือกซอฟต์แวร์ออกใบแจ้งหนี้แบบ self-hosted ตัวไหน?
ซอฟต์แวร์ออกใบแจ้งหนี้แบบ self-hosted ที่ใช้งานได้จริงบน VPS หนึ่งเครื่องมีให้เลือก 5 ตัวเลือก ซึ่งแต่ละตัวมีลักษณะการใช้งานที่แตกต่างกันอย่างสิ้นเชิง Invoice Ninja เป็นผลิตภัณฑ์ที่มีความสมบูรณ์ที่สุด โดยรองรับทั้งการออกใบแจ้งหนี้แบบประจำ (recurring invoices), พอร์ทัลสำหรับลูกค้า, การเชื่อมต่อกับ payment gateways และรูปแบบ e-invoice ซึ่งทั้งหมดนี้พร้อมใช้งานทันทีหลังจากติดตั้ง InvoiceShelf เป็นตัวเลือกที่เบากว่าและเป็น open source เต็มรูปแบบ InvoicePlane เป็นแอปพลิเคชัน PHP แบบเรียบง่ายที่ไม่ต้องมีการจัดการระบบที่ซับซ้อน Kimai เน้นการเรียกเก็บเงินตามชั่วโมงที่ทำงานจริงแทนการระบุรายการสินค้า ส่วน ERPNext เป็นระบบบัญชีเต็มรูปแบบที่สามารถออกใบแจ้งหนี้ได้ด้วย
ปัญหา 2 ประการที่ทำให้การตั้งค่าระบบออกใบแจ้งหนี้แบบ self-hosted ล้มเหลวบ่อยกว่าการขาดฟีเจอร์ คือเรื่องอีเมลและเรื่องการสำรองข้อมูล อีเมลใบแจ้งหนี้ที่ไปตกอยู่ในโฟลเดอร์สแปมคือใบแจ้งหนี้ที่ยังไม่ได้รับชำระ และไม่มีระบบใดแจ้งเตือนคุณเมื่อเกิดเหตุการณ์นี้ ส่วนปัญหาที่สองคือการสำรองข้อมูล นี่คือฐานข้อมูลแบบ self-hosted เพียงประเภทเดียวที่หากสูญหายจะกลายเป็นปัญหาทางภาษีมากกว่าแค่ความไม่สะดวกในการใช้งาน
โปรดอ่านใบอนุญาต (licence) ก่อนอ่านรายการฟีเจอร์ ซอฟต์แวร์ 5 ตัวนี้มี 3 ตัวที่เป็น copyleft, 1 ตัวเป็นแบบ permissive และอีก 1 ตัวเป็นแบบ source-available ซึ่งมีข้อจำกัดที่แท้จริงในการนำไปใช้งาน
ตัวเลือกทั้ง 5 รายการ และกลุ่มเป้าหมายของแต่ละตัว
Invoice Ninja
แอปพลิเคชันที่พัฒนาด้วย Laravel ปัจจุบันอยู่ในเวอร์ชัน v5 การ self-host นั้นฟรีและไม่มีการจำกัดฟีเจอร์ ไม่ว่าจะเป็นการออกใบแจ้งหนี้แบบทำซ้ำ, ใบเสนอราคา, การจัดการโปรเจกต์, การบันทึกเวลา, ค่าใช้จ่าย, พอร์ทัลสำหรับลูกค้า และเกตเวย์การชำระเงินรวมถึง Stripe และ PayPal ตัวโปรเจกต์นิยามตัวเองว่าเป็น "แอปพลิเคชันสำหรับออกใบแจ้งหนี้ ใบเสนอราคา จัดการโปรเจกต์ และบันทึกเวลาแบบ source-available ที่สร้างด้วย Laravel" ส่วนที่มีค่าใช้จ่ายเพียงอย่างเดียวคือการปรับแต่งแบรนด์ โดยทางโปรเจกต์ระบุว่า "เราเสนอใบอนุญาต white-label ในราคา 40 ดอลลาร์ต่อปี เพื่อนำแบรนด์ Invoice Ninja ออกจากส่วนที่ลูกค้ามองเห็น" ราคาดังกล่าวเป็นราคา ณ เดือนสิงหาคม 2026
เลือกตัวนี้หากคุณต้องการผลิตภัณฑ์ที่ครบถ้วนที่สุดและยอมรับการรัน stack ขนาดใหญ่ได้
InvoiceShelf
เป็น fork ของ Crater ภายใต้สัญญาอนุญาต GNU Affero General Public License version 3 (AGPL-3.0) ครอบคลุมการออกใบแจ้งหนี้, การประเมินราคา, การเรียกเก็บเงินแบบทำซ้ำ, ค่าใช้จ่าย, ภาษี, การรองรับหลายสกุลเงิน, พอร์ทัลลูกค้า และการจัดการหลายบริษัท ส่วนการชำระเงินและการทำ white-label จะอยู่ใน repository ของโมดูลทางการแยกต่างหาก ซึ่งเป็น AGPL-3.0 และใช้งานได้ฟรีทั้งคู่ การชำระเงินผ่านบัตรดำเนินการผ่าน Stripe checkout
เลือกตัวนี้หากคุณต้องการแอปพลิเคชันขนาดเล็กที่เป็น open source เต็มรูปแบบ และไม่จำเป็นต้องใช้เกตเวย์การชำระเงินจำนวนมาก
InvoicePlane
แอปพลิเคชัน PHP ที่ใช้ CodeIgniter เผยแพร่ภายใต้สัญญาอนุญาต MIT และเป็นตัวเลือกเดียวในที่นี้ที่ติดตั้งโดยการแตกไฟล์ลงใน web root ไม่ต้องใช้ Docker และไม่มีขั้นตอนการ build ด้วย Node ไฟล์ PDF สร้างจาก mPDF ดังนั้นเทมเพลตจึงเป็น HTML และ CSS ลูกค้าจะได้รับลิงก์สำหรับเข้าดูและชำระเงินในใบแจ้งหนี้
ข้อจำกัดคือเรื่องการชำระเงิน เอกสารระบุไว้อย่างชัดเจนว่า InvoicePlane 1.6 รองรับเฉพาะ Stripe เป็นค่าเริ่มต้น และผู้ให้บริการรายอื่นถูกนำออกไปในเวอร์ชันนี้ ความต้องการของระบบที่เผยแพร่สำหรับเวอร์ชัน 1.6 คือ PHP 8.0 ถึง 8.1 ร่วมกับ MySQL 5.5 หรือ MariaDB ที่เทียบเท่า โปรดอ่านบันทึกของเวอร์ชันที่คุณดาวน์โหลด เนื่องจากเวอร์ชัน 1.7 ยังคงมีการพัฒนาอยู่
เลือกตัวนี้หากคุณใช้งานบน shared hosting หรือ VPS ขนาด 512 MB
Kimai
เครื่องมือบันทึกเวลาภายใต้สัญญาอนุญาต AGPL-3.0 ซึ่งสามารถสร้างใบแจ้งหนี้จากบันทึกเวลาได้ เป็นคำตอบที่เหมาะสมสำหรับผู้ที่เรียกเก็บเงินตามชั่วโมงการทำงาน เทมเพลตใบแจ้งหนี้จะถูกอัปโหลดเป็นไฟล์ DOCX, ODS หรือ XLSX ซึ่งเอกสารยืนยันว่าเป็นรูปแบบเดียวที่รองรับ และจะถูกเรนเดอร์ออกมาเป็น PDF หรือ HTML คุณสามารถจัดรูปแบบใบแจ้งหนี้ในโปรแกรมประมวลผลคำแทนการเขียน CSS ซึ่งคนส่วนใหญ่พบว่าทำได้ง่ายกว่า
Kimai ไม่มีพอร์ทัลลูกค้าและไม่มีเกตเวย์การชำระเงิน ดังนั้นคุณต้องส่งไฟล์ PDF ทางอีเมล สำหรับการออกใบแจ้งหนี้อิเล็กทรอนิกส์แบบมีโครงสร้าง (Structured e-invoicing) จะเป็นปลั๊กอินแบบชำระเงินในร้านค้าชื่อ E-Invoice Plus ซึ่งมีราคาอยู่ที่ 99 ยูโรต่อปี (ไม่รวมภาษีมูลค่าเพิ่ม) สำหรับการติดตั้งแบบ self-hosted ณ เดือนสิงหาคม 2026 โดยครอบคลุมโปรไฟล์ EN16931, XRechnung, ZUGFeRD, Factur-X และ Peppol
เลือกตัวนี้หากใบแจ้งหนี้ของคุณเป็นผลลัพธ์จากการบันทึกเวลาทำงาน
ERPNext
สัญญาอนุญาต GPL-3.0 และเป็นซอฟต์แวร์คนละประเภทกัน ใบแจ้งหนี้การขายเป็นเพียงเอกสารประเภทหนึ่งภายในระบบบัญชีเต็มรูปแบบที่มีผังบัญชี, การบันทึกรายการบัญชี, สต็อก และการจ่ายเงินเดือน เป็นคำตอบที่เหมาะสมเมื่อการออกใบแจ้งหนี้ไม่ใช่หน้าที่หลักเพียงอย่างเดียวอีกต่อไป สำหรับฟรีแลนซ์หนึ่งคนที่ดูแลลูกค้าแปดราย ซอฟต์แวร์นี้ถือว่าใหญ่เกินความจำเป็น การติดตั้งระบบนี้ถือเป็นโปรเจกต์เฉพาะตัว ซึ่งครอบคลุมอยู่ใน การรัน ERPNext บน VPS
การออกใบแจ้งหนี้แบบประจำขึ้นอยู่กับตัวกำหนดเวลาที่คุณมองไม่เห็น
Invoice Ninja, InvoiceShelf, InvoicePlane และ ERPNext ต่างก็สามารถสร้างใบแจ้งหนี้แบบประจำได้ ส่วน Kimai ไม่มีฟีเจอร์ใบแจ้งหนี้แบบประจำในตัวหลัก เนื่องจากใบแจ้งหนี้ในระบบนั้นถูกสร้างขึ้นจากรายการบันทึกเวลาทำงานในช่วงเวลาหนึ่ง
รูปแบบความล้มเหลวของแอปพลิเคชันที่ใช้ Laravel นั้นเหมือนกันหมดและเงียบเชียบ ใบแจ้งหนี้แบบประจำจะถูกสร้างโดยงานที่กำหนดเวลาไว้คือ php artisan schedule:run ซึ่งต้องมีบางอย่างภายนอกแอปพลิเคชันเรียกใช้งานทุกนาที หากไม่มีการเรียกใช้งาน รายการใบแจ้งหนี้แบบประจำจะยังคงแสดงวันที่ส่งถัดไป และวันที่นั้นก็จะผ่านไปเฉยๆ โดยไม่มีใบแจ้งหนี้ปรากฏขึ้น และไม่มีการบันทึกข้อผิดพลาดใดๆ เนื่องจากไม่มีโค้ดส่วนใดทำงานเลย
ดังนั้น หลังจากที่คุณสร้างใบแจ้งหนี้แบบประจำรายการแรก ให้ตั้งวันที่ส่งถัดไปล่วงหน้าไว้ไม่กี่นาทีแล้วรอ หากไม่มีอะไรเกิดขึ้น แสดงว่าตัวกำหนดเวลาไม่ได้ทำงาน ในการติดตั้งแบบ Docker โดยปกติหมายความว่าบริการ cron หรือ scheduler ในไฟล์ compose ไม่เคยเริ่มทำงาน หรือมันหยุดทำงานไปแล้ว
docker compose ps
docker compose logs --tail 50ทุกบริการในไฟล์ควรรายงานสถานะเป็น running บริการที่ค้างอยู่ในสถานะ exited คือบริการที่คุณจำเป็นต้องอ่าน log ของมัน
หลายสกุลเงินและภาษี: สิ่งที่ต้องตรวจสอบก่อนตัดสินใจเลือกใช้งาน
รายการฟีเจอร์มักระบุว่า "รองรับหลายสกุลเงิน" แต่ความหมายที่แท้จริงอาจแตกต่างกันมาก ให้ดำเนินการตรวจสอบ 4 หัวข้อนี้บน instance ทดลอง โดยใช้ตัวเลขจริงจากธุรกิจของคุณ เพราะหากเกิดข้อผิดพลาด บัญชีของคุณจะเป็นผู้พบปัญหาก่อนที่คุณจะทราบ
- ใบแจ้งหนี้จัดเก็บอัตราแลกเปลี่ยน ณ วันที่ออกเอกสารหรือไม่? ระบบจำเป็นต้องทำเช่นนั้น หากแอปพลิเคชันคำนวณยอดรวมใหม่จากอัตราแลกเปลี่ยนปัจจุบันเสมอ รายงานของไตรมาสที่ผ่านมาจะเปลี่ยนแปลงทุกครั้งที่คุณเปิดดู และสมุดบัญชีของคุณจะไม่ตรงกับสิ่งที่ยื่นภาษีไปแล้ว
- ภาษีถูกคำนวณต่อรายการสินค้า ต่อใบแจ้งหนี้ หรือทั้งสองอย่าง? การใช้ภาษีอัตราเดียวต่อใบแจ้งหนี้อาจเพียงพอ จนกระทั่งคุณมีรายการสินค้าที่ได้รับยกเว้นภาษี (zero-rated)
- คุณสามารถระบุราคาแบบรวมภาษีและแยกภาษีได้หรือไม่? การแปลงค่าภายหลังจะทำให้เกิดผลต่างจากการปัดเศษทศนิยมในแต่ละรายการ ซึ่งผลต่างเหล่านี้จะสะสมรวมกันตลอดทั้งปี
- เอกสารแสดงผลอย่างไรสำหรับลูกค้าในต่างประเทศที่ได้รับยกเว้นภาษีมูลค่าเพิ่ม (VAT)? คุณจำเป็นต้องมีข้อความระบุการยกเว้นภาษีพิมพ์ลงในใบแจ้งหนี้ ไม่ใช่เพียงแค่เลขศูนย์ในช่องภาษี
Invoice Ninja และ ERPNext รองรับทั้ง 4 ข้อนี้ InvoiceShelf ระบุว่าภาษีและหลายสกุลเงินเป็นหนึ่งในฟีเจอร์ของตน ส่วน InvoicePlane และ Kimai มีความซับซ้อนน้อยกว่า ดังนั้นควรทดสอบด้วยใบแจ้งหนี้ที่ซับซ้อนที่สุดของคุณ แทนที่จะทดสอบกับใบแจ้งหนี้ที่ง่ายที่สุด
พอร์ทัลลูกค้าและเกตเวย์การชำระเงิน
พอร์ทัลลูกค้าคือหน้าเว็บที่ลูกค้าสามารถดูใบแจ้งหนี้ ดาวน์โหลดไฟล์ PDF และชำระเงินได้ สิ่งนี้มีความสำคัญมากกว่าที่คิด เพราะการติดตามการชำระเงินผ่านอีเมลนั้นใช้เวลาของคุณมากกว่าการออกใบแจ้งหนี้เสียอีก
Invoice Ninja มีความโดดเด่นในด้านนี้มากที่สุด โดยมีพอร์ทัลเต็มรูปแบบ รองรับเกตเวย์จำนวนมาก มีการจัดเก็บวิธีการชำระเงิน และระบบเรียกเก็บเงินอัตโนมัติสำหรับใบแจ้งหนี้ที่เกิดขึ้นประจำ ส่วน InvoiceShelf มีพอร์ทัลลูกค้าและเพิ่ม Stripe checkout ผ่านโมดูลการชำระเงิน ในขณะที่ InvoicePlane จะให้ลิงก์สำหรับแขกในแต่ละใบแจ้งหนี้และรองรับ Stripe สำหรับ Kimai นั้นไม่มีฟีเจอร์ดังกล่าว ดังนั้นไฟล์ PDF จะถูกส่งไปในรูปแบบไฟล์แนบแทน
มีประเด็นหนึ่งที่มักเกิดความสับสนอยู่เสมอ การโฮสต์แอปพลิเคชันออกใบแจ้งหนี้ด้วยตนเองไม่ได้หมายความว่าคุณต้องเก็บหมายเลขบัตรเครดิตไว้ ด้วย Stripe checkout ลูกค้าจะถูกเปลี่ยนเส้นทางไปยัง Stripe เพื่อกรอกข้อมูลบัตรที่นั่น และ VPS ของคุณจะไม่เห็นหมายเลขบัตรเลย ขอบเขตความรับผิดชอบด้าน PCI (มาตรฐานความปลอดภัยอุตสาหกรรมบัตรชำระเงิน) ของคุณจึงอยู่ในระดับต่ำ เพราะคุณไม่ได้เป็นผู้สร้างแบบฟอร์มการชำระเงินขึ้นมาเอง หากในอนาคตคุณต้องการใช้ผู้ให้บริการชำระเงินมากกว่าหนึ่งราย หรือต้องการกำหนดเส้นทางการชำระเงินตามประเทศ สิ่งนั้นควรจัดการในเลเยอร์แยกต่างหาก เช่น การจัดการการชำระเงินแบบ self-hosted ด้วย Hyperswitch
คุณภาพของ PDF และเทมเพลตที่คุณจะต้องแก้ไข
คุณจะต้องแก้ไขเทมเพลต ค่าเริ่มต้นทั้งหมดที่นี่วางที่อยู่ของคุณไว้ในตำแหน่งที่ไม่ถูกต้องสำหรับประเทศของคุณ
Invoice Ninja เรนเดอร์เทมเพลต HTML และ CSS เป็น PDF โดยใช้ headless Chromium ที่รวมอยู่ในอิมเมจ ซึ่งเป็นสาเหตุที่คอนเทนเนอร์มีขนาดใหญ่ คุณควรจัดสรรหน่วยความจำให้เพียงพอ เนื่องจาก headless browser เป็นกระบวนการที่ใช้ทรัพยากรมากที่สุดใน stack ดังนั้น VPS ขนาด 1 GB จึงถือว่าค่อนข้างจำกัด ส่วน InvoicePlane ใช้ mPDF ซึ่งเป็น PHP ล้วนและมีน้ำหนักเบา แต่ต้องแลกมาด้วยการไม่รองรับ CSS สมัยใหม่บางอย่าง ในขณะที่ Kimai ใช้วิธีที่ต่างออกไปโดยให้คุณอัปโหลดไฟล์ DOCX หรือ ODS ดังนั้นการจัดวางเลย์เอาต์จึงทำผ่าน LibreOffice หรือ Word โดยผู้ที่ไม่เคยเขียนสไตล์ชีตมาก่อน
หากการออกแบบใบแจ้งหนี้มีความสำคัญต่อคุณมากกว่า CSS วิธีของ Kimai จะเป็นตัวเลือกที่ดีกว่า แต่หากคุณต้องการให้เทมเพลตอยู่ในระบบควบคุมเวอร์ชันและสามารถเปรียบเทียบความแตกต่าง (diff) ได้ วิธีการใช้ HTML จะเหมาะสมกว่า
ใบอนุญาตอนุญาตให้ใช้งานเชิงพาณิชย์ได้หรือไม่
ทั้ง 5 รายการอนุญาตให้คุณออกใบแจ้งหนี้ให้ลูกค้าของคุณเองได้ ความแตกต่างจะปรากฏขึ้นเมื่อคุณทำสิ่งอื่นนอกเหนือจากนั้น
Invoice Ninja อยู่ภายใต้สัญญาอนุญาต Elastic License 2.0 ซึ่งมีข้อกำหนดสำคัญ 2 ประการ:
คุณไม่สามารถให้บริการซอฟต์แวร์แก่บุคคลที่สามในลักษณะบริการโฮสต์หรือบริการที่มีการจัดการ (managed service) โดยที่บริการนั้นเปิดให้ผู้ใช้เข้าถึงชุดฟีเจอร์หรือฟังก์ชันการทำงานส่วนใหญ่ของซอฟต์แวร์ได้
คุณไม่สามารถย้าย เปลี่ยนแปลง ปิดใช้งาน หรือหลีกเลี่ยงฟังก์ชันการทำงานของ license key ในซอฟต์แวร์ได้
ดังนั้น การใช้งานเพื่อธุรกิจของคุณเองจึงทำได้ แต่การเปิด instance ให้ลูกค้าใช้งานในลักษณะผลิตภัณฑ์นั้นทำไม่ได้ ข้อกำหนดข้อที่สองคือเหตุผลว่าทำไมการลบ branding ออกจึงต้องซื้อใบอนุญาตราคา $40 แทนที่จะเป็นการแก้ไข source code
InvoiceShelf, Kimai และ Crater ใช้สัญญาอนุญาต AGPL-3.0 ซึ่งอนุญาตให้ใช้งานเชิงพาณิชย์ได้ฟรีและไม่มีระดับชั้นการใช้งานที่เหนือกว่าคุณ ข้อผูกพันอยู่ที่ส่วนที่ 13: หากคุณแก้ไขโค้ดและเปิดให้ผู้อื่นใช้งานเวอร์ชันที่แก้ไขแล้วผ่านเครือข่าย คุณต้องเสนอ source code ของส่วนที่คุณแก้ไขให้แก่พวกเขา สำหรับ instance ที่ไม่ได้แก้ไขจะถือว่าครอบคลุมโดย source code สาธารณะของต้นทางอยู่แล้ว ดังนั้นผู้ที่ self-host ส่วนใหญ่จึงไม่ได้รับผลกระทบจากข้อนี้
InvoicePlane ใช้สัญญาอนุญาต MIT ซึ่งมีข้อผูกพันน้อยที่สุดในกลุ่มนี้ แม้ว่าไฟล์ README จะระบุว่าชื่อและโลโก้ยังคงเป็นกรรมสิทธิ์ของโครงการ
ERPNext ใช้สัญญาอนุญาต GPL-3.0 การแก้ไขใดๆ ที่คุณแจกจ่ายจะต้องถูกเปิดเผย แต่การใช้งานแบบส่วนตัวไม่มีข้อผูกพันใดๆ
นี่เป็นเพียงคำอธิบายเนื้อหาของใบอนุญาต ไม่ใช่คำแนะนำทางกฎหมาย
โครงการยังมีการดูแลรักษาอยู่หรือไม่? ตรวจสอบจากบันทึกการ commit
Crater เคยเป็นแอปพลิเคชันออกใบแจ้งหนี้แบบโอเพนซอร์สที่ได้รับความนิยมอยู่หลายปี และยังมีคู่มือจำนวนมากที่แนะนำให้ใช้งาน อย่างไรก็ตาม branch หลักของโครงการไม่มีการ commit ใดๆ มาเป็นเวลา 741 วันแล้ว
The data behind this chart
[
{
"label": "ERPNext",
"commit_gap": 0
},
{
"label": "Invoice Ninja",
"commit_gap": 1
},
{
"label": "Kimai",
"commit_gap": 1
},
{
"label": "InvoicePlane",
"commit_gap": 3
},
{
"label": "InvoiceShelf",
"commit_gap": 4
},
{
"label": "Crater",
"commit_gap": 741
}
]จากโครงการจำนวน 6 รายการในกลุ่มนั้น มี 5 รายการที่มีการ commit ภายในสัปดาห์ที่ผ่านมา InvoiceShelf คือ fork ที่นำงานของ Crater มาพัฒนาต่อภายใต้สัญญาอนุญาต AGPL-3.0 ฉบับเดียวกันและใช้โมเดลข้อมูลเดียวกัน ดังนั้นการย้ายไปใช้งานจึงเป็นการย้ายข้อมูลมากกว่าการเขียนใหม่ทั้งหมด ให้ติดตั้ง InvoiceShelf แทน Crater
การติดตั้งแต่ละรายการบน VPS
ทุกบริการยกเว้น InvoicePlane สามารถรันได้ง่ายที่สุดผ่าน Docker Compose หากคุณยังไม่คุ้นเคย ให้เริ่มต้นที่ การสร้าง Docker Compose stack ชุดแรกบน VPS แล้วจึงกลับมาที่นี่
Invoice Ninja มี repository สำหรับ compose ของตนเอง
git clone https://github.com/invoiceninja/dockerfiles.git
cd dockerfiles
docker run --rm -it invoiceninja/invoiceninja php artisan key:generate --showคัดลอก key นั้นลงในไฟล์ env ใน repository พร้อมกับ APP_URL จริงของคุณ จากนั้นตั้งค่าความเป็นเจ้าของไฟล์ตามที่ image ต้องการแล้วเริ่มการทำงาน
chmod 755 docker/app/public
sudo chown -R 1500:1500 docker/app
docker compose up -dความเป็นเจ้าของ 1500:1500 ต้องตรงกับผู้ใช้ภายใน image หากข้ามขั้นตอนนี้ แอปพลิเคชันจะไม่สามารถเขียนไฟล์แคชหรือไฟล์ PDF ที่สร้างขึ้นได้ ในขั้นตอนการตั้งค่าผ่าน wizard ให้ระบุ db เป็น database host เนื่องจากเป็นชื่อบริการบนเครือข่ายของ compose ส่วน localhost ในที่นั้นจะชี้ไปยัง container ของแอปพลิเคชันโดยตรง
InvoiceShelf มีไฟล์ compose เตรียมไว้ให้พร้อมใช้งาน โดยแยกตาม engine ของฐานข้อมูล
curl -fLO https://raw.githubusercontent.com/InvoiceShelf/docker/master/docker-compose.mysql.yml
mv docker-compose.mysql.yml docker-compose.ymlเปิดไฟล์นั้นก่อนเริ่มการทำงาน รหัสผ่านทุกตัวในไฟล์เป็นเพียงตัวอย่างและมีระบุไว้ในคอมเมนต์ของไฟล์แล้ว APP_URL, SESSION_DOMAIN และ SANCTUM_STATEFUL_DOMAINS มีค่าเริ่มต้นเป็น localhost ซึ่งทั้งสามค่านี้จำเป็นต้องเปลี่ยนเป็น hostname จริงของคุณก่อนการเข้าสู่ระบบครั้งแรก จากนั้นจึงเริ่มการทำงาน
docker compose up -dบริการนี้จะเปิดพอร์ต 8090 บนโฮสต์และให้บริการที่พอร์ต 8080 ภายใน container คุณควรติดตั้ง reverse proxy ที่รองรับ TLS (transport layer security) ไว้ด้านหน้าก่อนที่จะเริ่มใช้งานจริงกับลูกค้า
ไฟล์ compose สำหรับการใช้งานจริงของ Kimai จากเอกสารประกอบของโครงการ
services:
sqldb:
image: mysql:8.3
volumes:
- mysql:/var/lib/mysql
environment:
- MYSQL_DATABASE=kimai
- MYSQL_USER=kimaiuser
- MYSQL_PASSWORD=kimaipassword
- MYSQL_ROOT_PASSWORD=changemeplease
command: --default-storage-engine innodb
restart: unless-stopped
healthcheck:
test: mysqladmin -uroot -p$$MYSQL_ROOT_PASSWORD ping -h 127.0.0.1 --silent
interval: 10s
timeout: 5s
retries: 12
start_period: 30s
kimai:
image: kimai/kimai2:stable
depends_on:
sqldb:
condition: service_healthy
restart: true
volumes:
- data:/opt/kimai/var/data
- plugins:/opt/kimai/var/plugins
ports:
- 8001:8001
environment:
- APP_SECRET=your-fantastic-long-random-and-ultra-secure-secret
- TRUSTED_HOSTS=kimai.example.com
- ADMINMAIL=admin@example.com
- ADMINPASS=changemeplease
- DATABASE_URL=mysql://kimaiuser:kimaipassword@sqldb/kimai?charset=utf8mb4&serverVersion=8.3.0
restart: unless-stopped
volumes:
data:
mysql:
plugins:ตั้งค่า APP_SECRET ให้เป็นสตริงสุ่มที่มีความยาว และตั้งค่า TRUSTED_HOSTS ให้เป็นโดเมนที่คุณจะใช้งานจริง ADMINMAIL และ ADMINPASS จะสร้างบัญชีผู้ดูแลระบบคนแรกในการบูตครั้งแรก ดังนั้นควรเปลี่ยนรหัสผ่านในหน้าอินเทอร์เฟซหลังจากนั้นและนำรหัสผ่านออกจากไฟล์
InvoicePlane ไม่มี container ให้ใช้งาน คุณต้องสร้างฐานข้อมูลเปล่าขึ้นมาก่อน
sudo mysql -e "CREATE DATABASE invoiceplane CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"ดาวน์โหลดไฟล์ archive จาก หน้า releases ของโครงการ แตกไฟล์ลงใน web root ของคุณ คัดลอก ipconfig.php.example ไปยัง ipconfig.php และตั้งค่า URL ของคุณภายในไฟล์ตามคำแนะนำในคอมเมนต์ จากนั้นเปิด https://your-domain.example/index.php/setup และดำเนินการติดตั้งผ่านตัวติดตั้งตามขั้นตอน
เหตุใดใบแจ้งหนี้ของคุณจึงไปอยู่ในโฟลเดอร์สแปม
นี่คือความล้มเหลวที่ทำให้คุณสูญเสียรายได้ โดยที่แอปพลิเคชันจะยังคงรายงานว่าส่งใบแจ้งหนี้สำเร็จตามปกติ
ห้ามส่งอีเมลใบแจ้งหนี้จาก IP address ของ VPS โดยตรง IP address ของ VPS ที่เพิ่งเปิดใช้งานใหม่ไม่มีประวัติการส่งอีเมล ผู้ให้บริการรับอีเมลรายใหญ่จะถือว่าข้อความแรกที่มาจากที่อยู่ที่ไม่รู้จักในกลุ่ม IP ของผู้ให้บริการโฮสติ้งเป็นสิ่งที่น่าสงสัยโดยค่าเริ่มต้น ให้ส่งผ่าน SMTP (simple mail transfer protocol) relay บนโดเมนที่คุณได้ยืนยันตัวตนไว้แล้ว การตั้งค่าดังกล่าวตั้งแต่ต้นจนจบมีรายละเอียดเฉพาะตัว และ การส่งอีเมลอย่างน่าเชื่อถือจากแอปที่โฮสต์เอง จะครอบคลุมถึงการตั้งค่า relay, DNS records และการทดสอบ
ที่อยู่ From คือจุดที่การตั้งค่าใบแจ้งหนี้ส่วนใหญ่เกิดข้อผิดพลาด ที่อยู่นี้ต้องเป็นโดเมนที่คุณควบคุมและเป็นโดเมนที่ relay ของคุณลงนามด้วย DKIM (domainkeys identified mail) การใส่ที่อยู่ของลูกค้าลงในช่อง From อาจดูสุภาพแต่จะทำให้การส่งอีเมลล้มเหลว เนื่องจากเซิร์ฟเวอร์ผู้รับจะตรวจสอบว่าโดเมนในช่อง From ตรงกับโดเมนที่ยืนยันตัวตนข้อความนั้นหรือไม่ Gmail จะปฏิเสธการส่งหากข้อมูลไม่ตรงกันทันที:
550 5.7.1 Unauthenticated email from example.com is not accepted due to domain's DMARC policyให้ใช้ที่อยู่ของคุณเองในช่อง From และใส่ที่อยู่ของลูกค้าในช่อง Reply-To แทน ตรวจสอบ record ที่คุณเผยแพร่ก่อนที่จะเริ่มส่งข้อมูลจริง
dig +short TXT example.com
dig +short TXT _dmarc.example.com
dig +short TXT selector1._domainkey.example.comคำสั่งแรกควรแสดง SPF (sender policy framework) record ที่ระบุชื่อ relay ของคุณ คำสั่งที่สองควรแสดงนโยบาย DMARC (domain-based message authentication, reporting and conformance) ส่วนคำสั่งที่สามขึ้นอยู่กับ selector ที่ relay ของคุณกำหนดให้ หากได้ผลลัพธ์ว่างเปล่า หมายความว่า DKIM record หายไปหรือเผยแพร่ภายใต้ชื่อที่ไม่ถูกต้อง ส่งผลให้ทุกข้อความที่คุณส่งไม่ผ่านการตรวจสอบลายเซ็น
จากนั้นให้ส่งใบแจ้งหนี้จริงไปยังบัญชีที่คุณเป็นเจ้าของที่ผู้ให้บริการรายใหญ่ แล้วอ่าน raw headers ค่า dkim=pass และ spf=pass ใน header ส่วน Authentication-Results คือหลักฐานเดียวที่เชื่อถือได้ สถานะ "sent" ของแอปพลิเคชันหมายความเพียงว่าแอปได้ส่งข้อความไปยัง relay แล้วเท่านั้น
การสำรองข้อมูล: ฐานข้อมูลเดียวที่คุณห้ามทำหาย
การสูญเสียเซิร์ฟเวอร์สื่อบันเทิงหมายถึงการต้องดาวน์โหลดไฟล์ใหม่ทั้งหมด แม้แต่ เซิร์ฟเวอร์รูปภาพแบบ self-hosted อย่าง PhotoPrism หรือ Immich มักจะเก็บสำเนาชุดที่สองของไฟล์ต้นฉบับซึ่งยังคงมีอยู่ในโทรศัพท์ที่ใช้ถ่ายภาพนั้น แต่การสูญเสียฐานข้อมูลใบแจ้งหนี้หมายถึงคุณจะไม่สามารถแสดงรายการที่เรียกเก็บเงิน การชำระเงินที่ได้รับ หรือยอดค้างชำระได้ จงจัดการกับมันด้วยความสำคัญที่เหมาะสม
จงสำรองข้อมูล 4 ส่วน ได้แก่ ฐานข้อมูล, storage volume ซึ่งเก็บโลโก้ ไฟล์ PDF ที่สร้างขึ้น และใบเสร็จค่าใช้จ่าย, ไฟล์ environment ของแอปพลิเคชัน และไฟล์ PDF ที่สร้างเสร็จแล้วซึ่งเก็บไว้เป็นไฟล์ทั่วไป เพราะไฟล์ PDF สามารถเปิดอ่านได้ในอีก 10 ปีข้างหน้าโดยไม่จำเป็นต้องใช้แอปพลิเคชันที่สร้างมันขึ้นมา
ไฟล์ environment มีความสำคัญมากกว่าที่หลายคนคาดคิด Laravel จะเข้ารหัสค่าที่ละเอียดอ่อนที่จัดเก็บไว้ รวมถึงข้อมูลรับรองของ payment gateway โดยใช้ APP_KEY ที่อยู่ในไฟล์นั้น หากคุณกู้คืนฐานข้อมูลโดยใช้ key ที่สร้างขึ้นใหม่ ค่าเหล่านั้นจะไม่สามารถถอดรหัสได้ ใบแจ้งหนี้ของคุณจะยังอยู่ครบ แต่การตั้งค่า gateway ของคุณจะอ่านไม่ออก
การ dump ข้อมูลจาก stack ของ InvoiceShelf มีลักษณะดังนี้ บริการฐานข้อมูลของมันรัน mariadb:10 ดังนั้นเครื่องมือที่อยู่ภายใน container คือ mariadb-dump
docker compose exec -T database mariadb-dump \
--user=root --password=YOUR_ROOT_PASSWORD \
--single-transaction --databases invoiceshelf > invoiceshelf.sql--single-transaction จะทำการ snapshot ข้อมูลตาราง InnoDB อย่างสม่ำเสมอโดยไม่ต้องล็อกตาราง ทำให้แอปพลิเคชันยังคงให้บริการได้ในขณะที่การ dump ทำงานอยู่ -T จะป้องกันไม่ให้ Docker จัดสรร terminal ซึ่งหากไม่ทำเช่นนั้นจะทำให้ output ที่ถูก redirect เสียหาย และคุณจะได้ไฟล์ dump ที่ไม่สามารถนำไป import ได้
ส่งข้อมูลเหล่านั้นออกจากเซิร์ฟเวอร์ตามกำหนดเวลาด้วย การสำรองข้อมูลแบบเข้ารหัสด้วย restic ไปยัง off-site storage และตั้งค่าระยะเวลาการเก็บรักษาให้ครอบคลุมช่วงเวลาที่นักบัญชีของคุณกำหนด
จากนั้นให้ทดสอบการกู้คืน นำไฟล์ dump ขึ้นใน container ชั่วคราว ล็อกอินเข้าสู่ระบบ และเปิดใบแจ้งหนี้ของเดือนที่แล้วดู จนกว่าคุณจะได้ทำตามขั้นตอนนี้สักครั้ง คุณจะไม่มีทางทราบได้เลยว่าการสำรองข้อมูลของคุณใช้งานได้จริงหรือไม่
สิ่งที่นักบัญชีของคุณจะสอบถาม
อย่าใช้คำแนะนำด้านภาษีจากบทช่วยสอนนี้ สิ่งที่ระบุต่อไปนี้คือสิ่งที่ซอฟต์แวร์นี้สามารถจัดทำได้ เพื่อให้คุณนำรายการนี้ไปปรึกษากับผู้ให้คำแนะนำของคุณ
ข้อมูลที่ส่งออกได้ คุณควรจะสามารถส่งออกใบแจ้งหนี้และการชำระเงินเป็นไฟล์ CSV ได้จากหน้าจออินเทอร์เฟซ โดยไม่ต้องใช้ database client และไม่ต้องเปิด support ticket การทำ SQL dump ถือเป็นการสำรองข้อมูล ไม่ใช่การส่งออกข้อมูล เพราะนักบัญชีของคุณไม่สามารถเปิดไฟล์ดังกล่าวได้
การรันเลขที่เอกสารแบบแก้ไขไม่ได้ เลขที่ใบแจ้งหนี้ควรเรียงลำดับต่อเนื่องและห้ามนำกลับมาใช้ซ้ำโดยเด็ดขาด และต้องไม่มีเลขที่เว้นว่าง การลบใบแจ้งหนี้จะทำให้เกิดช่องว่างของเลขที่เอกสารซึ่งต้องมีการชี้แจงภายหลัง ให้ใช้วิธีการยกเลิกหรือออกใบลดหนี้แทน ซึ่งแอปพลิเคชันทุกตัวในที่นี้รองรับการทำงานดังกล่าว การกำหนดว่าคุณจำเป็นต้องใช้เลขที่เอกสารแบบต่อเนื่องไม่มีช่องว่างหรือไม่นั้น ขึ้นอยู่กับสถานที่ที่คุณจดทะเบียนธุรกิจ ซึ่งควรสอบถามเรื่องนี้ตั้งแต่เนิ่นๆ
การจัดเก็บข้อมูล ให้เก็บไฟล์ database dump และไฟล์ PDF ที่สร้างขึ้นไว้นานเท่าที่กฎระเบียบของคุณกำหนด ไฟล์ PDF คือเอกสารที่ถูกส่งออกไปจริง และเป็นหลักฐานสำคัญหากมีการโต้แย้งใบแจ้งหนี้ในอนาคต
ประวัติการเปลี่ยนแปลง การสามารถตรวจสอบได้ว่าใครเป็นผู้แก้ไขใบแจ้งหนี้และแก้ไขเมื่อใดเป็นสิ่งที่ควรมี ซึ่งฟีเจอร์นี้มีความแตกต่างกันมากในแต่ละแอปพลิเคชัน โดย Invoice Ninja จะเก็บ log กิจกรรมแยกตามแต่ละรายการไว้
การทำ e-invoicing แบบมีโครงสร้างได้กลายเป็นข้อกำหนดที่จำเป็น ไม่ใช่เพียงแค่ฟีเจอร์เสริมในบางพื้นที่ของ EU โดย Invoice Ninja สามารถสร้างรูปแบบมาตรฐานทั่วไปได้ ซึ่งครอบคลุมถึง ZUGFeRD, XRechnung, Facturae, FatturaPA และมาตรฐาน EN16931 ทั่วไป การส่งข้อมูลผ่านเครือข่าย Peppol จาก instance ที่ self-hosted จะต้องผ่าน access point ของ Invoice Ninja เอง โดยคุณจะต้องลงทะเบียนนิติบุคคลกับทางผู้ให้บริการและซื้อเครดิตสำหรับการส่งแต่ละครั้ง ซึ่งถือเป็นบริการแบบชำระเงิน ณ เดือนสิงหาคม 2026 ส่วน Kimai จะรองรับรูปแบบเดียวกันนี้ผ่านปลั๊กอินแบบชำระเงิน สำหรับแอปพลิเคชันอีกสามตัวที่เหลือไม่สามารถสร้าง e-invoices แบบมีโครงสร้างได้เลยในปัจจุบัน ซึ่งถือเป็นเหตุผลสำคัญที่สุดในการเลือกใช้ Invoice Ninja หากคุณออกใบแจ้งหนี้ภายในเขต EU
FAQ
ฉันควรติดตั้ง Crater หรือ InvoiceShelf?
ควรเลือก InvoiceShelf เนื่องจากสาขาหลัก (default branch) ของ Crater ไม่มีการ commit ใดๆ มาเป็นเวลา 741 วัน นับถึงวันที่ 21 สิงหาคม 2026 และระบบติดตามปัญหา (issue tracker) ของโครงการเองก็ได้แนะนำให้ผู้ใช้ย้ายไปใช้ fork อื่นแทน InvoiceShelf ใช้สัญญาอนุญาต AGPL-3.0 และมีรูปแบบข้อมูล (data model) เดียวกัน การย้ายจาก Crater มายัง InvoiceShelf จึงเป็นเพียงการย้ายฐานข้อมูล ไม่ใช่การเขียนใหม่ คู่มือใดที่ยังแนะนำให้ใช้ Crater คือคู่มือที่เขียนขึ้นก่อนที่โครงการจะหยุดการพัฒนา
ฉันสามารถใช้ Invoice Ninja สำหรับธุรกิจของตนเองโดยไม่เสียค่าใช้จ่ายได้หรือไม่?
ได้ Invoice Ninja เวอร์ชัน self-hosted มีฟังก์ชันการทำงานครบถ้วนโดยไม่มีค่าใช้จ่ายภายใต้สัญญาอนุญาต Elastic License 2.0 ซึ่งรวมถึงการออกใบแจ้งหนี้แบบต่อเนื่อง (recurring invoices), พอร์ทัลสำหรับลูกค้า และเกตเวย์การชำระเงิน สิ่งที่มีค่าใช้จ่ายมีอยู่สองอย่าง คือการนำแบรนด์ Invoice Ninja ออกจากหน้าเว็บที่ลูกค้ามองเห็น ซึ่งต้องใช้ใบอนุญาต white-label โดยมีราคาอยู่ที่ "$40 ต่อปี" ตามข้อมูลของโครงการ ณ เดือนสิงหาคม 2026 และการส่งใบแจ้งหนี้อิเล็กทรอนิกส์ผ่านเครือข่าย Peppol ซึ่งมีการคิดค่าบริการแยกต่างหาก สิ่งที่สัญญาอนุญาตไม่อนุญาตคือการนำซอฟต์แวร์ไปเปิดให้บริการในรูปแบบ hosted service ให้กับผู้อื่น
ทำไมอีเมลใบแจ้งหนี้ของฉันถึงไปอยู่ในโฟลเดอร์สแปม?
สาเหตุเกือบทั้งหมดเกิดจากข้อความไม่ได้ผ่านการยืนยันตัวตนสำหรับโดเมนที่ระบุในที่อยู่ From ให้ส่งอีเมลผ่าน SMTP relay แทนการส่งจากตัว VPS โดยตรง จากนั้นให้ประกาศระเบียน SPF และ DMARC สำหรับโดเมนของคุณ และเพิ่มระเบียน DKIM ตาม selector ที่ผู้ให้บริการ relay ของคุณกำหนด ให้คงที่อยู่ของคุณไว้ในช่อง From และใส่ที่อยู่ของลูกค้าในช่อง Reply-To การตั้งค่าที่อยู่ของลูกค้าเป็นผู้ส่งจะทำให้ Gmail ปฏิเสธข้อความด้วยรหัส 550 5.7.1 Unauthenticated email from example.com is not accepted due to domain's DMARC policy ให้ยืนยันการแก้ไขโดยตรวจสอบหา dkim=pass และ spf=pass ในส่วนหัว Authentication-Results ของข้อความทดสอบ
ฉันควรเลือกตัวไหนหากคิดค่าบริการเป็นรายชั่วโมง?
Kimai เนื่องจากเป็นระบบติดตามเวลา (time tracker) โดยเฉพาะ ใบแจ้งหนี้จึงถูกสร้างขึ้นจากรายการบันทึกเวลาที่ได้รับการอนุมัติ และรายการสินค้าในใบแจ้งหนี้คือเนื้องานที่คุณได้บันทึกไว้ เทมเพลตจะเป็นไฟล์ DOCX, ODS หรือ XLSX ที่คุณออกแบบผ่านโปรแกรมประมวลผลคำ ซึ่งทำได้ง่ายกว่าการแก้ไข CSS ข้อแลกเปลี่ยนคือ Kimai ไม่มีพอร์ทัลสำหรับลูกค้าและไม่มีเกตเวย์การชำระเงิน คุณจึงต้องส่งไฟล์ PDF ทางอีเมลและรับเงินผ่านการโอนเงิน ส่วน Invoice Ninja นั้นรองรับการติดตามเวลาและมีพอร์ทัลให้ใช้งาน ดังนั้นให้เลือก Invoice Ninja หากการรับชำระเงินผ่านบัตรออนไลน์มีความสำคัญมากกว่ารายละเอียดของบันทึกเวลา
ฉันจำเป็นต้องสำรองข้อมูลอะไรบ้าง?
ฐานข้อมูล, storage volume ที่เก็บโลโก้และไฟล์ PDF ที่สร้างขึ้น, ไฟล์ environment และไฟล์ PDF ที่เก็บไว้เป็นไฟล์ปกติ ไฟล์ environment คือสิ่งที่คนมักลืมสำรองข้อมูล: แอปพลิเคชัน Laravel เช่น Invoice Ninja และ InvoiceShelf จะเข้ารหัสข้อมูลรับรองที่จัดเก็บไว้ด้วย APP_KEY ดังนั้นหากคุณกู้คืนฐานข้อมูลโดยใช้คีย์ที่สร้างขึ้นใหม่ จะทำให้การตั้งค่าเกตเวย์การชำระเงินของคุณอ่านไม่ได้ ให้ทดลองกู้คืนข้อมูลทั้งหมดลงใน instance ชั่วคราวหนึ่งครั้งแล้วเปิดใบแจ้งหนี้เก่าดู เพราะนั่นเป็นวิธีเดียวที่จะยืนยันได้ว่าการสำรองข้อมูลนั้นใช้งานได้จริง