บทความนี้จะแนะนำวิธี ติดตั้ง ERPNext 15 ซึ่งเป็นเวอร์ชั่นล่าสุด โดยจะติดตั้ง บน Ubuntu 22.04 ด้วยคลาวด์ของ AWS EC2

ถ้าคุณกำลังมองหาโปรแกรม ERP มาใช้งานในองค์กร แบบฟรีๆ ผมขอแนะนำโปรแกรม ERPNext ซึ่งเป็น Open Source เราสามารถนำมาใช้ได้ฟรี เพียงแต่อาจมีค่าใช้จ่ายด้าน Server นิดหน่อย ซึ่งขอแนะนำให้ ติดตั้ง บน Ubuntu 22.04 โดยบทความนี้จะแนะนำวิธี ติดตั้ง ERPNext 15 ซึ่งเป็นเวอร์ชั่นล่าสุด โดยจะติดตั้ง บน Ubuntu 22.04 ด้วยคลาวด์ของ AWS EC2
เมื่อเริ่มใช้งาน Ubuntu ใหม่ๆ ต้องเริ่มด้วยการ Update packages ก่อนครับ
sudo apt-get update && sudo apt-get upgrade -yเปลี่ยน TimeZone ให้เปิดดู TimeZone ด้วยคำสั่ง
dateถ้า TimeZone ไม่ตรงกับที่เราต้องการ ให้เปลี่ยนได้เลยครับ เช่น
timedatectl set-timezone "Asia/Bangkok"อาจพิจารณาเปิดพอร์ตเหล่านี้ครับ
sudo ufw allow 22,25,143,80,443,3306,3022,8000/tcp
sudo ufw enableในกรณีที่เราต้องการใช้งาน Multi-Bench เราจะรันคำสั่ง bench init หลายครั้ง ซึ่งแต่ละครั้ง frappe bench จะสร้างโฟลเดอร์แยกออกไป แต่ละโฟลเดอร์จะไม่เกี่ยวกัน จะมี Environment เป็นของตัวเอง เช่น
bench init frappe-bench-1
bench init frappe-bench-2ในกรณีนี้ frappe bench จะสร้างพอร์ตใหม่ให้เราอัตโนมัติ เช่น
frappe-bench-1 ได้พอร์ต 8000, 9000, 13000, 12000, 11000
frappe-bench-2 ได้พอร์ต 8001, 9001, 13001, 12001, 11001
เราอาจพิจารณาใส่พอร์ตเหล่านี้ เพิ่มเติมเข้าไปใน UFW
เมื่ออัพเดท Ubuntu เสร็จแล้ว สร้างบัญชีผู้ใช้ใหม่
sudo adduser frappe
sudo usermod -aG sudo frappe
su frappe
cd /home/frappeเมื่อมีบัญชีผู้ใช้ใหม่แล้ว ให้ติดตั้ง Python ครับ โดยอาจจะติดตั้งโดยตรง หรือติดตั้งผ่าน Anaconda แล้วแต่ความชอบครับ แต่ผมแนะนำให้ติดตั้งผ่าน Anaonda ครับมันไม่ค่อยจุกจิก
curl -O https://repo.anaconda.com/archive/Anaconda3-2024.02-1-Linux-x86_64.shbash Anaconda3-2024.02-1-Linux-x86_64.sh -bถ้าต้องการใช้งาน Conda ให้ activate Conda โดยรันคำสั่ง
source /home/frappe/anaconda3/bin/activateแล้วตามด้วย
conda initถ้าต้องการปิดการใช้งาน Conda ให้ใช้คำสั่ง
conda deactivateบางคนอาจจะชอบให้ Conda activate ตัวเองโดยอัตโนมัติ ให้ใช้คำสั่ง
conda config --set auto_activate_base trueถ้าต้องการปิดการทำงาน ก็ใช้คำสั่ง
conda config --set auto_activate_base falseหมายเหตุ: ถ้าเราไม่ได้ activate Conda เราจะใช้คำสั่ง Bench ไม่ได้นะครับ ดังนั้นก่อนทำงานในโฟลเดอร์
frappe-benchให้ activate Conda ก่อนทุกครั้งครับ
เทคนิคเล็กๆน้อยๆคือ ให้สร้างคำสั่ง alias ไว้ใน.zshrcหรือ.bashrcโดยคัดลอกโค้ดนี้เข้าไป
alias frappe="source /home/frappe/anaconda3/bin/activate && cd ~/frappe-bench"การติดตั้ง Python มากกว่า 1 เวอร์ชั่นจะสร้างปัญหากับ ERPNext พอสมควร ดังนั้นต้องติดตั้งอย่างระมัดระวัง สำหรับคนที่ใช้ Ubuntu 23.04 จะมีเวอร์ชั่น 3.11 มาให้แล้ว สามารถข้ามขั้นตอนนี้ไปได้เลยครับ
เสร็จแล้วก็เพิ่ม repository ของ python เข้าไป
sudo add-apt-repository ppa:deadsnakes/ppa -y
sudo apt-get updateขั้นตอนต่อไป ติดตั้ง python
sudo apt-get install python3-dev python3.11-dev python3-setuptools python3-pip python3-distutilsหรือ แนะนำให้ติดตั้งแบบเต็มเวอร์ชั่นไปเลย
sudo apt-get install python3.11-fullต่อไปก็ ติดตั้ง pip
sudo apt install python3-pip
python3 -m pip install --upgrade pipติดตั้ง Python Virtual Environment
sudo apt-get install python3.10-venv python3.11-venvขั้นตอนนี้สำคัญ ต้องติดตั้ง venv ทั้ง python3.10 และ python3.11 ไม่งั้นจะพบ Error ตอนติดตั้ง ERPNext
กำหนดให้ Python 3.11 เป็นค่า Default
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.10 1
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.11 2เปลี่ยน Python เวอร์ชั่น ด้วยคำสั่ง
sudo update-alternatives --config pythonให้เลือกเบอร์ 2
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bashในกรณีใช้ Zsh
source ~/.zshrc
nvm install 18
sudo apt-get install npmหรือถ้าใช้ Bash
source ~/.bashrc
nvm install 18
sudo apt-get install npmติดตั้ง Redis Server เพื่อจัดการ Cache
sudo apt-get install redis-serverMariaDB ที่ใช้สำหรับ ERPNext เวอร์ชั่น 15 ทาง Frappe แนะนำว่าต้องใช้ MariaDB เวอร์ชั่น 10.6.x ขึ้นไป แต่ไม่ควรเกิน เวอร์ชั่น 10.8.x
sudo apt-get install software-properties-commonsudo apt install mariadb-server mariadb-clientโปรแกรมจิปาถะต่างๆ
sudo apt-get install xvfb libfontconfig wkhtmltopdf
sudo apt-get install libmysqlclient-dev curlsudo mysql_secure_installationต้องมี sudo ด้วยครับ
หลังใช้คำสั่งนี้ จะมีคำถามเด้งขึ้นมาให้ตอบตามนี้ครับ
Enter current password for root: กดปุ่ม Enter ผ่านได้เลยครับเพราะเรายังไม่มีพาสเวิร์ด
Switch to unix_socket authentication [Y/n]: Y
Change the root password? [Y/n]: Y
It will ask you to set new MySQL root password at this step. This can be different from the SSH root user password.
Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] N (ตอบ N เพราะในอนาคตเราจะใช้โปรแกรมวิเคราะห์ข้อมูล Metabase เชื่อมต่อดาต้าเบสแบบ remotely)
Remove test database and access to it? [Y/n] Y
Reload privilege tables now? [Y/n] Y
sudo nano /etc/mysql/mariadb.conf.d/erpnext.cnfให้คัดลอกโค้ดนี้ใส่เข้าไปในไฟล์
[mysqld]
innodb-file-format=barracuda
innodb-file-per-table=1
innodb-large-prefix=1
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
[mysql]
default-character-set = utf8mb4และ Enable Remote Access โดยเข้าไปที่ไฟล์ 50-server.cnf
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnfให้แก้ bind-address = 127.0.0.1 เป็น bind-address = 0.0.0.0
แล้วล็อกอินไปที่ MariaDB
mysql -u root -pใส่รหัสผ่าน
เสร็จแล้วจะเข้ามาที่หน้าจอ MariaDB Command Line
ให้รันคำสั่ง ตามโค้ดด้านล่างนี้
อธิบายโค้ด: SELECT host, user FROM mysql.user; => เป็นการตรวจดูก่อนว่า User root อยู่ตรงไหนบ้าง ซึ่งจากโค้ดตัวอย่างจะเห็นว่า User root จะ Active บน localhost เท่านั้น หมายความว่ามันยังไม่รองรับการเชื่อมต่อแบบ Remote
CREATE USER 'root'@'%' IDENTIFIED BY 'your-password'; => เป็นการ Active ให้ User root ทำงานได้ทุกหมายเลข IP หรือสามารถ Remote ได้นั่นเอง
สำหรับคำสั่งอื่นๆ เป็นคำสั่ง Routine ทั่วไปครับ
เสร็จแล้วให้รีสตาร์ท MariaDB Server
sudo systemctl restart mariadbเสร็จแล้วให้เปิด Firewall สำหรับ Remote Server
sudo ufw allow from x.x.x.x to any port 3306โดยเปลี่ยน x.x.x.x เป็นหมายเลข IP ของ Remote Server
เมื่อมาถึงขั้นตอนนี้ให้ลองทดสอบเชื่อมต่อแบบ Remote ดูครับ ให้ไปที่ Remote Server แล้วพิมพ์คำสั่ง
mysql -u root -h x.x.x.x -pถ้าใส่รหัสผ่านแล้ว สามารถเข้าไปที่หน้าจอของ MariaDB ได้ก็ถือว่าสำเร็จ หมายเหตุ: ให้แทน x.x.x.x ด้วยหมายเลข IP ของ MariaDB Server
sudo apt-get install git
sudo npm install -g yarnสำหรับคำสั่ง npm install ถ้าใช้ sudo แล้วไม่เวิร์ค ให้ตัด sudo ออก
npm install -g yarnsudo -H pip3 install frappe-bench
bench --versionตอนนี้เรามี bench cli บน Ubuntu 22.04 เรียบร้อยแล้ว สามารถใช้คำสั่ง bench ได้เลย
bench init frappe-bench --frappe-branch version-15 --python python3.11คำสั่งนี้สำคัญนะครับ เราต้องระบุ python เวอร์ชั่น 3.11 เข้าไปใน bench init ด้วย
cd frappe-bench
sed -i '/web:/ s/$/ --noreload/' Procfile
pip3 install honcho
yarn add node-sass
sudo chmod -R o+rx /home/frappe
bench startสร้าง เว็บไซต์บน Frappe
bench new-site yourdomain.comอย่าลืม เพิ่มเว็บไซต์ เข้าไปที่ hosts
bench --site yourdomain.com add-to-hostsสามารถเข้าไปตรวจสอบไฟล์ hosts ได้ที่
nano /etc/hostsหรือถ้าต้องการแก้ไขไฟล์ hosts ด้วยตัวเอง ให้ไปที่ root ก่อนนะครับ ดังนี้
sudo su
sudo nano /etc/hostsERPNext
bench get-app erpnext --branch version-15HRMS
bench get-app hrms --branch version-15Payments
bench get-app payments --branch version-15สำหรับ Apps ข้างล่างนี้เป็น Custom Apps เป็นเพียงตัวเลือก (Options) จะติดตั้งหรือไม่ก็ได้ครับ
Print Designer
bench get-app https://github.com/frappe/print_designerERPNext Expenses
bench get-app https://github.com/Upeosoft-Limited/erpnext-expense-management-module.gitCredit: Upeosoft
bench --site yourdomain.com install-app erpnext
bench --site yourdomain.com install-app hrms
bench --site yourdomain.com install-app payments
bench --site yourdomain.com install-app print_designer
bench --site yourdomain.com install-app erpnext_expensesอย่าลืมรันคำสั่ง migrate ครับ
bench --site yourdomain.com migrateใช้คำสั่ง
bench --site yourdomain.com enable-scheduler
bench --site yourdomain.com set-maintenance-mode off
sudo bench setup production <username>ในกรณีของเรา username คือ frappe ดังนั้นใช้คำสั่ง
sudo bench setup production frappeเมื่อถึงขั้นตอนนี้ เราจะได้
Nginx และ Supervisorctl
ทั้ง Nginx และ Supervisorctl อยู่ใน status running
สามารถเปิดเว็บไซต์ที่ http://yourdomain.com
bench config dns_multitenant on
sudo apt-get install certbot python3-certbot-nginx
sudo -H bench setup lets-encrypt yourdomain.combench config dns_multitenant on
bench new-site your-site2-name
bench setup nginx
sudo service nginx reloadข้อมูลที่เราคีย์เข้าระบบ ERP เป็นข้อมูลที่มีความสำคัญมาก ทำหายไม่ได้เด็ดขาด ดังนั้นเราต้องรู้คำสั่งเบื้องต้นในการบำรุงรักษา ฐานข้อมูล ใน ERPNext
ทุกๆคำสั่งต่อไปนี้ ต้องทำงานในโฟลเดอร์ frappe-bench
bash~/frappe-bench$ bench [command]
สำรองข้อมูล + ไฟล์ที่เราอัพโหลดเช่น ไฟล์ภาพพนักงาน ไฟล์ภาพทรัพย์สินถาวร ไฟล์โลโก้บริษัท เป็นต้น
bench --site {sitename} backup --with-filesหรือ สำรองข้อมูล เฉพาะ ฐานข้อมูล
bench --site {sitename} backupสำรองข้อมูลในทุกๆ ไซต์ พร้อมกัน
bench backup-all-sitesหรือ
bench --verbose --site all backupไฟล์ต่างๆที่ได้จากการสำรองข้อมูลจะถูกเก็บไว้ที่
~/frappe-bench/sites/your-site/private/backups/เมื่อต้องการเรียกคืนข้อมูลที่เคยสำรองเอาไว้ ให้เราดูว่าไฟล์ที่สำรอง เก็บไว้ที่ไหน เช่น
bench --site {your site} backup --with-files
Backup Summary for {your site} at 2023-12-07 09:37:06.707378
Config : ./{your site}/private/backups/20231207_093704-{your site}-site_config_backup.json 415.0B
Database: ./{your site}/private/backups/20231207_093704-{your site}-database.sql.gz 2.0MiB
Public : ./{your site}/private/backups/20231207_093704-{your site}-files.tar 50.0KiB
Private : ./{your site}/private/backups/20231207_093704-{your site}-private-files.tar 130.0KiBจะเห็นว่าเมื่อสั่งสำรองข้อมูลด้วย tag --with-files เราจะได้ไฟล์ทั้งหมด 4 ไฟล์ และเก็บไว้ที่ ./{your site}/private/backups/{ชื่อไฟล์}
config file ไว้เก็บชื่อ ฐานข้อมูล เป็นต้น
ไฟล์ฐานข้อมูล ลงท้ายด้วย .sql.gz
ไฟล์สาธารณะ ลงท้ายด้วย .tar
ไฟล์ส่วนตัว ลงท้ายด้วย .tar
bench --site {sitename-เดิม} --force restore [path ฐานข้อมูล] --with-private-files[path ไฟล์ส่วนตัว] --with-public-files[path ไฟล์สาธารณะ]bench new-site {sitename-ใหม่}bench --site {sitename-ใหม่} --force restore [path ฐานข้อมูล] --with-private-files[path ไฟล์ส่วนตัว] --with-public-files[path ไฟล์สาธารณะ]เช่น
bench --site {sitename-ใหม่} --force restore ./{sitename-เก่า}/private/backups/20231207_093704-{sitename-เก่า}-database.sql.gz \
--with-private-files ./{sitename-เก่า}/private/backups/20231207_093704-{sitename-เก่า}-private-files.tar \
--with-public-files ./{sitename-เก่า}/private/backups/20231207_093704-{sitename-เก่า}-files.tarเครื่องจะให้เราใส่รหัสผ่าน สำหรับ MariaDB
MySQL root password: <ระบุ MariaDB พาสเวิร์ด>เมื่อใช้คำสั่งข้างต้น จะได้หน้าจอแบบนี้
เสร็จแล้วสั่งให้ Frappe sync ฐานข้อมูล และสร้างไฟล์ที่จำเป็นสำหรับ {sitename-ใหม่}
bench --site {sitename-ใหม่} migrateจะเห็นหน้าจอ Terminal แสดงผลแบบนี้ครับ
bench set-mariadb-host {IP Address ของ MariaDB}เสร็จแล้วสร้าง site ใหม่
bench new-site {sitename-ใหม่} --mariadb-root-password {your-mariadb-password}ถ้าเราไม่กำหนดชื่อ ฐานข้อมูล Frappe จะตั้งชื่อฐานข้อมูลให้เรา อาจทำให้เราจำชื่อฐานข้อมูลไม่ได้ ดังนั้นถ้าเราต้องการตั้งชื่อ ฐานข้อมูล เอง ให้ทำดังนี้
bench new-site {sitename-ใหม่} --db-name {your-database-name} --mariadb-root-password {your-mariadb-password}ตรวจดูให้แน่ใจ ว่าเราอยู่ที่โฟลเดอร์ frappe-bench แล้วพิมพ์คำสั่ง
source env/bin/activate
pip install --upgrade frappe-benchsudo supervisorctl stop all
bench update --resetข้อสังเกต:
หลัง
bench update --resetทำงานเสร็จแล้ว มันจะ migrate ฐานข้อมูล ให้อัตโนมัติแต่เนื่องจากเราสั่งปิด Services ทั้งหมด ด้วยคำสั่ง
sudo supervisorctl stop allทำให้การ migrate ไม่สำเร็จ โดยมี Warning ดังนี้: Migrating [yoursitename.com] Service redis_cache is not running.Cannot run bench migrate without the services running. If you are running bench in development mode, make sure that bench is running:
ดังนั้นในกรณีนี้เราไม่ต้องใช้คำสั่ง
sudo supervisorctl stop allก็ได้ ให้ใช้คำสั่งbench update --resetได้เลย
ถ้า Ubuntu 22.04 ฟ้องว่า
manpath: can't set the locale; make sure $LC_* and $LANG are correctให้แก้ด้วยคำสั่ง
sudo dpkg-reconfigure localesจะมีหน้าจอเลือกภาษา Pop-up ขึ้นมา ให้เลือกภาษาไทย ดังนี้
th_TH.UTF-8 UTF-8
mysqldump -u [username] -p [database_name] > backup.sqlsudo systemctl stop mariadbsudo apt-get purge mariadb-server mariadb-client mariadb-common
sudo apt-get autoremove
sudo apt-get autocleansudo userdel -r mysql
sudo groupdel mysqlsudo rm -rf /etc/mysql/
sudo rm -rf /var/lib/mysql/sudo bench renew-lets-encryptคำสั่งนี้จะตรวจสอบ Certificates ทั้งหมดที่เรามีใน ERPNext ถ้าโดเมนไหนยังไม่หมดอายุ มันจะข้ามอัตโนมัติ มันจะ Renew เฉพาะโดเมนที่หมดอายุเท่านั้น ซึ่งทำให้การ Renew Certificates สะดวกมากๆ
Pain Point: กรณีที่มีบางไฟล์มีการแก้ไข เช่นไฟล์ translations -> th.csv เราได้เข้าไปแก้ภาษาไทย ให้ดูสละสลวยมากขึ้น ถ้าเราใช้คำสั่ง bench update ไฟล์ th.csv จะโดนแทนที่ด้วยไฟล์ต้นฉบับ
Solution: ให้ใช้คำสั่งดังนี้
เข้าไปที่โฟลเดอร์
frappe-bench/apps/erpnext/erpnext
และ
frappe-bench/apps/frappe/frappe
ทีละโฟลเดอร์ แล้วใช้คำสั่ง
git statusเพื่อดูว่ามีไฟล์ที่โดนแก้ไขอยู่บ้างมั๊ย ถ้ามี ให้ใช้คำสั่ง
git add --all
git stashเสร็จแล้วจึงใช้คำสั่ง
bench updateเมื่อ bench update ทำงานเสร็จแล้ว เราก็ดึงไฟล์ th.csv กลับมา โดยเข้าไปที่แต่ละโฟลเดอร์ที่กล่าวมาข้างต้น แล้วใช้คำสั่ง
git stash applyb'/usr/bin/bash: line 1: file: command not found\n'ให้แก้โดย ติดตั้ง package file
sudo apt-get install filePain Point: หลังจากรันคำสั่ง bench update แล้วเครื่องค้างนานเกินไป ไม่จำเป็นต้องนั่งรอนะครับ ให้รีบู๊ตเครื่องใหม่
Solution: พอเครื่องรีสตาร์ทเรียบร้อยแล้ว ให้ใช้คำสั่ง
bench update --resetPain Point: หลังใช้คำสั่ง bench new-app <app-name> แล้ว supervisor จะรีสตาร์ทใหม่ แต่อาจเกิดปัญหาในบางจุด ทำให้ supervisor รีสตาร์ทไม่สำเร็จ เช่น ข้อมูลด้านล่างนี้ node-socketio เกิด Error (spawn error)
frappe-bench-workers:frappe-bench-frappe-schedule: stopped
frappe-bench-workers:frappe-bench-frappe-short-worker-0: stopped
frappe-bench-workers:frappe-bench-frappe-long-worker-0: stopped
frappe-bench-web:frappe-bench-frappe-web: stopped
frappe-bench-workers:frappe-bench-frappe-schedule: started
frappe-bench-workers:frappe-bench-frappe-short-worker-0: started
frappe-bench-workers:frappe-bench-frappe-long-worker-0: started
frappe-bench-web:frappe-bench-node-socketio: ERROR (spawn error)
frappe-bench-web:frappe-bench-frappe-web: started
ERROR: sudo supervisorctl restart frappe-bench-workers: frappe-bench-web:Solution: ให้แก้ดังนี้ รันคำสั่งเหล่านี้ทีละคำสั่ง
bench setup socketio
bench setup supervisor
bench setup redis
sudo supervisorctl reloadในกรณีที่เราติดตั้ง Custom app เช่น หลังใช้คำสั่งนี้
bench get-app https://github.com/Upeosoft-Limited/erpnext-expense-management-module.git
bench --site [SITE_NAME] install-app erpnext_expensesแล้วเกิดปัญหา ModuleNotFoundError! ที่ Web Browser ให้ลองแก้โดยไปที่ Server แล้วรันคำสั่ง
bench setup requirements
sudo supervisorctl restart allหรือถ้าเป็น Development mode ให้ใช้ bench restart แทน
bench setup requirements
bench restartถ้ายังแก้ไม่ได้ให้ใช้คำสั่ง
bench update --reset
bench setup requirementsPain Point: หลังจาก Import ข้อมูลมาจากฐานข้อมูลเก่า แล้วพบ Bug เช่นเรา Import ข้อมูลพนักงานมา ตรงรหัสพนักงานมีเครื่องหมายคำพูดติดมาด้วย ซึ่งปกติไม่ต้องมี เมื่อ ERPNext ดึงข้อมูลเหล่านี้ไปประมวลผล จะทำให้เกิด Bug โปรแกรมทำงานแบบไม่เต็มร้อย

