วิธีติดตั้ง Nginx กับ DirectAdmin

วิธีติดตั้ง nginx แบบนี้เหมาะสำหรับ server ที่มีหลายเว็บไซต์ในเครื่องเดียว เช่น Server ที่ให้บริการ Web Hosting ครับ เนื่องจากจะมีการ กระจาย cache และ config ของ nginx ไปยังทุกๆ user ของ directadmin


ขั้นตอนจะยุ่งยากนิดนึงครับ ถ้าท่านไม่มั่นใจกรุณาแจ้งให้เจ้าหน้าที่ของเราติดตั้งให้นะครับ
สำหรับท่านที่ต้องการติดตั้งเองค่อยๆ ทำตามมีละบรรทัดนะครับใจเย็นๆ พร้อมแล้วเริ่มเลยดีกว่าครับ


ขั้นตอนที่ 1 ก่อนอื่นเข้าไปดูก่อนครับว่า nginx version ล่าสุดเป็น version อะไรที่
http://nginx.org/en/download.html


*สำหรับ NginX Version ใหม่ๆ ฟังก์ชั่นบางตัวที่สาธิตในการติดตั้งครั้งนี้อาจถูกเลิกใช้แล้ว หรือถูกแทนที่ด้วย ฟังก์ชั่นใหม่แล้ว กรุณาอ้างอิง ฟังก์ชั่นใหม่ๆ หรือฟังก์ชั่นที่ยกเลิกไปแล้วกับ nginx.org โดยตรงนะครับ
** แล้วจะรู้ได้อย่างไรว่าฟังก์ชั่นไหนยกเลิกไปแล้ว ก็ลองติดตั้งแล้ว start nginx ดูครับ จะแสดงข้อความว่า start ไม่ได้เพราะอะไร แล้วไล่แก้เอาครับ


ขั้นตอนที่ 2 พบแล้วก็ download ลงมาเลยครับ ยกตัวอย่างว่าผมเจอ เป็น version 1.3.15
wget http://nginx.org/download/nginx-1.3.15.tar.gz


ขั้นตอนที่ 3 แตกไฟล์
tar xzf nginx-1.3.15.tar.gz


ขั้นตอนที่ 4 ทำการติดตั้ง (ทีละบรรทัดนะครับ)
cd nginx-1.3.15
./configure --sbin-path=/usr/local/sbin --with-http_ssl_module
make
make install



ขั้นตอนที่ 5 แก้ไขไฟล์ config

nano -w /usr/local/nginx/conf/nginx.conf

ขั้นตอนที่ 6 ใส่ค่าดังนี้ (ดูดีๆ นะครับ ใน code ชุดนี้มีจุดที่ต้องเปลี่ยน IP ด้วย) และ

user apache apache;
worker_processes 4;
worker_rlimit_nofile 150000;

error_log /var/log/nginx/error_log;

pid /var/run/nginx/nginx.pid;

events {
worker_connections 25000;
}

http {
include mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log off

limit_zone one $binary_remote_addr 10m;
limit_conn one 7;
limit_rate 512K;
limit_zone cglob $binary_remote_addr 16m;

client_header_timeout 60;
client_body_timeout 60;
send_timeout 120;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_send_timeout 180;

msie_padding on;

proxy_buffer_size 32K;
proxy_buffers 64 512K;
proxy_busy_buffers_size 1024K;
proxy_temp_file_write_size 1024K;

gzip on;
gzip_min_length 10240;
gzip_buffers 32 64k;
gzip_types application/x-javascript text/css text/xml text/plain;

client_header_buffer_size 4K;
client_max_body_size 100000000;
large_client_header_buffers 16 8K;

sendfile on;
tcp_nopush on;
tcp_nodelay on;

output_buffers 32 256k;
postpone_output 1460;

lingering_time 30;
lingering_timeout 6;
reset_timedout_connection on;

keepalive_timeout 10;
server_names_hash_bucket_size 10240;

server {
listen **ใส่ ip ของ server ที่นี่**:85 default rcvbuf=8192 sndbuf=16384;
server_name localhost;
access_log /var/log/httpd/access_log main;
error_log /var/log/nginx/error_log info;

location / {
proxy_pass http://**ใส่ ip ของ server ที่นี่**/;
proxy_redirect off;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

# Main Static files location
#location ~* ^/(phpmyadmin|webmail|squirrelmail|uebimiau|roundcube)/.+\.(jpg|jpeg|gif|png|ico|css|zip|tar|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|wav|bmp|rtf|js|wmv|avi|cur|swf|mp3|wma|htc|cur)$ {
#root /var/www/html/;
#expires 30d;
#access_log off;
#}

# MRTG
#location ~* ^/(stats|mrtg)/.+\.(jpg|jpeg|gif|png|html|htm)$ {
#root /var/www/html/;
#access_log off;
#}

#Static files location
#location ~* ^.+\.(jpg|jpeg|gif|mp3|png|avi|vob|mpg|mpeg|mp4|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|wav|bmp|rtf|js)$ {
#root /var/www/html;
#}

#some bot does not send user-agent, just block them
if ($http_user_agent = "") {
set $proxyflag "forbidden";
return 403;
}

#security for timthumb remote code execution exploit
if ($request_uri ~* "\.php.*src=.*(flickr\.com|picasa\.com|blogger\.com|wordpress\.com|img\.youtube\.com|upload\.wikimedia\.org|photobucket\.com|imgur\.com|imageshack\.us|tinypic\.com)") {
set $proxyflag "forbidden";
return 403;
}

#cached folder should not have any php file
if ($request_uri ~* "/cache/.*\.php") {
set $proxyflag "forbidden";
return 403;
}

#bad behavior url (known botnet/trojan)
if ($request_uri ~* "\?.*eval\(") {
set $proxyflag "forbidden";
return 403;
}
if ($request_uri ~* "act=phptools") {
set $proxyflag "forbidden";
return 403;
}

#sql injection tools
if ($http_user_agent ~* "Havij") {
set $proxyflag "forbidden";
return 403;
}
if ($http_user_agent ~* "^sqlmap/") {
set $proxyflag "forbidden";
return 403;
}
}
include /usr/local/nginx/etc/virtual.conf;
}


เมื่อเรียบร้อยแล้วจากนั้นให้สร้าง 4 ไฟล์ตามลำดับดังนี้

ขั้นตอนที่ 7 สร้างไฟล์ที่ 1 ด้วยคำสั่ง
nano -w /usr/local/directadmin/data/templates/custom/nginx.conf


ขั้นตอนที่ 8 ใส่ข้อความด้านล้างนี้ลงไปในไฟล์ที่สร้า้งในขั้นตอนที่ 7
server {
listen |IP|:85;
server_name |DOMAIN| www.|DOMAIN| |SERVER_ALIASES|;
access_log /var/log/httpd/domains/|DOMAIN|.log main;
error_log /var/log/httpd/domains/|DOMAIN|.error.log error;
location / {
proxy_pass http://|IP|;
proxy_redirect off;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

client_max_body_size 10m;
client_body_buffer_size 128k;

proxy_connect_timeout 60;
proxy_send_timeout 90;
proxy_read_timeout 90;

proxy_buffer_size 64k;
proxy_buffers 120 256k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
}

location @back {
proxy_pass http://|IP|;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

#Static files location
location ~* ^.+\.(jpg|jpeg|gif|mp3|png|avi|vob|mpg|mpeg|mp4|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|wav|bmp|rtf|js)$ {
root |HOME|/domains/|DOMAIN|/public_html;
expires 14d;
error_page 404 = @back;
}
}


ขั้นตอนที่ 9 สร้างไฟล์ที่ 2 ด้วยคำสั่ง
nano -w /usr/local/directadmin/scripts/nginx_direct.sh


ขั้นตอนที่ 10 ใส่ข้อความด้านล้างนี้ลงไปในไฟล์ที่สรา้งขึ้นในขั้นตอนที่ 9
#!/bin/bash

NGINXHOST=/usr/local/nginx/etc/virtual.conf;

PATH_CONF=/usr/local/directadmin/data/users;

NGINXTEMPATE=/usr/local/directadmin/data/templates/custom/nginx.conf;

NGINXSUBTEMPATE=/usr/local/directadmin/data/templates/custom/nginx_sub.conf;

HOLD=/tmp/nginx.conf.$$;

 

showHelp() {

echo "Rewrite all users's nginx.conf from template:";

echo "$0 all ";

echo "Rewrite users nginx.conf :";

echo "$0 -u username";

echo "For useing modify nginx.conf , you mast create file:";

echo "/usr/local/directadmin/data/users/USERNAME/domains/DOMAIN_NAME.custom_nginx with modify config.";

}

do_exit() {

exit 1;

}

check_user(){

if [ "$1" = "" ] ; then

#echo "User not exit";

return 1;

else

return 0;

fi

}

check_domain()

{

if [ ! -s $1 ];then

return 1;

else

return 0;

fi

}

user_configs(){

_UHOME=`grep -e "^${1}:" /etc/passwd | cut -d: -f6`;

_USER=$1;

_DOMAINLIST=${PATH_CONF}/$_USER/domains.list;

_NGINXCONF=${PATH_CONF}/$_USER/nginx.conf;

if ! check_user $_UHOME; then

return 1;

fi

if ! check_domain $_DOMAINLIST; then

return 1;

fi

_UIP=`cat ${PATH_CONF}/$_USER/user.conf | grep ip= | cut -d= -f2`;

if [ ! -f $_NGINXCONF ]

then

echo "include $_NGINXCONF;" >> $NGINXHOST;

else

cat $_NGINXCONF > $HOLD;

rm -rf $_NGINXCONF;

fi

 

for i in `cat $_DOMAINLIST`; do

if [ -f ${PATH_CONF}/$_USER/domains/$i.custom_nginx ]

then

cat ${PATH_CONF}/$_USER/domains/$i.custom_nginx >> $_NGINXCONF;

else

if [ -f ${PATH_CONF}/$_USER/domains/$i.pointers ]

then

for j in `cat ${PATH_CONF}/$_USER/domains/$i.pointers | awk -F= '{print $1}' `; do

park=`echo "$park $j www.$j"`;

done

fi

if ! cat $NGINXTEMPATE | sed 's#|HOME|#'$_UHOME'#g' | sed 's!|DOMAIN|!'$i'!g' |sed 's/|SERVER_ALIASES|/'"$park"'/' | sed 's!|IP|!'$_UIP'!' | sed 's!|USERNAME!'$1'!' >> $_NGINXCONF; then

if [ -f $HOLD ]; then

cat $HOLD > $_NGINXCONF;

fi

return 1;

fi

fi

for l in `cat ${PATH_CONF}/$_USER/domains/$i.subdomains`; do

cat $NGINXSUBTEMPATE | sed 's#|HOME|#'$_UHOME'#g' | sed 's!|DOMAIN|!'$i'!g'|sed 's/|SUB|/'$l'/g' | sed 's!|IP|!'$_UIP'!' | sed 's!|USERNAME|!'$1'!' >> $_NGINXCONF;

done

park="";

done

if [ -f $HOLD ]; then

rm -rf $HOLD;

fi

}

doAll(){

for i in `ls /usr/local/directadmin/data/users/`; do

user_configs $i;

done

}

 

case "$1" in

all) doAll;

;;

-u) user_configs $2;