Solution: ให้แก้ดังนี้
1. คลิ๊กตรงชื่อ

2. ให้ลบเครื่องหมายคำพูดออก
3. เสร็จแล้วกดปุ่ม Rename

เมื่อกลับมาที่หน้าจอ Employee ให้ Refresh เราจะได้รหัสพนักงานที่ไม่มีเครื่องหมายคำพูด ซึ่งจะทำให้โปรแกรม ERPNext กลับมาทำงานเป็นปกติ

Pain Point: หลังจาก Import ข้อมูลมาจากฐานข้อมูลเก่า แล้วเกิดปัญหา
Scheduler Inactive Scheduler is inactive. Cannot import data.

เช่น ในกรณีที่คุณขายของบน Lazada และมีรายการขายค่อนข้างมาก คุณคงไม่สามารถคีย์ข้อมูลแบบ Manual ได้นะครับ จำเป็นต้อง Import ข้อมูลจาก Lazada เข้ามา แต่ถ้า Scheduler Inactive อยู่ คุณจะ Import ข้อมูลไม่ได้ครับ
Solution: มีวิธีแก้ไขปัญหาดังนี้
1. ให้ลองใช้คำสั่ง bench doctor จะเห็น Terminal แสดงข้อมูลประมาณนี้ครับ
bench doctor
-----Checking scheduler status-----
Scheduler paused for your-domain.com
your-domain.com: frappe.conf.pause_scheduler is SET
Scheduler inactive for your-domain.com
Workers online: 2
-----None Jobs-----2. ให้ใช้คำสั่ง
bench --site your-domain.com set-config pause_scheduler 0Scheduler ก็จะกลับมาทำงานปกติครับ และคุณสามารถ Import ข้อมูลจาก Lazada ได้แล้ว
ปัญหา: หลังจาก Import ข้อมูลจากฐานข้อมูลเก่า (หรือแม้แต่หลัง restart ปกติ) Scheduler กลับกลายเป็น Inactive เราอาจเห็น error เช่น Scheduler is inactive. Cannot enqueue job. — โดยเฉพาะเมื่อ submit POS Closing Entry หรือ job ที่ใช้ background queue อื่นๆ
สาเหตุที่แท้จริง: Scheduler สามารถอยู่ในสถานะ paused ได้แม้ว่า pause_scheduler จะเป็น 0 ใน site_config แล้ว Flag นี้ไม่ได้ถูกอ่านอย่างถูกต้องทุกครั้งหลัง restart ทำให้ scheduler ติดอยู่ในสถานะครึ่งๆ ค้าง ที่ bench doctor แสดงว่า "paused" และ "inactive" แต่ scheduler บอกว่า "enabled" การตั้งค่า pause_scheduler เป็น 0 อย่างเดียวไม่สามารถแก้ได้
_วิธีแก้ที่ถูกต้อง — disable → enable cycle:
# ขั้นตอนที่ 1: Disable แล้ว Enable scheduler (บังคับให้อ่าน config ใหม่)
bench --site your-domain.com disable-scheduler
bench --site your-domain.com enable-scheduler
# ขั้นตอนที่ 2: Restart เต็มรูปแบบเพื่อให้ workers รับ new state
bench restart
# ขั้นตอนที่ 3: ตรวจสอบ — งานควรแสดงใน queue แล้ว
bench doctorหลังจากทำ cycle แล้ว, bench doctor ควรแสดง jobs ที่อยู่ใน queue อย่าง active ใน default และ long queues:
Queue: default
Number of Jobs: 30
Queue: long
Number of Jobs: 57
ถ้า POS Closing Entry ล้มเหลวก่อนหน้านี้ ให้ลอง submit ใหม่ — ควรจะผ่านแล้ว
ปัญหานี้อาจเกิดจากเราเปลี่ยนสภาพแวดล้อมจาก Production ไป Development แล้วลืมเอากลับมาเป็น Production และด้วยเหตุอันใดก็ตามเราบังเอิญไปย้ายฐานข้อมูลไปไว้ที่ไหม่ ทำให้ค่า Config ติดไปด้วย ดังนั้นเราจึงต้องทำความเข้าใจโครงสร้างไฟล์ที่เกี่ยวกับค่า Config
โครงสร้างไฟล์ที่เป็นค่า Config ของ Frappe/ERPNext จะอยู่ที่โฟลเดอร์ sites ตามรูปนี้ครับ