;;

* ) showHelp;

do_exit 0;

;;

esac

do_exit 0;


ขั้นตอนที่ 11 สร้างไฟล์ที่ 3 ด้วยคำสั่ง
nano -w /usr/local/directadmin/scripts/nginx_task.sh

ขั้นตอนที่ 12 ใส่ข้อความด้านล้างนี้ลงไปในไฟล์ที่สร้างขึ้นในขั้นตอนที่ 11
#!/bin/bash

if [ -f /usr/local/nginx/etc/task.nginx ]; then

`cat /usr/local/nginx/etc/task.nginx | sort -u > /usr/local/nginx/etc/task.nginx.do`

rm -rf /usr/local/nginx/etc/task.nginx

while read LINE

do

`echo sh $LINE`;

done < /usr/local/nginx/etc/task.nginx.do

rm -rf /usr/local/nginx/etc/task.nginx.do

/etc/init.d/nginx reload

fi


ขั้นตอนที่ 13 สร้างไฟล์ที่ 4
nano -w /usr/local/directadmin/scripts/nginx_del.sh

ขั้นตอนที่ 14 ใส่ข้อความด้านล่างนี้ลงไปในไฟล์ที่สร้างในขั้นตอนที่ 13
#!/bin/bash

USER_CONF="include /usr/local/directadmin/data/users/$1/nginx.conf;";

if cp /usr/local/nginx/etc/virtual.conf /usr/local/nginx/etc/virtual.conf.bak; then

rm -rf /usr/local/nginx/etc/users/$1;

STR="/usr/bin/perl -pi -e 's#$USER_CONF##' /usr/local/nginx/etc/virtual.conf.bak";

eval ${STR};

sed '/^$/d' /usr/local/nginx/etc/virtual.conf.bak > /usr/local/nginx/etc/virtual.conf;

rm -rf /usr/local/nginx/etc/virtual.conf.bak

fi


ขั้นตอนที่ 15 ทำการเปลี่ยน Directory
cd /usr/local/directadmin/scripts/custom

ขั้นตอนที่ 16 สร้าง script สั่งการทำงานของ NginX ให้ DirectAdmin ค่อยๆ สั่งทีละบรรทัดนะครับ
echo "echo \"/usr/local/directadmin/scripts/nginx_direct.sh -u \$username\" >> /usr/local/nginx/etc/task.nginx" > domain_create_post.sh;
echo "echo \"/usr/local/directadmin/scripts/nginx_direct.sh -u \$username\" >> /usr/local/nginx/etc/task.nginx" > domain_destroy_post.sh;
echo "echo \"/usr/local/directadmin/scripts/nginx_direct.sh -u \$username\" >> /usr/local/nginx/etc/task.nginx" > domain_pointer_create_post.sh;
echo "echo \"/usr/local/directadmin/scripts/nginx_direct.sh -u \$username\" >> /usr/local/nginx/etc/task.nginx" > domain_pointer_destroy_post.sh;
echo "echo \"/usr/local/directadmin/scripts/nginx_direct.sh -u \$username\" >> /usr/local/nginx/etc/task.nginx" > subdomain_create_post.sh;
echo "echo \"/usr/local/directadmin/scripts/nginx_direct.sh -u \$username\" >> /usr/local/nginx/etc/task.nginx" > subdomain_destroy_post.sh;
echo "echo \"/usr/local/directadmin/scripts/nginx_direct.sh -u \$username\" >> /usr/local/nginx/etc/task.nginx" > user_create_post.sh;
echo "echo \"/usr/local/directadmin/scripts/nginx_del.sh $username" > user_destroy_post.sh;

ขึ้นตอนที่ 17 ทำการเปลี่ยนเจ้าของไฟล์ให้ DirectAdmin สามารถรันได้
chown diradmin:diradmin -R /usr/local/directadmin/scripts/*

ขั้นตอนที่ 18 ทำการเปลี่ยน Permission ไฟลให้รันได้์
chmod a+x /usr/local/directadmin/scripts/custom/*.sh
chmod a+x /usr/local/directadmin/scripts/*.sh

ขั้นตอนที่ 19 เรียบร้อยแล้วสร้าง cron เพื่อรัน script ที่เราสร้างไว้ทุกๆ 2 นาทีด้วยคำสั่ง
echo "*/2 * * * * /usr/local/directadmin/scripts/nginx_task.sh" >> /etc/crontab
/etc/init.d/crond restart