โดยในโฟลเดอร์ sites จะมีไฟล์ common_site_config.json ซึ่งทุกๆไซต์จะใช้งานไฟล์นี้ร่วมกัน ให้สังเกตคำว่า common
ค่า Config มีอะไรบ้างดูตามรูปนี้ครับ

จะเห็นว่าค่า maintenance_mode และ pause_scheduler แสดงเป็นเลข 1 หมายความว่ามันอยู่ในสถานะเปิด มันจึงส่งผลให้ Scheduler Inactive ในทุกๆไซต์
ถ้าต้องการปิด maintenance_mode เรามี 2 ทางเลือก
1. แก้ maintenance_mode และ pause_scheduler ในไฟล์ common_site_config.json ให้เป็นเลข 0 หรือ
2. ให้เราไปแก้ทีละไซต์ในไฟล์ site_config.json ตามรูปนี้


สิ่งที่ต้องเตรียม เลข IP Address ของ Master Server
(Master มีข้อมูลอยู่แล้ว)
1. กำหนด Server ID ให้ Master โดยรันคำสั่ง
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnfแล้วแก้ไขไฟล์ 50-server.cnf ดังนี้ โดยคอมเม้นท์บรรทัด bind-address
[mysqld]
server-id = 1
log-bin = mysql-bin
#comment bind-address
#bind-address = 127.0.0.1เสร็จแล้ว restart MariaDB
sudo systemctl restart mariadb2. เข้าไปที่ MariaDB เพื่อสร้าง User rep_user โดยกำหนดให้เป็น Slave User ดังนี้
mysql -u root -pใส่รหัสผ่านเพื่อเข้าสู่หน้าจอของ MariaDB แล้วสร้าง User ได้เลย
CREATE USER 'rep_user'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'rep_user'@'%';
FLUSH PRIVILEGES;3. คัดลอกฐานข้อมูลจาก Master ไปที่ Slave
บน Terminal MariaDB รันคำสั่ง
FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS\Gจะได้ผลลัพธ์ออกมาหน้าตาประมาณนี้
MariaDB [(none)]> SHOW MASTER STATUS\G
*************************** 1. row ***************************
File: master-bin.000009
Position: 43510
Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.000 sec)จดข้อมูล File และ Position เอาไว้ เสร็จแล้วออกไปที่หน้าจอ Terminal Ubuntu เพื่อสำรองไฟล์ฐานข้อมูล
mysqldump -u root -p --all-databases --master-data > backup.sqlใช้โปรแกรม FileZilla เพื่อ ดาวน์โหลดไฟล์ backup.sql และอัพโหลดไปไว้ที่ Slave Server
1. กำหนด Server ID ให้ Slave โดยรันคำสั่ง
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnfแล้วแก้ไขไฟล์ 50-server.cnf ดังนี้ โดยคอมเม้นท์บรรทัด bind-address
[mysqld]
server-id = 2
#comment bind-address
#bind-address = 127.0.0.1เสร็จแล้ว restart MariaDB
2. วาง Database ที่คัดลอกมาจาก Master โดยรันคำสั่งนี้บน Ubuntu
mysql -u root -p < backup.sqlเสร็จแล้วให้เข้าไปที่ MariaDB terminal แล้วรันคำสั่ง
STOP SLAVE;
CHANGE MASTER TO
MASTER_HOST='master_ip',
MASTER_USER='rep_user',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='master-bin.000009',
MASTER_LOG_POS=43510;
START SLAVE;Pain Point: หลังจากติดตั้ง ERPNext บนเซิร์ฟเวอร์ที่มี RAM เพียงพอแล้ว แต่เว็บไซต์กลับแสดง Error 504 Gateway Time-out โดยเฉพาะเมื่อโหลดหน้าที่ต้องดึงข้อมูลจากฐานข้อมูลจำนวนมาก เซิร์ฟเวอร์มีการใช้งาน Disk I/O สูงมาก ทั้งที่ CPU ยังมีทรัพยากรเหลืออยู่
สาเหตุ: ค่าเริ่มต้นของ MariaDB สำหรับ innodb_buffer_pool_size คือเพียง 128MB เท่านั้น เมื่อ buffer pool มีขนาดเล็กเกินไป ทุกการ query ฐานข้อมูลต้องอ่านจาก Disk แทนที่จะอ่านจาก RAM ทำให้เกิดปัญหา I/O bottleneck และ request timeout ในการใช้งานจริง
ที่ MooCoding เราเจอปัญหานี้บน Deployment ของ AWS Solution Ltd. บนเซิร์ฟเวอร์ที่มี RAM 16GB เว็บไซต์เกิด Error 504 แทบทุกหน้า หลังจากตรวจสอบ buffer pool hit rate พบว่าอยู่ที่ใกล้ 0% ยืนยันว่าทุกการ query ต้องอ่านจาก Disk
Solution: เพิ่มค่า innodb_buffer_pool_size ให้อยู่ที่ประมาณ:
ขั้นที่ 1. ตรวจสอบค่า buffer pool ปัจจุบัน:
mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';"ถ้าค่าที่ได้คือ 134217728 (128MB) แสดงว่าต้องเพิ่มค่านี้
ขั้นที่ 2. สร้างไฟล์ config ที่ปรับแต่งแล้ว (อย่าแก้ไขไฟล์ 50-server.cnf โดยตรง):
sudo nano /etc/mysql/mariadb.conf.d/99-frappe-optimized.cnfให้วางการตั้งค่านี้ — ปรับ innodb_buffer_pool_size ตาม RAM ของเซิร์ฟเวอร์:
[mysqld]
# เซิร์ฟเวอร์ RAM 16GB ที่รัน App + DB บนเครื่องเดียวกัน → ใช้ ~40%
innodb_buffer_pool_size = 6G
# เซิร์ฟเวอร์ DB เฉพาะ RAM 16GB → ใช้ ~60%
# innodb_buffer_pool_size = 8G
innodb_log_file_size = 512M
innodb_flush_method = O_DIRECT
innodb_file_per_table = 1
max_allowed_packet = 256M
max_connections = 500
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mariadb-slow.log
long_query_time = 2
character_set_server = utf8mb4
collation_server = utf8mb4_unicode_ciขั้นที่ 3. สร้างโฟลเดอร์สำหรับ slow query log:
sudo mkdir -p /var/log/mysql
sudo chown mysql:adm /var/log/mysql
sudo chmod 750 /var/log/mysqlขั้นที่ 4. รีสตาร์ท MariaDB:
sudo systemctl restart mariadbขั้นที่ 5. ตรวจสอบว่าการตั้งค่าใหม่มีผลแล้ว:
mysql -e "SHOW VARIABLES WHERE Variable_name IN (
'innodb_buffer_pool_size', 'slow_query_log', 'max_connections');"เพิ่มเติม — ลดค่า swappiness (ฐานข้อมูลไม่ชอบ Swap):
echo 1 | sudo tee /proc/sys/vm/swappiness
echo 'vm.swappiness = 1' | sudo tee /etc/sysctl.d/99-db-tuning.conf
sudo sysctl -p /etc/sysctl.d/99-db-tuning.confหมายเหตุ: หลังจาก MariaDB รีสตาร์ทแล้ว buffer pool ต้องใช้เวลาในการ warm up ค่า hit rate จะค่อยๆ ดีขึ้นในชั่วโมงแรก หลังจากผ่านไปไม่กี่วัน hit rate ควรจะอยู่ที่ใกล้ 99.9%+ และ Error 504 ควรหายไปอย่างถาวร
การ Deploy ERPNext Ubuntu 22.04 ต้องติดตั้งซอฟท์แวร์ ต่อไปนี้ให้แล้วเสร็จก่อนติดตั้ง Frappe Bench
1. ติดตั้ง Python 3.11
2. NodeJS V20+ ผ่าน NVM
3. Redis Server V5
4. MariaDB V10.6-10.8
5. Yarn และ Git
6. Nginx, cron และ wkhtmltopdf
MariaDB [(none)]> SELECT host,user FROM mysql.user;
+-----------+---------------+
| Host | User |
+-----------+---------------+
| localhost | mariadb.sys |
| localhost | metabase_user |
| localhost | mysql |
| localhost | root |
+-----------+---------------+
4 rows in set (0.001 sec)
MariaDB [(none)]> CREATE USER 'root'@'%' IDENTIFIED BY 'your-password';
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' WITH GRANT OPTION;
Query OK, 0 rows affected (0.001 sec)
หรือจำเพาะเจาะจงเฉพาะ Server ที่เราต้องการใช้งาน
MariaDB [(none)]> CREATE USER 'root'@'remote-server-ip' IDENTIFIED BY 'your-password';
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'root'@'remote-server-ip' WITH GRANT OPTION;
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.001 sec)
MariaDB [(none)]> EXIT;SETVAL(`crm_note_id_seq`, 1, 0)
1
SETVAL(`prospect_opportunity_id_seq`, 1, 0)
1
SETVAL(`pwa_notification_id_seq`, 1, 0)
1
SETVAL(`web_form_list_column_id_seq`, 1, 0)
1
App frappe already installed
*** Scheduler is enabled ***
Site {sitename-ใหม่} has been restored with filesbench --site {sitename-ใหม่} migrate
Migrating {sitename-ใหม่}
Updating DocTypes for frappe : [========================================] 100%
Updating DocTypes for erpnext : [========================================] 100%
Updating DocTypes for hrms : [========================================] 100%
Updating DocTypes for payments : [========================================] 100%
Updating DocTypes for print_designer: [========================================] 100%
Updating Dashboard for frappe
Updating Dashboard for erpnext
Updating Dashboard for hrms
Updating Dashboard for payments
Updating Dashboard for print_designer
Updating customizations for Address
Updating customizations for Contact
Queued rebuilding of search index for {sitename-ใหม่}