ขั้นตอนที่ 20 ให้สร้างไฟล์ nginx_sub.conf
nano -w /usr/local/directadmin/data/templates/custom/nginx_sub.conf

ขั้นตอนที่ 21 ใส่ข้อความด้านล้างนี้ลงไปในไฟล์ที่สร้างในขั้นตอนที่ 20
server {
listen |IP|:85;

server_name |SUB|.|DOMAIN| www.|SUB|.|DOMAIN|;

access_log /var/log/httpd/domains/|DOMAIN|.|SUB|.log main;

error_log /var/log/httpd/domains/|DOMAIN|.|SUB|.error.log error;

location / {

proxy_pass http://|IP|;

proxy_redirect off;

 

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

 

client_max_body_size 10m;

client_body_buffer_size 128k;

 

proxy_connect_timeout 60;

proxy_send_timeout 90;

proxy_read_timeout 90;

 

proxy_buffer_size 4k;

proxy_buffers 120 64k;

proxy_busy_buffers_size 64k;

proxy_temp_file_write_size 64k;

 

}

location @back {

proxy_pass http://|IP|;

proxy_redirect off;

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}

#Static files location

location ~* ^.+\.(jpg|jpeg|gif|mp3|png|avi|vob|mpg|mpeg|mp4|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|wav|bmp|rtf|js)$ {

root |HOME|/domains/|DOMAIN|/public_html/|SUB|;

expires 14d;

error_page 404 = @back;

}

}


ขั้นตอนที่ 22 สร้างโฟลเดอร์ 2 ชุด ทีละบรรทัดนะครับ
mkdir /var/run/nginx/
mkdir /usr/local/nginx/etc/

ขั้นตอนที่ 23 สร้างไฟล์เปล่า ชื่อ virtual.conf
vi /usr/local/nginx/etc/virtual.conf

ขั้นตอนที่ 24 สร้างโฟลเดอร์เพื่อเก็บ log
mkdir /var/log/nginx

ขั้นตอนที่ 25 สร้างไฟล์เปล่าเพื่อเก็บ log
/var/log/nginx/error_log

ขั้นตอนที่ 26 กระจาย nginx config เข้าไปใน directadmin user
rm -f /usr/local/directadmin/data/users/*/nginx.conf
cat /dev/null > /usr/local/nginx/etc/virtual.conf
/usr/local/directadmin/scripts/nginx_direct.sh all

ขั้นตอนที่ 27 สร้างไฟล์เพื่อ start/stop/restart nginx service
nano -w /etc/init.d/nginx

ขั้นตอนที่ 28 ใส่ config ด้านล่างนี้ที่ไฟล์ที่สร้างในขั้นตอนที่ 27
#!/bin/sh
#
# nginx - this script starts and stops the nginx daemin

# Taken from http://www.hikaro.com

# chkconfig: - 85 15

# description: Nginx is an HTTP(S) server, HTTP(S) reverse \

# proxy and IMAP/POP3 proxy server

# processname: nginx

# config: /usr/local/nginx/conf/nginx.conf

# pidfile: /usr/local/nginx/logs/nginx.pid

# Source function library.

. /etc/rc.d/init.d/functions

# Source networking configuration.

. /etc/sysconfig/network

# Check that networking is up.

[ "$NETWORKING" = "no" ] && exit 0

nginx="/usr/local/sbin/nginx"

prog=$(basename $nginx)

NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf"

lockfile=/var/lock/subsys/nginx

start() {

[ -x $nginx ] || exit 5

[ -f $NGINX_CONF_FILE ] || exit 6

echo -n $"Starting $prog: "

daemon $nginx -c $NGINX_CONF_FILE

retval=$?

echo

[ $retval -eq 0 ] && touch $lockfile

return $retval

}

stop() {

echo -n $"Stopping $prog: "

killproc $prog -QUIT

retval=$?

echo

[ $retval -eq 0 ] && rm -f $lockfile

return $retval

}

restart() {

configtest || return $?

stop

start

}

reload() {

configtest || return $?

echo -n $"Reloading $prog: "

killproc $nginx -HUP

RETVAL=$?

echo

}

force_reload() {

restart

}

configtest() {

$nginx -t -c $NGINX_CONF_FILE

}

rh_status() {

status $prog

}


rh_status_q() {

rh_status >/dev/null 2>&1

}


case "$1" in

start)

rh_status_q && exit 0

$1

;;

stop)

rh_status_q || exit 0

$1

;;

restart|configtest)

$1

;;

reload)

rh_status_q || exit 7

$1

;;

force-reload)

force_reload

;;

status)

rh_status

;;

condrestart|try-restart)

rh_status_q || exit 0

;;

*)

echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"

exit 2

esac


ขั้นตอนที่ 29 เปลี่ยน permission ไฟล์ถูกเรียกใช้งานได้
chmod +x /etc/init.d/nginx

ขั้นตอนที่ 30 ทำการ Restart nginx ด้วยคำสั่ง
service nginx restart

ขั้นตอนที่ 31 สั่งให้ nginx ทำงานทันทีที่ reboot server
/sbin/chkconfig nginx on

ขั้นตอนที่ 32 เพิ่ม NginX ที่ Service Monitor ของ DirectAdmin ด้วยการแก้ไขไฟล์ Service Status ของ DirectAdmin
nano -w /usr/local/directadmin/data/admin/services.status

ขั้นตอนที่ 33 เพิ่ม Code ด้านล่างนี้ไปที่ท้ายสุดของไฟล์ในขั้นตอนที่ 29
nginx=ON

ขั้นตอนที่ 34 สั่ง Restart DirectAdmin
service directadmin restart
ถึงขั้นตอนนี้ให้ทดสอบเรียกเว็บด้วย port 85 ที่เราตั้งค่าไว้ดูครับโดยเรียกผ่าน
www.domain.com:85
ถ้าไม่พบปัญหาหน้าเว็บเพี้ยน เจอ error รูปไม่แสดงผล

ก็สั่งให้ NginX ทำงานเป็น Reverse Proxy ก่อน Apache ด้วย iptables
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 85

ถ้าเกิดข้อผิดพลาดสามารถย้อคำสั่งได้ด้วย
iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 85

ถ้าไม่มีปัญหาก็สั่งบันทึก iptables ได้เลยครับ
iptables save

การติดตั้ง NginX รูปแบบนี้จะทำให้ log ของ Apache ไม่ตรงครับ IP ที่เรียกเข้ามาจะแสดงเป็น IP ของ Server ล้วนๆ
วิธีแก้ไขสามารถทำได้โดยติดตั้ง mod_rpaf ครับ ขั้นตอนติดตั้งสามารถดูจาก link ด้านล่างได้เลยครับ http://support.hostatom.com/knowledgebase.php?action=displayarticle&id=105

Was this answer helpful?

 Print this Article

Also Read

NginX basic security configuration

เป็น Security Config ที่สามารถป้องกัน bot ที่ไม่มีประโยชน์และการโจมตีบางประเภทได้ครับ...

วิธีเพิ่ม NginX ลงที่หน้าดู Service Monitor ของ Directadmin

เริ่มด้วยการแก้ไขไฟล์ Service Status ของ DirectAdmin nano -w...

วิธีสร้างไฟล์เพื่อ Start Restart หรือ Stop Service NginX

เริ่มต้นด้วยการสร้างไฟล์เพื่อ start/stop/restart nginx service เลยครับ touch /etc/init.d/nginx...

วิธีสั่งให้ NginX ทำงานทันทีเมื่อ restart เครื่อง

ก่อนทำวิธีนี้ต้องทำการสร้างไฟล์เพื่อทำการ Start Stop และ Restart NginX ก่อนนะครับจาก link นี้ครับ...